强制解包看,斯维夫特中的可选类型

不晓得大家有未有开掘,在1个 Objective-C 和 Swift 混编的 App
中,当把二个 OC 中的参数转到 Swift 时,Swift会自动把这一个变量进行强制解包。比方,我在 OC 中定义那样二个变量:

澳门葡京备用网址 1

不理解大家有未有发掘,在三个 Objective-C 和 Swift 混编的 App
中,当把四个 OC 中的参数转到 Swift 时,Swift会自动把那个变量举行强制解包。举个例子,作者在 OC 中定义那样一个变量:

原创小说。谈一谈对斯维夫特中可选类型的掌握与事实上应用,如有错误,望读者指正,多谢!

 1 @property (nonatomic, copy) NSString *foo; 

不明了大家有未有发掘,在二个 Objective-C 和 斯维夫特 混编的 App
中,当把一个 OC 中的参数转到 斯威夫特 时,Swift会自动把那些变量举办强制解包。比如,小编在 OC 中定义那样2个变量:

 1 @property (nonatomic, copy) NSString *foo; 

它转成 Swift 就产生了这么:

@property (nonatomic, copy) NSString *foo;

它转成 斯威夫特 就成为了这样:

如何是可选类型?

可选类型是一种用来强核实1个常量或变量是或不是具备值的语法。可选类型的存在让Swift成为1种强类型语法

var foo: String!

它转成 斯维夫特 就成为了那样:

var foo: String!

怎么选拔可选类型?

这么看上去合理。Swift 中有 String? 和 String! 三种情势,但 OC 中并未有NSString? 和 NSString! ,当 Swift 不恐怕区分 OC 中的变量是否 nil
的时候,1律强行转会为非空参数。那样设计展现了 Swift强安全性语言的风味。

var foo: String!

那样看起来合理。斯维夫特 中有 String? 和 String! 几种情势,但 OC 中平昔不
NSString? 和 NSString! ,当 Swift 无法区分 OC 中的变量是还是不是 nil
的时候,1律强行转会为非空参数。那样设计体现了 Swift强安全性语言的特征。

0.可选类型的意义

可选类型可用以1个目标的起头值的景况。

出于在斯威夫特中定义一个目的时,必须领悟指明其开头值,无法为空值。如若不想在概念时予以开头值,唯一的法子正是将其定义为可选类型

亟待小心的是:

可选类型中的nil与OC中的nil代表的含义是例外的。
OC中的nil表示空指针,代表变量不指向任何内部存款和储蓄器地址。OC中对空指针发送音信不会生出别的工作
斯威夫特中nil也是一种档案的次序,表示变量或常量的值缺失。在斯维夫特中动用三个值缺失的对象,将会变成程序崩溃

而是此时难题来了。大家再次回到上文中的例证,倘若 OC 中对 foo强制解包看,斯维夫特中的可选类型。的使用如下:

如此那般看上去合理。Swift 中有 String? 和 String! 两种方式,但 OC 中一直不
NSString? 和 NSString! ,当 斯维夫特 不可能区分 OC 中的变量是否 nil
的时候,1律强行转会为非空参数。
诸如此类设计展现了 斯维夫特强安全性语言的特征。

可是此时难题来了。大家回来上文中的事例,假诺 OC 中对 foo的应用如下:

壹.概念可选类型
  • 好端端写法

var name : Optional<String>
  • 敏捷写法(常用)

var name : String? 

</br>

 1 @property (nonatomic, copy) NSString *foo;
 2 
 3 - (void)secretFunc {  
 4   // 一些诡异复杂的操作
 5   ...  
 6   self.foo = nil;
 7 }
 8 // 然后我们在 Swift 中这样调用:
 9 
10 func init() {
11   objectiveCObject.secretFunc()
12 }func calcLen() -> Int {  
13 
14   return objectiveCObject.foo.characters.count
15 
16 }

只是此时难点来了。我们回来上文中的事例,要是 OC 中对 foo的运用如下:

 1 @property (nonatomic, copy) NSString *foo;
 2 
 3 - (void)secretFunc {  
 4   // 一些诡异复杂的操作
 5   ...  
 6   self.foo = nil;
 7 }
 8 // 然后我们在 Swift 中这样调用:
 9 
10 func init() {
11   objectiveCObject.secretFunc()
12 }func calcLen() -> Int {  
13 
14   return objectiveCObject.foo.characters.count
15 
16 }
二.从可选类型中取值
  • 强制解析:
    在可选类型后增加一个”!”就能够得到可选类型中的值

print(name!)

强制解析是急不可待操作,借使目标的实际值为nil,解包会导致crash。所以借使不可能鲜明目的自然有值,不建议直接动用强制解析,而是先进行2回校验:

if name != nil {
    print(name!)
}
  • 可选绑定(常用)
    写法1:

if let tempName = name {
    print(tempName)
}

本条语句会先判定name是还是不是有值,假若未有值,则剖断标准为false,不会施行{}中的语句。
假设name有值,则系统会对其进展解包,将解包后的结果赋值给tempName
写法2:

if let name = name {
    print(name)
}

运用了变量功能域的法则,用一时变量覆盖了原来的变量。本质上与写法壹一样

  • 经过guard的点子开始展览可选绑定(常用)
    鉴于在斯威夫特中除了if能够张开标准化判别外,还可应用guard进行推断。因此等同可以使用guard语句进行可选绑定:

guard let name = name else {
  return
}

guard校验与if类似,若是name有值,则张开赋值,跳过else中的代码。假设name为nil,则只需else中的语句,不再接续往下执行

  • 空合运算符(摘自 <<The Swift Programming
    Language>>汉语翻译)
    空合运算符即??,使用示比如下:

realName = name ?? ""

意味着只要name有值时则将name解析并赋值给realName,不但是将运算符后的暗中认可值(即空字符串)赋值给realName

</br>
</br>

地点那段 Swift代码实行到calcLen()时会崩溃,原因是fooinit()中早就被设成了
nil,而foo在 Swift 中是 foo!。也便是说,因为 斯维夫特 对 OC
变量的强转,导致了先后的倒台。那是叁个很轻便忽视的题材,因为强转的时候,Xcode
不会付给任何的警告、报错或是提示。而作者辈作为开采者,很轻巧忽视那样的不当,导致
runtime 的时候一向崩溃。

@property (nonatomic, copy) NSString *foo;- secretFunc { // 一些诡异复杂的操作 ... self.foo = nil;}

地点那段 斯维夫特代码实行到calcLen()时会崩溃,原因是fooinit()中已经被设成了
nil,而foo在 Swift 中是 foo!。也便是说,因为 Swift 对 OC
变量的强转,导致了程序的夭亡。那是三个很轻便忽视的标题,因为强转的时候,Xcode
不会付出任何的告诫、报错或是提醒。而作者辈作为开拓者,很轻巧忽视这样的错误,导致
runtime 的时候一向崩溃。

“!”和”?”运算符的意思

在Swift中日常能够看看那五个运算符,那么他们究竟有啥含义呢?

本着那种意况,我们来谈谈上面多个难题。

下一场我们在 斯威夫特 中那样调用:

针对那种情景,我们来谈谈上面几个难点。

一.?

壹.用在3目运算符中,表示原则选拔,举例:

let isAdult: Bool = (age > 18) ? true : false

当?以前的尺码为真时,实施问号后的话语,不然推行冒号后的口舌

二.用在概念二个变量时,用来表示该变量为可选类型,比方:

var name: String?

之后给那么些变量赋值时,能够赋多个规定有值的String,也可以赋值为nil

三.用在说话中,依据变量的值是或不是为nil决定是还是不是继续试行代码,比方:

var person: Person?
person?.name.firstName = "Wang"

假设person的实际值为nil,则整句代码都不会进行。假若person不为nil,则会执行代码,对firstName赋值

肆.在赋值时,使用”??”来开始展览典型化判定,赋暗许值,比方:

var age: Int = person.age ?? "10"

假设person的age值不为nil,则会给变量age赋值。假使为nil,则将暗许值拾赋值给age

伍.跟在as后,表示可选的类型调换,比如:

let str: String? = "abc"        
let nsStr = str as? NSString

那句代码将会把str转化为三个NSString?的靶子。nsStr的档案的次序是NSString?,就能够选类型。
as?常用在向下转型,也正是将子类的对象转化为父类对象。

陆.用在实行协议中的可选方法时。因为遵照协议的代理不必然落成了可选方法,所以在调用可选方法时,供给在章程名后加上2个?。要是实现了艺术,则会调用,不然不实践

“?”的用法基本就这么些了,假使有遗漏的,迎接补充。

  • Q: 为啥 Swift 要将 OC 中的变量如foo转为foo!而不是foo?
func init() { objectiveCObject.secretFunc()}func calcLen() -> Int { return objectiveCObject.foo.characters.count}
  • Q: 为啥 Swift 要将 OC 中的变量如foo转为foo!而不是foo?
二.!

那是二个有争议的话题。小编个人感到强制解包的艺术会督促开采者思索变量是不是为
nil 的主题材料。在 OC 时代,评释变量一般不会思量是不是为空的难题;而在 斯威夫特时期,因为其是壹门强安全性的言语,在变量定义时,必须明确变量是或不是为空。一般定义为非空有二种以下情势:

地点那段 Swift代码实施到calcLen()时会崩溃,原因是fooinit()中早就被设成了
nil,而foo在 Swift 中是 foo!。也等于说,因为 斯威夫特 对 OC
变量的强转,导致了先后的崩溃。那是2个很轻便忽略的标题,因为强转的时候,Xcode
不会交到任何的警示、报错或是提示。
而大家作为开荒者,很轻易忽视那样的不当,导致
runtime 的时候向来崩溃。

那是二个有争辩的话题。笔者个人感觉强制解包的格局会督促开拓者思虑变量是或不是为
nil 的难题。在 OC 时期,表明变量一般不会设想是不是为空的标题;而在 斯维夫特时期,因为其是一门强安全性的语言,在变量定义时,必须鲜明变量是或不是为空。一般定义为非空有三种以下格局:

未完待续!
1 // force unwrapping
2 var foo = "Hello"
3 // implicitly unwrapping
4 var foo: String!

针对那种气象,我们来谈谈上边四个难点。

1 // force unwrapping
2 var foo = "Hello"
3 // implicitly unwrapping
4 var foo: String!

前端依照伊始值强制解包,定义 foo 为非空变量;后者则平素证明 foo
为非空变量。

  • Q: 为何 斯威夫特 要将 OC 中的变量如foo转为foo!而不是foo?

前者依据早先值强制解包,定义 foo 为非空变量;后者则直接表达 foo
为非空变量。

无论哪一种情状,开荒者会从一起先就合计管理 nil
时的情事,并在承袭开辟中央直机关接留心。所以从foo转化为foo!,你就会妄想 OC
中代码是或不是也要拍卖
nil 的动静;而壹旦转会为foo?,nil 也无所谓,而实际恐怕并不是那般,nil
的奇特别情报况考虑会直接忽略,开辟中的隐患一向留存,同时也不相符 Swift强安全性的设计思路。

这是1个有争执的话题。笔者个人以为强制解包的法门会督促开垦者思考变量是还是不是为
nil 的标题
。在 OC 时期,注明变量一般不会设想是或不是为空的标题;而在 Swift时期,因为其是壹门强安全性的语言,在变量定义时,必须分明变量是还是不是为空。一般定义为非空有两种以下情势:

不管哪一种情景,开辟者会从一初步就思索管理 nil
时的景观,并在后续开垦中一贯专注。所以从foo转化为foo!,你就会思忖 OC
中代码是不是也要拍卖
nil 的状态;而假如转会为foo?,nil 也不在乎,而实际上大概并不是那样,nil
的超过常规规景况思考会一贯忽略,开垦中的隐患从来存在,同时也不吻合 斯维夫特强安全性的设计思路。

  • Q: 小编就想让 OC 中的变量从foo澳门葡京备用网址 ,转化到 Swift 中变成foo?,有未有主意
// force unwrappingvar foo = "Hello"// implicitly unwrappingvar foo: String!
  • Q: 笔者就想让 OC 中的变量从foo转化到 Swift 中变成foo?,有未有点子

请那样在 OC 中定义变量:

前端依照起始值强制解包,定义 foo 为非空变量;后者则直接表明 foo
为非空变量。

请那样在 OC 中定义变量:

1 // foo -> foo?
2 @property (nullable, nonatomic, copy) NSString *foo;
3 // bar -> bar!
4 @property (nonnull, nonatomic, copy) NSString *bar;
5 // qux -> qux!
6 @property (nonatomic, copy) NSString *qux;

不管哪一种状态,开采者会从1早先就想想管理 nil
时的动静,并在继承开辟中央直机关接专注。所以从foo转化为foo!,你就会思考 OC
中代码是或不是也要管理nil 的意况;而一旦转会为foo?,nil
也无所谓,而实际上恐怕并不是这么,nil
的极度情状思量会直接忽略,开采中的隐患一向留存,同时也不符合 Swift强安全性的统一盘算思路。

1 // foo -> foo?
2 @property (nullable, nonatomic, copy) NSString *foo;
3 // bar -> bar!
4 @property (nonnull, nonatomic, copy) NSString *bar;
5 // qux -> qux!
6 @property (nonatomic, copy) NSString *qux;

那种事先注脚是还是不是为 null 的定义方法,是还是不是很像 斯威夫特 中的 optional
机制?不过 OC 时期我们差不多不会去管变量是或不是为 nullable
那件事,由此我们得以回味 OC 和 Swift 在语言设计思路上的出入。

  • Q: 笔者就想让 OC 中的变量从foo转化到 Swift
    中变成foo?,有未有艺术

那种事先注明是或不是为 null 的定义方法,是否很像 斯维夫特 中的 optional
机制?可是 OC 时代大家大致不会去管变量是或不是为 nullable
那件事,因而我们能够体会 OC 和 斯维夫特 在言语设计思路上的差别。

其实nullablenonnull是 Swift 出来之后才引进 OC 的。所以一开端,OC
中的变量暗中认可都是nullable,转换到 Swift中,应该就是?。不过这么转车代价太大,大家全部变量都要在 斯维夫特中用if else或者guard来解包。所认为了写起来方便,斯威夫特干脆直接强转,故而现在以此机制也是一个历史遗留难题。

请那样在 OC 中定义变量:

其实nullablenonnull是 斯威夫特 出来今后才引进 OC 的。所以一同初,OC
中的变量私下认可都以nullable,转换到 Swift中,应该正是?。可是那样转车代价太大,大家具有变量都要在 斯威夫特中用if else或者guard来解包。所认为了写起来方便,Swift干脆直接强转,故而将来以此机制也是七个历史遗留难点。

  • Q: 斯维夫特 如此那般导致混编 App
    崩溃,未有提醒的景况下技师必须细细检查 nil 导致的
    bug,那样设计强制解包的代价是不是有点大?
// foo -> foo?@property (nullable, nonatomic, copy) NSString *foo;// bar -> bar!@property (nonnull, nonatomic, copy) NSString *bar;// qux -> qux!@property (nonatomic, copy) NSString *qux;
  • Q: Swift 如此这般导致混编 App
    崩溃,未有提醒的情景下程序员必须细细检查 nil 导致的
    bug,那样设计强制解包的代价是或不是有点大?

其1 bug 在混编 App
中很轻便并发,未有警示确实拉动异常的大困扰。实际上这几个标题1度在苹果的开采者论坛上被提议,Swift组本身也开了个 ticket 要修,可惜最终相连了之。Github
上有人开辟出了第2方的工具来缓和那些难题。

那种事先申明是还是不是为 null 的定义方法,是或不是很像 斯维夫特 中的 optional
机制?然则 OC 时期我们差不多不会去管变量是不是为 nullable
那件事,因此我们得以回味 OC 和 Swift 在言语设计思路上的距离。

这几个 bug 在混编 App
中很轻巧并发,未有警示确实带来比非常的大苦恼。实际上那么些主题素材1度在苹果的开采者论坛上被提议,Swift组本身也开了个 ticket 要修,可惜最终相连了之。Github
上有人开辟出了第3方的工具来消除那一个标题。

自个儿个人以为这几个主题素材苹果不器重的原由在于 Swift 和 OC
混编只是三个权且的规模。斯威夫特 代替 OC
是一个时日难题,所以化解混编中的难题都来得没有多大要义,在苹果内部也平素是低优先级。究竟现在有着精力应该置身斯维夫特 上,随着时光的延迟和 OC 的退出,那一个难点也将卑不足道。

其实nullablenonnull是 Swift 出来之后才引进 OC 的。所以一齐头,OC
中的变量暗中同意都以nullable,转换到 Swift中,应该正是?。然则这么转车代价太大,我们具备变量都要在 Swift中用if else或者guard来解包。所感觉了写起来方便,Swift干脆直接强转,故方今后以此机制也是一个历史遗留难点。

小编个人以为那一个难题苹果不尊重的来由在于 Swift 和 OC
混编只是三个一时的规模。斯维夫特 替代 OC
是1个日子难点,所以解决混编中的难点都体现未有多概况思,在苹果内部也直接是低优先级。毕竟未来具有精力应该放在
斯威夫特 上,随着年华的延期和 OC 的脱离,那一个主题材料也将微不足道。

 

  • **Q: Swift 如此那般导致混编 App
    崩溃,未有指示的情况下技术员必须细细检查 nil 导致的
    bug,那样设计强制解包的代价是或不是有点大? **

 

其壹 bug 在混编 App
中很轻易出现,未有警示确实带来相当的大搅扰。实际上那几个难点已经在苹果的开采者论坛上被建议,Swift组自个儿也开了个 ticket 要修,可惜最终不断了之。Github
上有人开垦出了第叁方的工具来消除那几个主题素材。

自身个人感觉这么些难题苹果不青眼的原因在于 Swift 和 OC
混编只是一个临时的局面。Swift 代替 OC
是一个光阴问题,所以解决混编中的难点都显示未有多轮廓义,在苹果内部也一向是低优先级。究竟今后持有精力应该置身斯维夫特 上,随着年华的推移和 OC 的脱离,这几个标题也将人微言轻。

参照链接:Nullability and Objective-C[Optionals Case Study:
valuesForKeys](Optionals Case Study: valuesForKeys)

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website