[译文]如何才能不崩溃 #5: Threading, part 2

原文地址: http://inessential.com/2015/05/26/how_not_to_crash_5_threading_part_2 我 前面发布的关于线程的文章 留下了一个开发的问题,关于怎样让代码运行在主线程之外进行沟通 - 安全的 - 返回到主线程。 对象创建的后台任务掌握着任务的结果。这是一个硬性的规则。 通常创建任务的对象在整个app的生命周期中一直存活着。图片缓存可能是个例子 - 缓存可能会在app的生命周期中被清空,但是缓存对象在这段时间内一直存活着。 另一个例子是类似于 Vesper 的 VSAccount 对象。总是有一个 VSAccount 实例。用户也许有也许没有一个服务端账户。用户可能会改变他们的账户。但是一直会有一个 VSAccount 对象贯穿于整个app的生命周期。 (注意:显然,一个app管理多个账户会做不同的事情。但是 Vesper 管理最多一个服务端账户,所以,…

[译文]如何才能不崩溃 #4: Threading

原文地址: http://inessential.com/2015/05/22/how_not_to_crash_4_threading 这有一个简单的规则:做任何事情都在主线程上。随着机器和设备的日益发展,你可以在主线程中做比你想象中更多的事情。 当你不需要考虑任何并发的时候,这就太美好了。 但是... 我是一个性能狂。或者,更重要的是,我是一个用户体验狂。唯一一个比缓慢更糟的是明显的阻塞主线程。所以不要这么做。 好,我们先从主线程开始。 主线程规则 所有我期望运行在主线程上的代码只在主线程上运行,除少数之外。(我们在一分钟内获得例外。) 这解决了一串问题。例如,我以前写了一个文章关于在dealloc中注销通知。很多人指出,你不能保证dealloc将会在哪一个线程中被调用 - 但是你能,实际上,对于任何在主线程上运行的对象,都只能在主线程上被引用。 这意味着,任何KVO的改变都被发送到主线程上,所有观察者也依然运行在主线程上,并在主线程上期待通知。 不处理并发的好处是极大的。我强烈建议你使用这种方式去编写你的app,然后去测试是否会有东西阻塞主线程。如果没有,…

[译文]如何才能不崩溃 #3: NSNotification

原文地址: http://inessential.com/2015/05/21/how_not_to_crash_3_nsnotification 实际上,相比起KVO我更喜欢NSNotification(特别是)在绑定上。我有的时候会使用KVO - 当有些时候,这是最明智的。但是NSNotification,像很多更老的API一样,在不引起崩溃的情况下,更容易使用。 但是你依然需要很小心。 崩溃的一种方法 当一个对象注册了一个通知,然后对象在释放的时候没有注销这个通知,然后在发送通知的时候,app就会崩溃。 大规则 我有一个简单的、硬性并快速的规则:通知只在主线程发送。没有例外。如果某些代码在另外一个线程上跑,并且它需要去发送一个通知,那它只能在主线程上这么做。 这能避免通知进入一个你不期望的线程所导致的所有问题。在注销通知后,这可以避免资源竞争。 一个app几乎所有的代码都应该运行在主线程上。运行在通知或者GCD队列上的代码应该从其他代码上独立出来,并且当多个对象一起工作的时候,应该使用代理模式(使用或不使用block)。 确保通知应该一直很容易的在主线程上发送。(我将在另一篇 如何才能不崩溃…

[译文]如何才能不崩溃 #2: Mutation Exceptions

原文地址: http://inessential.com/2015/05/16/hownottocrash2mutationexceptions 你从某处获得了一个集合并且枚举它 - 然后你得到了一个关于集合在枚举中被改变的错误。然后app崩溃了。 你可以用一种简单的方法避免这种不幸的命运:不枚举可变集合。 不同意我 你可能会认为真正正确的答案是枚举中不去改变一个可变的集合。你应该对你的app有足够的了解,来编写安全的可枚举可变集合的代码。 是的,你应该,你绝对应该。 然而,编写不崩溃的代码就是在移除疑惑的问题。将发生错误的机率降到最低,将未来引入改变而导致崩溃的机率降到最低(通过你或其他人)。 可变集合不应该为公共API 这个应该非常罕见 - 或者,更加,绝不 - 一个对象拥有一个公共的可变集合的属性。可变集合应该放在对象的内部。 (此外,尽可能的让公共的集合都是只读属性。当然,这并不一直都可能。) 现在,一个拥有公共集合属性的对象完全有可能在内部是一个可变集合。追踪一个operations集合,它的公共部分可能像这样: @property (nonatomic, readonly) NSArray *operations; 它的内部是这样: @property…

[译文]如何才能不崩溃 #1: KVO and Manual Bindings

原文地址: http://inessential.com/2015/05/14/hownottocrash1kvoandmanualbind 我最近修复了一些bug,但是相比起修复bug,我想我对如何写出不导致崩溃的代码更感兴趣。 在第一部分,我将讨论KVO、manual bindings(手动绑定)、retain cycles(循环引用)、invalidate methods(无效方法)。 绑定意味着永远不会说再见 iOS开发者不会,但是Mac开发者会做下面的事情:我们可以绑定一个属性到另外一个属性上面。我们这么做是为了,如果x.foo更新了,那么y.foo也会一起更新。 在AppKit的NSKeyValueBinding.h中,看一下这个方法:bind: toObject: withKeyPath: options:。 让我们想象一下,有一个button有一个title属性。无论何时,某个controller的title更新,这个title属性也要更新。我们说这个controller拥有这个button,我们也许会这么写: static NSString *kTitleKey = @"title"; [self.…

译文

个人翻译能力一般,如果你在文中发现任何错误,请你帮忙指正一下,谢谢。 Facebook [译文]在iOS上自动检测内存泄露 How Not to Crash - 如何才能不崩溃 这是来源于inessential.com的一系列博客,我觉得内容写的非常好,也非常有意义,所以我在此进行一系列的翻译。 下面是原博客地址: http://inessential.com/hownottocrash 如何才能不崩溃 #1: KVO and Manual Bindings 如何才能不崩溃 #2: Mutation Exceptions 如何才能不崩溃 #3: NSNotification 如何才能不崩溃 #4: Threading 如何才能不崩溃 #5: Threading, part 2 如何才能不崩溃 #6: Properties and Accessors 如何才能不崩溃…

Objective-C中为什么不支持泛型方法

今天和网易的一位朋友交流,我和他说,我下面的app会用Swift+函数式编程方式去写,然后他说 Swift大公司都用的较少, 因为新东西,都怕不稳定, 尽量把Objective-C学的精深一些 是的,最近一段时间我看了一些Python的书,使用web.py和django写了点模仿豆瓣和拉钩的demo,我也在学习Swift,使用ReactiveCocoa。最近的时间都花在了这个上面,这是否是一种舍本求末的做法,我不知道,但是Desperado同志确实提醒了我,Objective-C是我现在的饭碗。(另外,我再瞻仰一下Desperado在北京的工资...) 言归正转,我们一起来探究一下Objective-C中为什么不支持泛型方法。 每当探讨此类语言级别对某一个特性的支持的时候,其实很多时候是在探讨这个语言的设计者对这门语言的设计哲学。比如说,很多语言不支持多继承,可能并不是实现不了,也不是不好实现(松本行弘的Ruby就使用了一个很好的多继承实现方式),可能是作者认为马就应该是马,驴就应该是驴,不存在一个又是马、又是驴的物种,顶多是一个物种具有另一个物种的某些特性和行为。这只是我的猜测,别当真。 这里,我尝试从Objective-C的Method方法的具体实现上去解释为什么Objective-C不支持泛型方法。 首先,我们去看一下Objective-C中的方法”Method”是怎样的一个数据结构。 我们先下载一下苹果开源的Objective-C runtime的源码,在下面的地址上: http://opensource.apple.…

ZBar-iOS

ZBar从2012年之后就没有更新过了,所以在iOS上,如果使用ZBar的话,那么ZBar默认提供的只有32位的静态库,当然我们可以直接下载到ZBar的源码,然后编译64位的版本,这很方便。 当我们有更深一层的需要的时候,我们可能会要求将ZBar的源码直接嵌入我们的项目中,而这个就是一个被剥离出来的ZBar-iOS部分。可以直接嵌入到项目中。 由于历史的悠久,ZBar在64位iOS下编译有大量的警告,我这里将Build Phases中的文件编译flag中加入了一些参数,默认不显示这些类型的警告。 由于在剥离后,在64位下编译有一些问题,我修改了部分内容,很少,我这就不写出了,但是并不影响大家使用。 当然,都已经是源码了,并且这个项目已死,大家可以直接修改,而不用担心升级更新的问题。 步骤: 在你的项目中加入下面的库: libiconv.dylib CoreVideo.framework CoreMedia.framework AVFoundation.framework 将ZBarSDK文件夹拖拽或者拷贝到你的工程目录下面 参照ZBar官方给的Demo即可正常使用 下载地址: https://github.com/Forkong/ZBar-iOS…

infer install

infer是facebook开源的一个代码纠错工具。 infer可以智能纠错Android、iOS、java工程等,目前支持Mac和Linux系统。 infer的安装可以选择下载压缩文件,然后直接安装,操作如下,这里以发文时的最新版0.1.1版本为例。 目前infer已经更新,请大家去github上下载最新版本 直接安装 下载压缩文件 Mac OS X: https://github.com/facebook/infer/releases/download/v0.1.1/infer-osx-v0.1.1.tar.xz Linux: https://github.com/facebook/infer/releases/download/v0.1.1/infer-linux64-v0.1.1.tar.xz 安装infer…

__block 与 __weak

下面举个使用__block的例子: __block BOOL found = NO; NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil]; NSString *string = @"gamma"; [aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) { *stop = YES; found = YES; } }]; // 在这之后, found == YES 上面例子的意思是,迭代一个NSSet,当迭代出的一个字符处的小写编码和string一致,则停止搜索,将found值修改为YES,注意,found在block之外被创建,并被__block修改,且在block内发生修改。 那同样的这一段代码,我们将__block修改为__weak会怎么样呢,…