为什么 NSLog 对象不支持属性与方法 Swift 对象

Swift开发的几个小技巧
招聘信息:
(整理自)正所谓掌握一样技术最好的办法就是用它来做一个东西,于是这段时间的实战让我对 Swift 的理解更深了一层,也积累了一些使用技巧。今天就分享一则:如何正确地定义一个类变量(和类常量)。Swift 语言对于无论是静态语言过来还是动态语言过来的开发者来说,都有点点不适应,很多问题的解决思路不能用已经习以为常的方法去做。如何正确的定义一个类变量(和类常量)Swift 支持用 class func 来修饰一个「类方法」,然而却不能用「class var」和「class let」来指定类变量和类常量,一旦你尝试这样做了,那么 Xcode 会提示你:Class variable not yet supported。真是遗憾…不过从这个提示可以看出,Class variable 的支持只是时间问题。那么现阶段我们要怎么完成这一目标?总不能用丑陋的 Workaround 吧。办法还是有的,我从 Apple 官方的例子中学到了如何去定义一个类级的常量和变量,那就是用 struct。来个 demo 你就明白了:class&MyClass&{&
&&&&&struct&Constants&{&
&&&&&&&&&static&let&name&=&"MyClass"&
&&&&&struct&Variables&{&
&&&&&&&&&static&var&age&=&0&
&}然后在调用的时候,就可以这样来调用: MyClass.Constants.name 和 MyClass.Variables.age虽然中间还隔了一层 Constants 和 Variables,但是我觉得这样也挺好,相当于有了一个 Prefix,直接看代码时就知道是常量还是变量了。如果你不喜欢这种方式,也可以用 computed property 的形式来模拟真实的类变量(常量)的调用。比如:extension&MyClass&{&
&&&&class&var&name:&String&{
&&&&&&&get&{
&&&&&&&&&&&return&Constants.name
&&&&class&var&age:&Int&{
&&&&&&&&get&{
&&&&&&&&&&&&return&Variables.age
&&&&&&&&set&{
&&&&&&&&&&&&Variables.age&=&newValue
&}定义了这种方式后,就可以直接用 MyClass.name 和 MyClass.age 来访问类常量或修改类变量了。这种方式在语法上兼容了未来会得到支持的类变量和类常量,但就是自己要写一大堆 getter 和 setter,有点麻烦,大家可以根据自己的需要决定是不是要采用这种方式。关于本文的 demo 代码,大家可以粘贴进「swift」这个命令行工具来实践一下。效果正如我们想要的那样,常量不允许修改,变量可以修改,所有的这些操作都是在 MyClass 上进行,而不需要实例化。虽然现在用 Swift 来做一些常用的任务还略显麻烦,不过作为一个年轻的语言,目前它确实已经能用在生产环境中写出真正可用的 App 了,随着接下去的发展,我相信它会变得越来越好的。PS:现在我只想 SourceKitService 崩溃的少一点…用Optional来避免异常指针问题最近在用 Swift 开发的过程中,又碰到了一个问题。简单的说,系统在该返回非 nil 值的地方返回了一个异常指针(即指向 0x0000 地址,产生 KERN_INVALID_ADDRESS 异常)造成了 App 的 crash,算是 iOS UIKit 的一个 Bug。这个问题需要 SDK 的升级来解决,但是在 SDK 升级之前,我们可以通过一个小小的 Workaround 去解决。来龙去脉是这样的:iOS 的 Swift 版的 API 与 Objective-C 的 API 最大的不同是,你需要看 Objective-C 的 API 文档才知道一个系统返回的值是不是可能是 nil。比如 UIDataSourceModelAssociation 这个用来还原 UITableView 和 UICollectionView 位置的 Protocol,它有两个方法,其中一个是:-&(NSString&*)modelIdentifierForElementAtIndexPath:(NSIndexPath&*)idx&inView:(UIView&*)view光看 Objective-C 这个方法,你是不知道系统返回的 idx 有没有可能是 nil 的,但是一看 Swift 版本,就非常显然了:func&modelIdentifierForElementAtIndexPath(_&idx:&NSIndexPath,&inView&view:&UIView)&->&Stringidx 和 inView 一样,都没有 ? 和 !,因而它们不是 Optional,所以值不可能是 nil。如果 idx 和 inView 可能是 nil 的,那么它应该是用 ! 来修饰,以警告开发者,这个值可能是 nil,请小心使用。func&modelIdentifierForElementAtIndexPath(_&idx:&NSIndexPath!,&inView&view:&UIView!)&->&StringSwift 这种比 Objective-C 更彻底的 API 即文档的表达形式,我在编码一段时间后非常喜欢。然而,也正是系统的框架还进化的不彻底的原因,这些 API 依然可能会返回 nil 的值,但是 API 因为被标记不会返回 nil,于是就会发生 swift_dynamicCastClassUnconditional 的异常,最后导致 App crash。下图即是 modelIdentifierForElementAtIndexPath 这个方法在应该返回值的情况下,却返回了一个指向 0x0000 的对象。然后 Swift 在包装值的时候,没能包装成功而发生 crash。那么如何避免因为这个问题造成的 App crash 呢?实际上很简单,只需要手动用 Optional 包装一下这个 0x0000 对象,再判断它是不是 nil,就不会发生问题了。比如这样的代码:let&optionalIdx&=&Optional(idx)
if&optionalIdx&==&nil&{
&&&&return&"Do&something"
}刚开始遇到这个问题我也很苦恼,后来突然想到,是不是可以用 Optional 去包装一下这种异常指针再检查是不是 nil,一试果然可以。于是问题就这样解决了。幸好,这种坑没有多到让我抓狂的步地,我能继续用 Swift 愉快的写下去了…如何用 Swift 思维设计网络请求近来在用 Swift 开发 App 的过程中,最大的心得就是:我开始渐渐用「Swift 思维」来思考了。回顾刚开始我用 Swift 时,只是套用它的语法而已,脑子里依然是 Objective-C 思维。这段时间,随着对 Swift 基本特性的掌握,我开始有意识地学习并尝试一些 Swift 才有的特性,此谓「Swift 思维」。Swift 有很多专有(Objective-C 没有的)的模式,今天我就从一个很简单的例子讲起,那就是:如何用 Swift 思维设计网络请求。做过网络类应用的同学应该都知道,我们做一个网络请求时,通常会有两个结果:一个是失败,返回错误,一个是成功,返回结果。当然途中还会有更复杂的情况,比如:1、网络请求本身的失败(比如网络超时);2、API 端返回的内部结果型失败(比如密码不正确)。这里我们就不细分了。在传统的 Objective-C 的项目里,有几种处理这种异常的情况,主要是:直接判断 NSError&NSError&*error&=&
id&result&=&[API&doSomething:&error];
if&(error&!=&nil)&{
&&&NSLog("Oh&Error!")
}这种处理太直白,一般会阻塞当前的线程,因而不推荐。一般用的比较多的是下面两种:通过 success,failture 的 block 来处理[API&doSomethingWithSuccess:^(id&result)&{
&&&&NSLog(@"Seems&good")
}&failure:^(NSError&*error)&{
&&&&NSLog(@"Oh&Error!")
}];这种就相对好点了,通过 Block 及内部实现,可以做到不阻塞当前线程,在有结果的时候再进行处理。在对应的 Block 处理对应的情况:成功 or 失败。 不过这个设计依然还有一点缺陷,因为它对结果的处理分散在不同的 Block,如果我需要统一处理无论成功或失败的情况,那么需要分别调用,不是太直观了。所以,我们还有第三种模式。通过统一的 completionHander 的 block 来处理[API&doSomethingWithCompletionHandler:^(id&result,&NSError&*error)&{
&&&&if&result&!=&nil&{
&&&&&&&&NSLog(@"Seems&good")
&&&&if&error&!=&nil&{
&&&&&&&&NSLog(@"Oh&Error!")
}];这种通过 CompletionHandler 来统一作成功结果和错误失败的处理应该是现在设计的首先,包括系统自己的 API 也是这样设计的。特别适合在一个 Block 里就把所有情况处理掉的需求。Swift 式网络请求处理简单列举了三种 Objective-C 下常见的网络请求类处理方式,看起来还不错,那么 Swift 模式是什么样的,能做好更好吗?我觉得是的。Swift 里有着非常棒的 enum 机制,所有的枚举情况不但可以是任何类型,而且可以是不一样的类型。这意味着,我们在 Swift 里可以包装一种结果型 enum,比如:enum&Result&{
&&&&case&Error(NSError)
&&&&case&Value(JSON)
&&&&init(_&e:&NSError?,&_&v:&JSON)&{
&&&&&&&&if&let&ex&=&e&{
&&&&&&&&&&&&self&=&Result.Error(ex)
&&&&&&&&}&else&{
&&&&&&&&&&&&self&=&Result.Value(v)
}这段是我真实世界的代码,用在了我的微博客户端里。代码很简单,我定义了一个名为「Result」的 enum 对象,它会包装两种情况,一种是 Value,在网络请求成功时,它就是一个 JSON 值;第二种时 Error,是一个 NSError 值,在网络请求失败时,包含着具体的错误信息。这样,就成功地把一个网络请求下的可能的两种情况包装在了一个 Result 对象里,这个对象,要么是成功的结果,要么就是失败的错误,永远不会有同时有结果和错误。于是,我们的网络请求处理代码可以更为简单的设计成这样:API.doSomethingWithCompletionHandler({&(result)&->&Void&in
&&&&switch&(result)&{
&&&&case&let&.Error(e):
&&&&&&&&NSLog("Oh&Error!")
&&&&case&let&.Value(json):
&&&&&&&&NSLog("Seems&good")
})看起来似乎和前面 Objective-C 的第二种模式一样?似乎又像第三种?估且称之为混合模式吧。让我来简单说说这种模式有什么好处:首先,我们通过 Switch 条件判断这种非此即彼的模式,我们可以减少很多错误的发生,保证条件分支判断不会出问题;其次,我们依然只是在一个 Closure (这里换成 Swift 术语,而不是 Objective-C 的 Block)处理我们的一个请求结果 result,因而可以在前前后后做些其他对结果的统一处理,保证我们逻辑的统一性。这就是我所认为的 Swift 这种模式的好处了。通过这种模式改造我的项目后,我觉得代码变得更整洁、逻辑清晰,也不会有遗失的错误处理情况。当然我做采用的还只是简化版的 Swift 模式网络处理,更为强大的例子大家可以参考 swiftz 项目的 Result 对象,它使用了 Swift 的 Generic 特性,从而使其可以包装任意值(不仅仅是 JSON),从而大大增强了扩展性:https://github.com/typelift/swiftz/blob/master/swiftz_core/swiftz_core/Result.swift#L12我依然还在用 Swift 思维改造项目的过程中,目前这种模式应该还是有改进余地的,希望能和大家做更多有关这个的讨论与交流。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量5548点击量4060点击量3713点击量3659点击量3251点击量3244点击量3231点击量3195点击量3116
&2016 Chukong Technologies,Inc.
京公网安备89百家博赌场就上⑦0⑥.com_百家博赌场就上⑦0⑥.com
郭德纲和于谦的辈分关系怪物大师中的十影王有谁署执行主任谢里夫、马来西亚总理纳吉布、中国住房和城乡建设部副部长倪虹等来自70多个国家主管城市发展、住房、基础设施和城市管理的部长级领导出席了此次活动。“第九届世界城市论坛”现场在2月8日上午举行的世界城市论坛最重要的主题活动&s退出、项目方回购或转让给第三方机构以及做市实现长期存续。新规下“私募+委贷”模式终结通常,私募基金份额或信托受益权是这类项目的基础资产,通过SPV(特殊目的机构)控制项
张国荣为什么自杀?英国有什么著名的旅游景点杭州有名旅游景点有哪些?金百博彩民福地app
紫色和什么颜色搭配最好看什么是低碳生活kk娱乐平台骗我钱了百家博真人娱乐平台
洗衣机哪个牌子的质量好十佳诚信经营户&rdquo&#59;,2007年被评为苏州市&ldquo&#59;光彩之星&rdquo&#59;,2008年在江苏常熟服装城光荣地加入了中国共产党党员,2009年他获得了由服装城颁发的&ldquo&#59;优秀
关键词:百家博赌场就上⑦0⑥.com
看过本文的人还看过Dear Erica: Why doesn’t NSLog support Swift objects & Erica Sadun

我要回帖

更多关于 浏览器对象不支持属性 的文章

 

随机推荐