转自:http://www.cocoachina.com/swift/20160613/16632.html
原文:Thinking in Swift,Part 1: Saving ponies,原博客地址:Crunchy Developmen,译者:ray16897188
我常看见Swift的新手试着将它们的ObjC代码翻译成Swift。但是开始用Swift写代码的时候最难的事情并不是语法,而是思维方式的转变,去用那些ObjC里并没有的Swift新概念。
在这一系列的文章中,我们会拿一个ObjC代码做例子,然后在把它转成Swift代码的全程中引入越来越多的对新概念的讲解。
本文的第一部分内容:可选类型(optionals),对可选类型的强制拆包,小马,if let,guard和??。
ObjC代码
假设你想创建一个条目列表(比如过会儿要显示在一个tableVIEw里)- 每个条目都有一个图标,标题和网址 - 这些条目都通过一个JsON初始化。下面是ObjC代码看起来的样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @interfaceListItem:NSObject @property(strong)UIImage*icon; @property(strong)Nsstring*Title; @property(strong)NSURL*url; @end @implementationListItem +(NSArray*)ListItemsFromJsONData:(NSData*)JsonData{ NSArray*itemsDescriptors=[NSJsONSerializationjsONObjectWithData:JsonDataoptions:0error:nil]; NSMutableArray*items=[NSMutableArray new ]; for (NSDictionary*itemDesc in itemsDescriptors){ ListItem*item=[ListItem ]; item.icon=[UIImageimagenamed:itemDesc[@ "icon" ]]; item.Title=itemDesc[@ "Title" ]; item.url=[NSURLURLWithString:itemDesc[@ ]]; @H_419_145@ [itemsaddobject:item]; } return [itemscopy]; } @end |
直译成Swift
想象一下有多少Swift的新手会把这段代码翻译成这样:
classListItem{ var icon:UIImage? Title:String= "" url:NSURL! staticfuncListItemsFromJsONData(JsonData:NSData?)->NSArray{ letJsonItems:NSArray= try !NSJsONSerialization.JsONObjectWithData(JsonData!,options:[])as!NSArray letitems:NSMutableArray=NSMutableArray() itemDesc JsonItems{ letitem:ListItem=ListItem() item.icon=UIImage(named:itemDesc[ ]as!String) item.Title=itemDesc[ ]as!String item.url=NSURL(string:itemDesc[ "url" ]as!String)! items.addobject(item) } @H_419_145@ items.copy()as!NSArray } } |
对Swift稍有经验的人应该会看出来这里面有很多代码异味。Swift的资深使用者读到这段代码之后就很可能心脏病突发而全部挂掉。
哪里会出错?
上面例子中第一个看起来像代码异味的地方就是一个Swift新手经常犯的坏毛病:到处使用隐式解析可选类型(value!),强制转型(value as! String)和强制使用try(try!)。
可选类型是你的朋友:它们很棒,因为它们能迫使你去思考你的值什么时候是nil,以及在这种情形下你该做什么。比如"如果没有图标的话我该显示什么呢?在我的tableVIEwCell里我该用一个占位符(placeholder)么?或者用另外一个完全不同的cell模板?"。
这些就是我们在ObjC中经常忘了考虑进去的用例,但是Swift帮助我们去记住它们,所以当值是nil的时候把它们强制拆包导致程序崩溃,把可选类型这个高级特性扔在一边不用,是很可惜的。
你绝不应该对一个值进行强制拆包,除非你真的知道你在干什么。记住,每次你加一个!去安抚编译器的时候,你就屠杀了一匹小马。
很可悲,Xcode是鼓励犯这种错误的,因为error提示到:"value of optional type ‘NSArray?’ not unwrapped. DID you mean to use ! or ?",修改提示建议...你在后面加一个!??。噢,Xcode,你是有多菜。
我们来拯救这些小马吧
那么我们该怎样去避开这些无处不在的糟糕的!呢?这儿有一些技巧:
@H_396_301@使用可选绑定(optional binding)if let x = optional { /* 使用 x */ }
用as?替换掉as!,前者在转型失败的时候返回nil;你当然可以把它和if let结合使用
你也可以用try?替换掉try!,前者在表达式失败时返回nil1。
好了,来看看用了这些规则之后我们的代码2:
if letnonNilJsonData=JsonData{ letJsonItems:NSArray=( ?NSJsONSerialization.JsONObjectWithData(nonNilJsonData,options:[]))as?NSArray{ letitems:NSMutableArray=NSMutableArray() JsonItems{ letitem:ListItem=ListItem() leticon=itemDesc[ ]as?String{ item.icon=UIImage(named:icon) } letTitle=itemDesc[ ]as?String{ @H_419_145@ item.Title=Title leturlString=itemDesc[ ]as?String{ leturl=NSURL(string:urlString){ item.url=url @H_86_403@ } } items.addobject(item) } @H_103_419@ items.copy()as!NSArray } } [] //IncasesomethingFailedabove } 判决的金字塔 |
评论列表(0条)