• [技术翻译]构建现代化的 Objective-C (上)


    我的技术博客经常被流氓网站恶意爬取转载。请移步原文:http://www.cnblogs.com/hamhog/p/3561514.html,享受整齐的排版、有效的链接、正确的代码缩进、更好的阅读体验。

    本文翻译自:Structuring Modern Objective-C 译者:Ley戴仓薯

    当学习一个新技能时,比如编程语言,我们经常为了能运行,而把所有能用的都揉合在一起。再后来,我们回归到这些习惯,并进行重新估计,采用社区中的最佳实践并写出更好、更有结构化的代码。

    最近,Objective-C语言收到了过多的新特性,但社区的最佳实践还没持续更新。这就超出了“风格”的范畴,进入了“结构”的领域。

    我在最近一段时间里,审视了我自己的代码实践,评估了我可以在哪里做的更好,所以我想我应该和你们分享我的发现。

    欢迎光临现代Objective-C。

    (以上部分感谢Ley翻译)

    访问实例变量(Instance Variable)

    唉,实例变量。从何说起呢。一句话,实例变量很糟。如果你会这样写:

    @interface MyClass : NSObject {
        BOOL someVariable;
    }
    
    @end

    别这么写了。现在就改。

    不要再声明实例变量了,尤其别声明在头文件里。你应该把它们声明为property,然后用消息机制或者“.”来访问它们。

    之前说过为什么通过实例变量来访问property没有明显的益处。事实上,通过getter/setter方法来访问有几个优势。

    • 一致性: 你不需要再去怀疑getter/setter方法有没有副作用了,假如有的话,也肯定早就会被人注意到。

    • Debug: 你可以简便地在getter/setter方法上设置断点,而不用在运行时针对实例变量的内存地址设置watchpoint。

    真的,没有理由再去声明实例变量、再去直接访问这些实例变量形式的属性了——除非是在本身覆盖(override) getter/setter的方法里,或者在initializer/dealloc 方法里,取决于你想要代码有多少防御性(感谢 Bryan 提供链接)。再除非就是习惯了,但你应该改掉这个习惯。我就改了。

    更新: 我找到了官方文档的一个链接,建议不要在dealloc中调用getter/setter方法。供参考。

    那么只读的属性怎么办呢?既然没有setter方法,你不还是需要访问实例变量吗?好问题。这引出了本文的下一点。

    在头文件中定义readonly属性

    在你public的接口中要暴露属性或组件,使用readonly属性是一个很好的方式。但是如果不直接访问实例变量,怎么设置它们的值呢?答案是在 .m 文件中定义一个private的class extension。

    在你的头文件中,声明如下:

    @interface MyClass : NSObject
    
    @property (nonatomic, readonly) Type propertyName;
    
    @end

    然后,在类的 implementation 文件中,在以上定义的基础上,再定义如下:

    @interface MyClass ()
    
    // Private Access
    @property (nonatomic, strong, readwrite) Type propertyName;
    
    @end

    这样你就定义了 public 的 getter 和 private 的 setter。可喜可贺!现在你不需要再访问实例变量了。

    Schwa 补充了一条建议:

    @ashfurrow 回复:《在头文件中定义readonly属性》。我还要加一条,不要在头文件里暴露可变(mutable)对象。顺便赞一下,很好的文章。

    — Jonathan Wight (@schwa) January 24, 2014

    合理地定义 BOOL 类型的属性

    定义属性时,遵从Apple官方指南总是没错的。但我承认,我也不总是看得那么勤快。要记住,定义BOOL类型的属性时,要同时手动定义一个getter方法。

    @property (nonatomic, assign, getter = isSomething) BOOL something;

    如非必要,不要把#import写在头文件里

    我经常在Objective-C新手写的代码里看到这种情况。总体来说,问题在于大多数的#import语句应该只写在 .m 文件里,而不应该写在 .h 头文件里。

    如下面的例子。

    #import "MyOtherClass.h"
    
    @interface MyClass : NSObject
    
    @property (nonatomic, strong) MyOtherClass property;
    
    @end

    你可以改写代码如下,然后在类的 implementation 文件 yourMyClass.m 中再去 #import MyOtherClass.h 头文件。

    @class MyOtherClass;
    
    @interface MyClass : NSObject
    
    @property (nonatomic, strong) MyOtherClass property;
    
    @end

    @class MyOtherClass的写法是类的前向声明(forward class declaration)

    这样写的益处良多。用类的前向声明来代替 #import 头文件可以提高编译速度,可以避免循环#import,还可以让你的头文件更轻盈——本该如此。

    (未完待续)

    本文翻译自:Structuring Modern Objective-C 译者:Ley戴仓薯

  • 相关阅读:
    CSP2021&NOIP2021游记
    P3835[模板]可持久化平衡树【无旋Treap】
    P4688[Ynoi2016]掉进兔子洞【莫队,bitset】
    C# (CSharp) ADODB.Command示例
    求最大公约数 算法记录
    流逝时间+Windows下监测文件夹
    C# WinForm开发系列 文章索引
    09年搞笑签名
    高三班主任写给学生的一封信(在读大学的要看完)
    北京生存法则
  • 原文地址:https://www.cnblogs.com/hamhog/p/3561514.html
Copyright © 2020-2023  润新知