美文网首页程序员
采用现代Objective-C (1)

采用现代Objective-C (1)

作者: Runxing | 来源:发表于2014-05-15 18:48 被阅读288次

多年来,Objective-C语言已经有了革命性的发展。虽然核心理念和实践保持不变,但语言中的部分内容经历了重大的变化和改进。现代化的Objective-C在类型安全、内存管理、性能、和其他方面都得到了增强。使你更容易编写正确的代码。在你现有和未来的代码中使用这些改进是很重要的,会使你的代码一致、可读、灵活。

Xcode提供了一个工具来帮助做这些结构性的变化。但在使用这个工具之前,你想了解工具为你的代码做了什么改变以及为什么。本文强调了一些最重要的和有用的现代化方式可以用在你的代码中。

instancetype

使用instancetype关键字作为返回类型的方法,该方法返回一个类的实例(或该类的子类)这些方法包括alloc,init,和类工厂方法。


使用instancetype代替id在适当的地方可以改善Objective-C代码类型安全。例如:考虑下面的代码:

    @interface MyObject : NSObject
    + (instancetype)factoryMethodA;
    + (id)factoryMethodB;
    @end

    @implementation MyObject
    + (instancetype)factoryMethodA
    {
        return [[[self class] alloc] init];
    }

    + (id)factoryMethodB
    {
        return [[[self class] alloc] init];
    }
    @end

    void doSomething()
    {
        NSUinteger x, y;
        // Return type of +factoryMethodA is taken to be "MyObject *"
        x = [[MyObject factoryMethodA] count];
        // Return type fo +factoryMethodB is "id"
        y = [[MyObject factoryMethodB] count];
    }

因为+factoryMethodA使用了instancetype作为返回类型,该消息的类型
表达式为MyObject *.当MyObject没有-count方法的时候,编译器会发出警告的在x行:

    main.m: 'MyObject' may not respond to 'count'

然而,由于+factoryMethodB返回类型为id,编译器不可以给出警告。因为一个id可以是任何类型的对象类,由于存在一个名为-count的方法在一些类中,编译器可能返回一个+factoryMehtodB的实现的方法。

确保instancetype工厂方法有权利子类化行为,在初始化的时候一定要使用[self class]而不是直接引用的类名。遵循这个惯例确保编译器将正确判断出子类的类型。例如:考虑尝试这样做一个MyObject的子类从前面的示例:

    @interface MyObjectSubclass : MyObject

    @end

    void doSomethingElse()
    {
        NSString *aString = [MyObjectSubclass factoryMethodA];
    }

关于这个代码编译器将给出下面的警告:

    main.m: Incompatible pointer types initializing 'NSString *'
    with an expression of type 'MyObjectSubclass *'

在这个例子中,+factoryMethodA MyObjectSubclass类型的消息发送返回一个对象,这是接收者的类型。编译器确定适当的返回类型+factoryMethodA应该是MyObjectSubclass子类,而不是超类的工厂方法被调用。


怎样适配

在你的代码中,出现id作为返回值替换为instancetype在适当的地方。这通常是init方法和类的工厂方法。甚至编译器会自动转以“alloc”、“init”、“new”开头的方法,而不转换其他的方法。objective-c对instancetype的转换是显式的方式。


请注意,您仅应该用instancetype替换id作为返回值,而不是在你的代码的任何地方都这么做。不像id,instancetype在声明方法时仅仅只能作为返回值类型使用。

    例如:
    @interface MyObject
    - (id)myFactoryMethod;
    @end

    应该变为:
    @interface MyObject
    - (instancetype)myFactoryMethod;
    @end

或者,您可以在Xcode使用现代objective-c变换器自动进行转换您的代码。更多信息请看使用Xcode重构你的代码

相关文章

  • 采用现代Objective-C (1)

    多年来,Objective-C语言已经有了革命性的发展。虽然核心理念和实践保持不变,但语言中的部分内容经历了重大的...

  • 采用现代Objective-C (2)

    Properties 一个public或private的Objective-C属性使用@property语法声明的...

  • 采用现代Objective-C (3)

    Enumeration Macros NS_ENUM和NS_OPTIONS宏提供一个简洁、简单的定义枚举的方法和基...

  • iOS - 采用现代化的Objective-C

    说明:本篇文章是作者(Mitchell)参考苹果的 Adopting Modern Objective-C 这篇文...

  • 熟悉Objective-C

    一、了解Objective-C语言的起源 Objective-C采用消息结构(messaging structur...

  • iOS求职之OC面试题

    1、Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议。 2、#...

  • iOS求职之OC面试题

    1、Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议。 2、#...

  • iOS-OC面试题

    1、Objective-C的类可以多重继承么?可以采用多个协议么?答:不可以多重继承,可以采用多个协议。2、#im...

  • iOS-面试题3

    1、Objective-C的类可以多重继承么?可以采用多个协议么?答:不可以多重继承,可以采用多个协议。2、#im...

  • View Controller 容器 - 言无不尽 ( 中文翻新

    原 Demo 代码为 Objective-C , 我采用了 Swift

网友评论

    本文标题:采用现代Objective-C (1)

    本文链接:https://www.haomeiwen.com/subject/mxtdtttx.html