zoukankan      html  css  js  c++  java
  • Objective—C常见特性(instancetype和id比较、@property、枚举宏(Enumeration Macros))

    Objective—C中常见特性

    这么多年过去了,Objective—C不断的成长和进化。虽然核心思想和实践保持不变,但是语言还是产生了标志性的改变和提高。这些现代化的提高体现在类型安全、内存管理、性能和Objective—C的其他方面,这些让我们更加容易的编写正确的代码。

    instancetype和id比较

    使用instancetype作为关键字的函数返回一个类的实例,这个函数方法里面包含alloc、init和这个类的工厂方法。

    使用instancetype代替id会提高代码的类型安全。例如

    @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;
    
        x = [[MyObject factoryMethodA] count]; // Return type of +factoryMethodA is taken to be "MyObject *"
        y = [[MyObject factoryMethodB] count]; // Return type of +factoryMethodB is "id"
    }
    

    因为用instancetype作为返回类型的函数+factoryMethodA,这个消息的类型表示的是Myobject *。因为Myobject类没有-count方法。编译器会再 x 行报出警告:

    main.m: ’MyObject’ may not respond to ‘count’
    
    

    然而,使用id类型的话,表示的是任何一个类型,所以里面可能会包含有-count,编译器就不会报出错误提示。

    在子类中,为了确保instancetype的工厂方法有正确的子类行为,当分配一个类的时候,要用[self class]代替直接使用类名。

    例如在上面的类的子类如下:

    @interface MyObjectSubclass : MyObject
    @end
    
    void doSomethingElse() {
            NSString *aString = [MyObjectSubclass factoryMethodA];
    }
    

    编译器会给出以下错误提示:

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

    How to Adopt如何让代码采用instancetype方式

    在你的代码中,用instancetype替代已经存在的id。有代表性的是init方法和类工厂方法。编辑器只会替我们自动把以alloc、init、new开头的方法和返回值为id的方法转换成返回instancetype的方法,但是编辑器不会覆盖其他的方法。Objective-C 中约定明确的为所有方法写上instancetype。

    注意:你只需要在返回值的地方用instancetype替换id,er'bu'而不是把所有的id都用instancetype替换。instancetype只能作为函数声明的返回值。这是和id的不同点。

    例如:

    @interface MyObject
    - (id)myFactoryMethod;
    @end
    

    应该变成

    @interface MyObject
    - (instancetype)myFactoryMethod;
    @end
    

    还有一种方法,你可以在xcode中使用Objective-C的转换器自动改变你的代码,方法是下面的用xcode重构代码

    用xcode重构代码

    xcode提供现代Objective-C转换工具,在开发工程中可以辅助我们,它可以识别并应用现代化工具转换代码,但它并不能解释代码的意思。例如:它不会知道你的-toggle方法会影响你的对象的状态,并且它可能会错误的认为这个行为是一个属性。所以凡是自动转换的代码都要手动进行审查和确认。

    它会帮我们做这些事情:

    • 在正确的地方把id转换为instancetype
    • 改变enum成为NS_ENUM或NS_OPTIONS
    • 更新@property语法

    除了这些,它还会更改你的代码的地方如下:

    • 转换成文字,所以这样的声明[NSNumber numberWithInt:3]成为@3。
    • 使用加下标,所以这样的声明[dictionary setObject:@3 forKey:key]成为dictionary[key]= @3。

    使用这种模式,选择Edit > Refactor > Convert to Modern Objective-C Syntax.

    属性

    使用@property声明属性比使用实例变量带来的好处是:

    • 自动生成getters和setters方法
    • 更好的声明一套方法的意图,这样使得编辑器更好的知道getter和setter方法是干什么的
    • 会提供一些关于行为的信息,因为这样声明的属性会带有assign (vs copy), weak, atomic (vs nonatomic),等等

    属性的名字有一套命名规则:属性的getter方法名就是属性的名字本身(例如:属性date的getter方法就是date),属性的setter方法就是在属性名前面加上set前缀(例如:属性date的setter方法就是setDate)。Boolean属性的getter方法以is开头

    @property (readonly, getter=isBlue) BOOL blue;
    

    这样做就能像下面这样使用了:

    if (color.blue) { }
    if (color.isBlue) { }
    if ([color isBlue]) { }
    

    枚举宏(Enumeration Macros)

    使用NS_ENUM 和 NS_OPTIONS宏定义枚举,可以明确的指定你的宏的类型和大小,,除此之外,这个语法在老的编辑器中也能被识别。

    使用NS_ENUM宏定义一组互斥的枚举值:

    typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
            UITableViewCellStyleDefault,
            UITableViewCellStyleValue1,
            UITableViewCellStyleValue2,
            UITableViewCellStyleSubtitle
    };
    

    NS_ENUM帮助定义名字和类型的列举,这里名字是UITableViewCellStyle,类型是NSInteger。这中类型的枚举应该是NSInteger。

    使用NS_OPTIONS定义一个可以组合的值:

    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
            UIViewAutoresizingNone                 = 0,
            UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
            UIViewAutoresizingFlexibleWidth        = 1 << 1,
            UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
            UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
            UIViewAutoresizingFlexibleHeight       = 1 << 4,
            UIViewAutoresizingFlexibleBottomMargin = 1 << 5
    };
    

    这种类型的枚举通常使用NSUInteger。

  • 相关阅读:
    初赛第四场B
    初赛第四场A
    初赛第六场C
    CF 365(2) C 思维,图形模拟 D 树状数组,离线处理,思维
    CF 725C 模拟 725D
    CF 378(2) C D 模拟
    CF 729D 模拟,思维
    CF 729C 模拟,二分
    CF 381(2) D. dfs序,二分,数组模拟维护
    CF 395(2) D.矩形上色,模拟
  • 原文地址:https://www.cnblogs.com/66it/p/4878262.html
Copyright © 2011-2022 走看看