1、?与!的区别
?代表可选 ,如果为空就是nil ;!代表强制 ,如果为空就报错。这个的作用是告诉我们使用的时候很直观的去看到哪些部分可能是nil,假如有些部分报错也可以快速的定位。
2、指定构造器与便利构造器
指定构造器必须调用其直接父类的的指定构造器。
便利构造器必须调用同一类中定义的其它构造器。
便利构造器必须最终以调用一个指定构造器结束;便利构造器需要在init关键字之前放置convenience关键字,并使用空格将它们俩分开:
class Food {
var name: String init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[Unnamed]")
}
}
3、与属性方法和下标不同,重载构造器的时候不需要写override
如果你重载的构造器是一个指定构造器,你可以在子类里重载它的实现,并在自定义版本的构造器中调用父类版本的构造器。 如果你重载的构造器是一个便利构造器,你的重载过程必须通过调用同一类中提供的其它指定构造器来实现。
4、public和open的区别:open是真正的公开,public是在moudle里面可以继承可以公开,但是在moudle外是不可继承的。
5、protocol里面使用mutating修饰方法的作用是结构体实现的时候,可以在这个方法里面去修改结构体或者枚举,如果不写就不让修改。
6、尾随闭包是对于在函数参数中,闭包处于最后一个位置的情况下,可以把这个闭包放到函数调用外面,这样写起来比较简洁。
7、自动闭包是这个闭包是没有参数的默认返回闭包里面的表达式的值的一种便捷闭包。@autoclosure的目的是传入一个具体的表达式转成对应的闭包,这样既可以接一个自动闭包,还可以接收一个实际的表达式(加上@autoclosure系统会自动帮我转成闭包)。
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
print("Collected \(customerProviders.count) closures.")
// 打印 "Collected 2 closures."
for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
// 打印 "Now serving Barry!"
// 打印 "Now serving Daniella!"
这这段代码之中并不是马上去运行了customersInLine.remove(at: 0),而是把这个表达式转为一个闭包,存入到了customerProviders数组里面。
8、逃逸闭包,是值这个闭包是函数的参数,但是这闭包是在这个函数结束后去执行的一种闭包,逃逸闭包是显示持有self的。
9、lazy的属性,在多线程的情况下是无法确保是否被初始化一次。
10、struct默认的认为,方法是不允许修改属性成员的,需要加上mutating。
11、在struct和enum里面使用静态方法或者属性使用static,但是在class里面不能使用使用静态成员,所以这里只能用静态计算变量和方法,而且为了做区分使用class关键字。
12、继承的时候,重写属性的时候提供了setter也要提供getter;不能同时去重写setter和属性观察;不允许重写常量或者只读属性添加属性观察。
13、在构造器里面进行赋值是不会触发属性观察的。
14、对于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
15、指定构造器是要调用父类的指定构造器,便利构造器是要直接或者间接调用当前类的指定构造器。
16、当重写父类的指定构造器的时候需要加上override,但是如果重写便利构造器的时候就不需要加上,因为子类是无法直接调用父类的便利构造器的,所以你的子类并未对父类的构造器造成重写,所以就不加override。
17、在引用对象的生命周期内,如果它可能为nil,那么就用weak引用。反之,当你知道引用对象在初始化后永远都不会为nil就用unowned 。weak使用的时候,这个对象内存释放的时候,变量变为nil。unowned不会随着内存的释放,而置空,所以适用于非可选属性。就像是implicitly unwrapped optional(隐式可选类型),如果你能保证在使用过程中引用对象不会为nil,用unowned 。如果不能,那么就用weak 。
18、解包是对于?进行可选值包装的变量进行的解操作,直接用!来强制解包例:let temp:Residence = person.res!,如果person.res是nil,这时候就会崩溃,但是出现一个特例就是在if的条件里面使用的时候,隐式的会进行解包操作,=左边是得到解包的变量,=右边是可选值变量,所以这个帮我们去判断一个值是否真实存在的一个好办法(因为没有可以写else- - !)。?.操作得到的值如果是非nil能拿到对应的值就返回对应的值,否则这个链式就返回nil,这样在swift中基本上就可以安全的解决空值问题了,大体流程是:
在不确定是否为nil的时候用可选值来帮助代入,如果是nil方法或者值的调用也为nil,这样就可以去判断是否是nil,来进行安全的判断。
如果是确定不为nil的值时候,直接不用使用可选值就可以了,或者我很有信心我也可以设置为var person:Person!
19、在解包的过程中,如果一个可选值是nil,调用的方法或者属性是没有作用的并且如果实在赋值的情况下,john.residence?.address = createAddress() createAddress方法不会去执行,因为在运行的时候左边的residence可选值是nil所以后面的运行是没有意义的,所以不会调用=右边的方法。
20、可选链式调用,?.的到的都是对于类型的可选类型比如,?.number number是Int类型,那么?.number返回的就是Int?类型,但是在很多时候要判断方法调用是否成功,怎么办 ? 那就这么写 if person?.count() != nil {} 方法有返回值,返回的是Int?,如果没有返回值就默认的返回Void?;当然可选值的下标也是一样。总结一下,就是如果=左边,在可选值链式调用的时候,存在nil的可选值,那么就不计算=右边的表达式。
21、多级可选链式调用john.residence?.address?.street返回的类型是 street的而不是address的。john.residence?.address?.buildingIdentifier()?.hasPrefix("The")在方法上进行可选链式调用,是对方法的返回值进行的可选链式调用而不是对方法。
22、从上面几条总结的是swift的可选值这个技术要点,nil在oc里面可能是一个内存是否存在的概念,而在swift里面这个nil就是说这个可选值是nil,所以可选值简单理解为一个结构体,有值就是结构体包裹的一个值,没有值就是nil,针对的是这个结构体,因为有这个结构体存在所以说也就是结构体可以帮助你把这个对于nil的操作进行优化,而不去影响实际变量,这就是可选值的安全性。
23、any和anyobject的区别是,any代表所有类型(包括枚举结构体),anyobject只是代表对象类型。
24、协议protocol可以定义只能是类类型去实现,在:后面跟上class表示只允许类去实现。协议还可以进行组合 通过&进行组合,比如func wishHappyBirthday(to celebrator: Named & Aged){} 表示遵循这两个协议。
25、@objc代表这个协议只能是oc代码可以访问的。optional可选协议里面的方法,说明这个方法可以不实现,就和oc里面的@option一个意思。
26、协议泛型化的时候使用associatedtype来占位将要实现的类中所指定的泛型类型;在实现的泛型扩展的协议的实现类里面使用typealias来指定泛型类型。就类似java接口泛型化一样,只不过java在实现的时候指定了实现的泛型类型,而在swift里面使用typealias来指定。
网友评论