swift 学习笔记

渲染:

1 当前屏幕渲染:在GPU的当前屏幕缓冲区中进行的渲染

2 离屏渲染:在GPU当前屏幕缓冲区外另建缓冲区渲染

3 CPU渲染:如重写drawRect,用到core graphics技术绘图(特殊的离屏渲染)

.. 2比1效率低,因为要新建缓冲区,要切换缓冲区的上下文

.. 3比1,2,缺点是CUP的浮点运算能力比GPU差

.. 尽量用1,对于简单的效果,3又比2强,因为运算能力的略势比不上创建缓冲区和切换上下文的消耗

/******* Array ***********/

.. Array是一组相同类型的变量的有序集合(类型安全)

Array的创建方式:加Array关键字:

1, var a1 = Array(count:5, repeatedValue:8) /let a1 = Array(arrayLiteral: 1, 2, 3)

2, var a2 = Array(arrayLiteral: "1","6","99")

无Array关键字:

4, var a3 = [Int](count:3, repeatedValue:6) /var a3 = [Int](arrayLiteral:1, 2, 4)// 使用构造函数限制数组元素个数并且指定默认值

5, var a4: [String] = ["x", "y"]

6, var a5 = ["x", "y"]

7, var a6 = [Int]() //创建一个空数组,以后可通过 a6 = []赋值

综上,基于switft的习惯(":" 后指定类型)和执行的效率(不需要类型推断)考虑,建议用第5种

操作:1 a5.isEmpty和(a5.count == 0)等价,判断是否为空

2 a5.append(”x”)往尾部添加元素和 a5 += “x”等价

3 += 的方式还可以加另外一个Array

4 通过下标访问 var value = a5[0], 赋值 a5[0] = value5 a5[2…4] = [“1”,”2”,”3”],如何后面的个数小于前面的下标集合,表示有删除

/******* Set ***********/

.. Set是一组相同类型的变量的无序集合(类型安全)

.. 创建的时候要加Set,不然可能被当成ArraySet的

创建方式:

1 var s1: Set= [“x”, “y”] (等价于 var s1 : Set(String) = 【‘x’, 'y'】)/var s1: Set = [1, 2]

2 var s2 = Set() //创建一个空set,再赋值  //声明s2后在 s2 = [“2”, “1”]没问题,但是var s3 = [“8”], s2 = s3则是错误的,s3是个数组

两个Set操作:

1 intersect(_:)交集 根据两个集合中都包含的值创建的一个新的集合

2 exclusiveOr(_:) 去掉重复再合并 根据只在一个集合中但不在两个集合中的值创建一个新的集合

3 union(_:) 并集 根据两个集合的值创建一个新的集合

4 subtract(_:) 去掉重复求剩余 根据不在该集合中的值创建一个新的集合

实例:

varset1 :Set = [1,2,3,4,5,6]

varset2 :Set = [5,6,7,8,9,10]

varset3 =set1.intersect(set2) // 5, 6

varset4 =set1.exclusiveOr(set2) // 10, 2, 4, 9, 7, 3, 1, 8

varset5 =set1.union(set2) // 10, 2, 4, 9, 5, 6, 7, 3, 1, 8

varset6 =set1.subtract(set2) // 2, 3, 1, 4

varset7 =set2.subtract(set1) // 7, 10, 9, 8

..参数为另一个Set/******* Dictionary ***********/

.. Dictionary用来存储一组相同类型且无序的值,每个值都关联一个唯一的关键字(key)(类型安全)

.. Dictionary关键字和元素的类型必须显式或隐式的指定

.. Dictionary,KeyType必须是可离散化(提供一个方法来唯一的表示自己)的类型,如String,Int,Double,Bool都是可离散化的

Dictionary的创建:

1 var k1: Dictionary= [“k1”: “x”, “k2”: “yy”] //显式 

2 var k2 = [2 : "xx", 3 : "yy"] //隐式 

3 var k3 = Dictionary() //创建一个空字典

操作:

1 k2[2] = "zz”;k1[“k1”] = "zz” //通过下标(key)修改值

2 k2[2] = nil //通过下标删除一个元素

3 k2 = [:] //清空一个字典所有元素

4 updateValue(value:”xx”, forKey: “k3”) //如果k3存在,返回旧值,并修改旧值,如果k3不存在,添加并返回nil

实例:

vardic :Dictionary= [1:"i",2:"love",3:"free"]

vardic1 =dic.updateValue("maomao", forKey:3) // "fress"

dic // [1: "i", 2 : "love", 3:"maomao"], 顺序不定

vardic2 =dic.updateValue("haha", forKey:4)  // nil

dic // [1: "i", 2 : "love", 3:"maomao", 4 "haha"], 顺序不定

/******* Tuple ***********/

.. 开发过程中,有时想临时组织一个数据类型,它没有那么复杂但定义又比较麻烦,此时无需使用结构体和类,使用元组Tuple的

创建:

1 var tPoint = (x:50, y:100) /var tPoint: (int, int, int, float) = (0, 0, 100, 11.5) //如何指定了类型,就不要指定元素名称

2 var tSize = (width:100, 50) 

操作:

1 func request()->(code:Int,description:String){    return (404,"not found")}// 借助元组实现函数的多返回值

2 元组可以下标访问 tPoint.x == tPoint.0

/******* 可选类型 ***********/

.. 一个变量或常量可能有值也可能没有值就可以设置为可选类型

.. swift是强类型语言,在声明变量的时候没有赋值,不会默认设置初始值

.. 可选类型的本质就是此类型内存存储部分分为“Some”和“None“两部分,有值就放到“Some”中,没值就是“None“

.. 强制解包就是读取的“Some”中的内容设置方式:var x: Float? //没默认值则为nil

应用:

1 var y: Float = 2 //必须赋初值,否则编译不过

2 var z = x + y //错误,x,y类型不一致,要对x强制解包 var z = x! + y

3 var age = “32” var ageInt = age.Int(age) //ageInt是可选类型,因为Int()不能保证一定能转化为Int类型

4 对3中的ageInt,可以通过可选绑定不解包,下面如果走yes,newAge已经不是可选类型了 

 if let newAge = ageInt{var zz = newAge + 10  }  else{  }

5 隐式可选解析类型(如果一个可选类型从第一次赋值后就能保证有值,那么就不需要解包) 

 var age: Int! = 0; age = 29; 

 var newAge: Int = age //不需要解包,程序自动解包/******* 运算符 ***********/

1 for i in 1...5 { //闭区间运算符...(从1到5,包含5)  

  print("i=\(i)")}

2 for i in 1..<5{ //半开区间运算符..<(从1到4)  

  print("i=\(i)")}

3 var range="a"..."z";   range.contains() //是否在a到z之间

4 溢出运算符: var a = UInt8.max; var b: Uint = a + 1,b溢出报错  应该是 var b: UInt8 = a &+ 1 结果为:0,类似的还有&-、&*、&/  溢出运算符的原理其实很简单,例如对于UInt8,如果8位均为1则十进制表示是255,但是当加1之后则变成了9位“100000000”,  出现了溢出但是UInt8本身值只能存储8位,所以取后面8位就变成了“00000000”,十进制表示就是0

/******* 控制流 ***********/

1 let b = “b” 

 switch b{  

case “a”,”b”: //支持一个case多个模式匹配   

 print("b=a or b=b")   

 fallthrough //一个case完成后会自动break,不会隐式贯穿,要贯穿加fallthrough关键字

  case "c","d","e","f":   

 print("b in (c,d,e,f)") 

 default:   

 println("b=g")  } 

 如果b是数值类型,还可以区间匹配:

case 9…20:

2 如果case包含所有情况,不需要加default:

3 对于元组,可以用_忽略一个值  var d = (x:900,y:0)  switch d{  case (0,0):    print("d in (0,0)")  case (_,0): //忽略x值匹配    print("d in y")

4 标签,类似goto语句  var a=5  whileLoop:  while --a>0 {    for var i=0;iVoid或->())或写Void,Void的本质就是空元组()

func sum(num1:Int,num2:Int,_ num3:Int)->Int{

return num1 + num2

}

sum(1, num2: 2, 66) //从第二个参数开始,调用的时候要加标签(局部参数作为外部参数),否则函数定义时加 _ 修饰

2  .. 函数参数名分为局部参数名和外部参数名,有外部参数名,调用的时候必须加上,一个有意义的外部参数名可以节省开发成本

func split(string a:String,seperator b:Character)->[String]{ //

return split(a, maxSplit: Int.max, allowEmptySlices: false, isSeparator: {$0==b})

}

split(string: "hello,world,!", seperator: ",")

3 可变参数

.. 一个函数最多一个可变参数且为最后一个参数,strings参数在内部是一个【String】,对外部是不定个数的String参数

func joinStr(seperator:Character=",",strings:String...)->String{

for i in 0 ..< strings.count //for var i=0; i < strings.count; ++i{ //c形式的for语句弃用了

//…

}

//…

}

joinStr(“,”,strings:”s1”,”s2”,”s3 )

4 参数类型

.. 参数默认是常量,除非声明为var,,C语言默认是变量,这个变量对外无效函数执行完就消失

func sum2(var num1:Int,num2:Int)->Int{

num1 = num1 + num2

return num1

}

5 输入输出

.. 通过输入输出参数可以在函数内部修改函数外部的变量,注意调用时不能是常量和字面量

func swap(inout a:Int ,inout b:Int){

a=a+b

b=a-b

a=a-b

}

var a=1,b=2

swap(&a, &b) //调用时参数加上“&”符号

6 函数也是类型

.. 可以赋值,自动推断类型,但是不同类型的函数不能直接赋值

var sum3 = sum

sum3(1, num2:2, 7) //结果:10

.. 可以作为返回值,可以嵌套

func fn()->(Int,Int)->Int{

func minus(a:Int,b:Int)->Int{

return a-b

}

return minus;

}

var minus = fn()

.. 函数可以作为参数

//函数作为参数

func caculate(num1:Int,num2:Int,fn:(Int,Int)->Int)->Int{

return fn(num1,num2)

}

caculate(1, 2, sum) //结果:3

caculate(1,2, minus) //结果:-1

/******* 闭包 ***********/

.. 就是一个函数代码块

.. 特点就是可以捕获和存储上下文中的常量和变量的引用,即使这些常量和变量在原作用域已经被销毁了,在代码块中仍能使用

.. 全局函数和嵌套函数也是一种闭包,全局函数不会捕获任何常量和变量,嵌套函数可以捕获所在函数的常量和变量

.. 闭包更多的是指闭包表达式,也就是没有函数名称的情况,也叫匿名闭包

定义:

{(parameters)->returnType in

statements

}

尾随闭包:

.. 一个函数最后一个参数是一个函数类型的参数或者说闭包表达式,则可以将此参数写在函数括号之后

尾随闭包的简写演进过程(调用时简写):

func sum(num1:Int,num2:Int)->Int{

return num1 + num2

}

func minus(num1: Int, num2: Int)->Int{

return num1 - num2;

}

func caculation(num1: Int, num2: Int, fn: (Int, Int)->Int)->Int{

return fn(num1, num2);

}

var (a, b) = (2, 3)

1 利用闭包表达式简化闭包函数

caculation(2, num2: 4, fn: {(num1:Int, num2:Int)->Int in

return num1 - num2

})// -1

2 简化形式,根据上下文推断类型并对于单表达式闭包(闭包内只有一行语句)可以隐藏return关键字

caculation(a, num2:b, fn:{num1, num2 in

num1 - num2

})// -1

3 再次简化,使用参数名缩写以省略参数,in关键字也省略

caculation(2, num2: 4, fn: {

$0 + $1

}// 6

4 最后一个参数是闭包表达式可以写在括号之后,,如果这个函数只有一个闭包表达式参数时,可以连同括号一块省略

caculate(a, b){

$0 - $1

}// -1

捕获变量或常量:

func add()->()->Int{

var total=0

var step=1

func fn()->Int{

total+=step

step += 1

return total

}

return fn

}

var a = add()

a()// 1

a()// 3 a保存了total,step的副本

.. add()返回一个无参数,返回一个Int型的函数,fn捕获了total和step,执行add()后total和step就被释放了,但是fn

.. 捕获了二者的副本,所有fn会随着两个变量的副本一起被存储

var b = add()

b()// 1

.. 说明a, b单独保存了total,step的副本

var c=b

c()// 3

.. 说明闭包是引用类型,或者说函数是引用类型,否则是1

.. 总结:swift会自动决定捕获变量或常量的副本的拷贝类型(值拷贝或者引用拷贝)而不需要开发者关心,被捕获的变量或常量的内存

.. 管理也是有swift负责,例如当a不使用了那么fn捕获的两个变量也就释放了

类:

Swift中一个类如果不继承于任何其他基类(ObjC通常必须继承于NSObject),那么此类本身就是一个基类类的定义方式如下,

classPerson{

//定义属性

var name:String

var height=0.0

var age = 0

var info:String

       get{

              return name.append(String(height))

       }

      set{

              name =  newValue // newValue就是新的值,也可以自己设置新的值,不用newValue,如,set(myValue){},这时myValue就是新值

     }

//类型属性

static var skin:Array{ // 使用方式只能是,类名.skin 方式

return["yellow","white","black"];

}

lazy var car = Car() // 一个Car类对象属性的懒加载

//构造器方法,注意如果不编写构造方法默认会自动创建一个无参构造方法

init(name:String){

self.name=name

}

//便利构造方法,通过调用指定构造方法、提供默认值来简化构造方法实现

convenience init(name:String){

     self.init(name:name,height:0.0,age:0)

}

//实例方法

func modifyInfoWithAge(age:Int,height:Double){

self.age=age

self.height=height

}

//通过final声明,子类无法重写

final func sayHello(){

println("hello world.")

}

//类型方法

class func showClassName(){

println("Class name is \"Person\"")

}

//定义方法

func showMessage(){

println("name=\(name),height=\(height)")

}

//析构方法,在对象被释放时调用,类似于ObjC的dealloc,注意此函数没有括号,没有参数,无法直接调用

deinit{

print("deinit...")

}

}

使用如下,

var p=Person(name:"adrian")

p.height=168.0

p.showMessage()//结果:name=adrian,height=168.0

//类是引用类型

varp2=p

p2.name="zeo"

if p===p2 {

//“===”表示等价于,这里不能使用等于“==”(等于用于比较值相等,p和p2是不同的值,只是指向的对象相同)

      //p等价于p2,二者指向同一个对象

}


Swift中的属性分为两种:存储属性(用于类、结构体)和计算属性(用于类、结构体、枚举),并且在Swift中并不强调成员变量的概念。无论从概念上还是定义方式上来看存储属性更像其他语言中的成员变量,但是不同的是可以控制读写操作、通过属性监视器来属性的变化以及快速实现懒加载功能(属性的懒加载,第一次访问才会计算初始值,在Swift中懒加载的属性不一定就是对象类型,也可以是基本类型)。

需要注意的是:

1,计算属性并不直接存储一个值,而是提供getter来获取一个值,或者利用setter来间接设置其他属性;

2,lazy属性必须有初始值,必须是变量不能是常量(因为常量在构造完成之前就已经确定了值);

3,在构造方法之前存储属性必须有值,无论是变量属性(var修饰)还是常量属性(let修饰)这个值既可以在属性创建时指定也可以在构造方法内指定;

计算属性可以在setter中看值的变化,存储属性不能添加setter方法,但是可以用属性监视器看值的变化,newValue和oldValue也是系统的默认参数,也可以自己定义:

classAccount {

//注意设置默认值0.0时监视器不会被调用

varbalance:Double=0.0{

willSet{

self.balance=2.0

//注意newValue可以使用自定义值,并且在属性监视器内部调用属性不会引起监视器循环调用,注意此时修改balance的值没有用

print("willSet,newValue=\(newValue),value=\(self.balance)") // willSet,newValue=4.0,value=2.0\n

}

didSet{

self.balance=3.0

//注意oldValue可以使用自定义值,并且在属性监视器内部调用属性不会引起监视器循环调用,注意此时修改balance的值将作为最终结果

print("didSet,oldValue=\(oldValue),value=\(self.balance)") // didSet,oldValue=0.0,value=3.0\n

}

}

}

varaccout =Account()

accout.balance=4 // 调用这句是,打印如注释

print("balance =\(accout.balance)") // balance = 3.0\n

存储属性的默认值设置不会引起属性监视器的调用(另外在构造方法中赋值也不会引起属性监视器调用),只有在外部设置存储属性才会引起属性监视器调用;
存储属性的属性监视器willSet、didSet内可以直接访问属性,但是在计算属性的get、set方法中不能直接访问计算属性,否则会引起循环调用;在didSet中可以修改属性的值,这个值将作为最终值(在willSet中无法修改);

除构造方法、析构方法外的其他方法的参数默认除了第一个参数是局部参数,从第二个参数开始既是局部参数又是外部参数(这种方式和ObjC的调用方式很类似,当然,可以使用“#”将第一个参数同时声明为外部参数名,也可以使用“_”将其他参数设置为非外部参数名)。但是,对于函数,默认情况下只有默认参数既是局部参数又是外部参数,其他参数都是局部参数。(也就是为什么在playground中,对于没有外部参数的方法,调用还是要这样,caculate(aa, num2:bb, fn:sum))

构造方法的所有参数默认情况下既是外部参数又是局部参数;

Swift中的构造方法分为“指定构造方法”和“便利构造方法(convenience)”,指定构造方法是主要的构造方法,负责初始化所有存储属性,而便利构造方法是辅助构造方法,它通过调用指定构造方法并指定默认值的方式来简化多个构造方法的定义,但是在一个类中至少有一个指定构造方法。

下标脚本:

定义和使用方式如下,

classRecord {

//定义属性,假设store是Record内部的存储结构

varstore:[String:String]

init(data:[String:String]){

self.store=data

}

//下标脚本(注意也可以实现只有getter的只读下标脚本)

subscript(index:Int)->String{

get{

letkey=Array(self.store.keys)[index]

returnself.store[key]!

}

set{

letkey=Array(self.store.keys)[index]

self.store[key]=newValue//newValue参数名可以像属性一样重新自定义

}

}

//下标脚本(重载)

subscript(key:String)->String{

get{

returnstore[key]!

}

set{

store[key]=newValue

}

}

}

varrecode =Record(data:["name":"adrian","age":"33"])

varname =recode[1]

recode["age"]="18"

类的继承:

class Student:Person{

//重写属性监视器

override var firstName:String{

willSet{

println("oldValue=\(firstName)")

}

didSet{

println("newValue=\(firstName)")

}

}

var score:Double

//子类指定构造方法一定要调用父类构造方法

//并且必须在子类存储属性初始化之后调用父类构造方法

init(firstName:String,lastName:String,score:Double){

self.score=score

super.init(firstName:firstName,lastName:lastName)

}

convenience init(){

self.init(firstName:"",lastName:"",score:0)

}

//将只读属性重写成了可写属性

override var fullName:String{

get{

return super.fullName;

}

set{

letarray=split(newValue,maxSplit:Int.max,allowEmptySlices:false,isSeparator: { $0=="."})

if array.count==2{

firstName=array[0]

lastName=array[1]

}

}

}

//重写方法

override func showMessage() {

print("name=\(fullName),age=\(age),score=\(score)")

}

}

实例化:

var p=Student()

p.firstName="maomao"

为了保证存储属性在构造方法执行完之前都有值,要注意如下规则:

1,子类的指定构造方法必须调用父类构造方法,并确保调用发生在子类存储属性初始化之后。而且指定构造方法不能调用同一个类中的其他指定构造方法;

2,便利构造方法必须调用同一个类中的其他指定构造方法(可以是指定构造方法或者便利构造方法),不能直接调用父类构造方法(用以保证最终以指定构造方法结束);

3,如果父类仅有一个无参构造方法(不管是否包含便利构造方法),子类的构造方法默认就会自动调用父类的无参构造方法(这种情况下可以不用手动调用);

4,常量属性必须默认指定初始值或者在当前类的构造方法中初始化,不能在子类构造方法中初始化;

扩展的定义和使用:

classPerson {

varfirstName:String,lastName:String

varage:Int=0

varfullName:String{

get{

returnfirstName+" "+lastName

}

}

init(firstName:String,lastName:String){

self.firstName=firstName

self.lastName=lastName

}

funcshowMessage(){

print("name=\(fullName),age=\(age)")

}

}

extensionPerson{

//只能扩展便利构造方法,不能扩展指定构造方法

convenienceinit(){

self.init(firstName:"",lastName:"")

}

//只能扩展计算属性,无法扩展存储属性

varpersonInfo:String{

return"firstName=\(firstName),lastName=\(lastName),age=\(age)";

}

//扩展实例方法

funcsayHello(){

print("hello world.")

}

//嵌套类型

enumSkinColor{

caseYellow,White,Black

}

//扩展类型方法

class funcskin()->[SkinColor]{// class ,static都行,用class是类型方法,用static是静态方法

return[.Yellow,.White,.Black]

}

}

varp =Person()

p.firstName="ran"

p.lastName="adrian"

p.age=18

p.sayHello()

p.personInfo

Person.skin()

结构体:

结构体的定义其实跟class差不多,只是关键字不是class,而是struct,同时,内部的类型方法的定义用static。

所有结构体默认生成一个全员逐一构造函数,一旦自定义构造方法,这个默认构造方法将不会自动生成。由于结构体(包括枚举)是值类型所以赋值、参数传递时值会被拷贝(所以下面的实例中p2修改后p并未修改,但是如果是类则情况不同)。

类的类型方法使用class修饰(以便子类可以重写),而结构体、枚举的类型方法使用static修饰(补充:类方法也可以使用static修饰,但是不是类型方法而是静态方法;另外类的存储属性如果是类型属性使用static修饰,而类中的计算属性如果是类型属性使用class修饰以便可以被子类重写;换句话说class作为“类型范围作用域”来理解时只有在类中定义类型方法或者类型计算属性时使用,其他情况使用static修饰[包括结构体、枚举、协议和类型存储属性]);

枚举:

枚举的定义和使用如下,

//注意Swift中的枚举默认并没有对应的整形值,case用来定义一行新的成员,也可以将多个值定义到同一行使用逗号分隔,例如:case Spring,Summer,Autumn,Winter

enumSeason{

caseSpring

caseSummer

caseAutumn

caseWinter

}

vars=Season.Spring

//一旦确定了枚举类型,赋值时可以去掉类型实现简写

s= .Summer

switchs{

case.Spring://由于Swift的自动推断,这里仍然可以不指明类型

println("spring")

case.Summer:

println("summer")

case.Autumn:

println("autumn")

default:

println("winter")

}

当然,枚举也可以指定一个值和枚举成员对应,

//指定原始值(这里定义成了整形)

enumSeason:Int{

caseSpring=10//其他值会默认递增,例如Summer默认为11,如果此处也不指定值会从0开始依次递增

caseSummer

caseAutumn

caseWinter

}

varsummer=Season.Summer

//使用rawValue访问原始值

println("summer=\(summer),rawValue=\(summer.rawValue)")

如果一个枚举类型能够和一些其他类型的数据一起存储起来往往会很有用,因为这可以让你存储枚举类型之外的信息(类似于其他语言中对象的tag属性,但是又多了灵活性),这在Swift中称为枚举类型相关值。要注意的是相关值并不是原始值,原始值需要事先存储并且只能是同一种类型,但是相关值只有创建一个基于枚举的变量或者常量时才会指定,并且类型可以不同(原始值更像其他语言的枚举类型):

//相关值

enumColor{

caseRGB(String)//注意为了方便演示这里没有定义成三个Int类型(例如: RGB(Int,Int,Int))而使用16进制字符串形式

caseCMYK(Float,Float,Float,Float)

caseHSB(Int,Int,Int)

}

varred=Color.RGB("#FF0000")

vargreen=Color.CMYK(0.61,0.0,1.0,0.0)

varblue=Color.HSB(240,100,100)

枚举也有一些类型和结构体的特性,例如计算属性(包括类型属性,枚举只能定义计算属性不能定义存储属性,存储属性只能应用于类和结构体)、构造方法(其实上面使用原始值创建枚举的例子就是一个构造方法)、方法(实例方法、类型方法)、下标脚本 ,

enumSeason:Int{

caseSpring=0,Summer,Autumn,Winter

//定义计算属性

vartag:Int{

returnself.rawValue

}

//类型属性

staticvarenumName:String{

return"Season"

}

//    //定义构造方法,注意在枚举的构造函数中则必须保证self有值(正如类的构造方法必须保证其存储属性有值一样)

//    init(prefix:String){

//        switch prefix.lowercaseString {

//            case "sp":

//                self = .Spring

//            case "su":

//                self = .Summer

//            case "au":

//                self = .Autumn

//            default:

//                self = .Winter

//        }

//    }

//其实上面的构造器有些不合理,那就是default就是Winter,事实上这类构造器可能传任何参数,此时可以使用可失败构造函数来解决

//可失败构造函数返回nil(尽管Swift中构造函数是不返回值的,但是此时约定返回nil代表构造失败)

init?(prefix:String){

switchprefix.lowercaseString{

case"sp":

self= .Spring

case"su":

self= .Summer

case"au":

self= .Autumn

case"wi":

self= .Winter

default:

returnnil

}

}

//定义实例方法

funcshowMessage(){

println("rowValue=\(self.rawValue)")

}

//定义类型方法

staticfuncshowEnumName(){

println("Enum name is \"Season\"")

}

}

varsummer=Season.Summer

println(summer.tag)//结果:1

println(Season.enumName)//结果:Season

Season.showEnumName()//结果:Enum name is "Season"

summer.showMessage()//结果:rowValue=1

ifletspring=Season(prefix:"au") {//可选绑定,构造函数返回值可能为nil

println(spring.tag)//结果:2

}

泛型:

泛型可以让你根据需求使用一种抽象类型来完成代码定义,在使用时才真正知道其具体类型。这样一来就好像在定义时使用一个占位符做一个模板,实际调用时再进行模板套用,所以在C++中也称为“模板”。泛型在Swift中被广泛应用,上面介绍的Array<>、Dictionary<>事实上都是泛型的应用。通过下面的例子简单看一下泛型参数和泛型类型的使用,

结构体中使用,

struct Stack{

varstore:[T] = []

mutatingfuncpush(item:T){

store.append(item);

}

mutatingfuncpop()->T{

returnstore.removeLast()

}

}

var s =Stack()

s.push(1)

s.push(2)

s.pop()//返回2

//扩展泛型类型

extension Stack{

var top:T?{

return store.last

}

}

s.top // 1

var ss =Stack();

ss.push("adrian")

ss.push("zeo")

ss.pop()//返回“zeo”

方法中使用,

func isEqual(a:T, b:T)->Bool{

returna==b

}

vara:Int=1, b:Int=2

varequal =isEqual(a,b:b)

varc:String="maomao", d:String="maomao"

varequal1 =isEqual(c, b:d)

关于协议的东西将会立即补上。

笔记中的例子基本都是在playGround中验证过的,对swift感兴趣的同学,推荐移步到这个博客学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容