• iOS开发学习笔记-创建和初始化对象


    Objective-C中对象的创建和初始化
    (Allocating and Initializing Objects)
    (主要内容来自于Apple的电子书《The Objective-C Programming Language》的“Allocating and Initializing Objects”。电子书可以从iBooks商店下载。iOS Developer Library也有同名的文档,但是内容上是不同的。)


    在Objective-C中创建对象分为两步:
    1 开辟一个对象所需的内存,Allocating object
    2 为对象的各个成员赋予初始值,Initializing object

    开辟内存这个步骤很简单。一般来说,Objective-C中的所有类都继承于NSObject。NSObject定义了两个方法——alloc和allocWithZone:。子类不用重载和修改这两个方法。直接使用就能开辟创建一个自己子类对象所需的内存。

    重要的工作在第二步。

    初始化对象的方法一般以init开头,比如无参数的init方法,或者initWithFrame:方法。NSObject类定义了init方法。一般而言,子类需要根据自己需要,定义自己的初始化方法。

    初始化方法返回的对象(返回值)
    需要注意的是,初始化方法(init...)的返回值不一定和该方法的接收者(或者以C语言角度来说是调用者)同类型的对象。如果初始化失败,返回的对象则是nil。比如依靠一个文件来初始化对象,如果打开文件失败,那么返回的对象是nil。
    下面的代码是危险的:
    id aObject = [SomeClass alloc];
    [aObject init]; //在这里返回值不一定就是aObject,
    [aObject someOtherMessage]; //实际应该someOtherMessage的接收者应该是init的返回值,而不是aObject
    正确的写法如下:
    id aObject = [SomeClass alloc] init];
    [aObject someOtherMessage];


    实现初始化方法时需要注意的地方
    ~方法的名字应该以init开头
    ~方法的返回值类型应该是id
    ~在实现中需要调用designated initializer(什么是designated initiailizer后面会提到)。一个类有很多初始化方法,其中一个(或者一些)叫designated initializer(翻译成?“指定的初始化方法”?)。实现子类的designated initializer时,必须调用父类的designated initializer。实现子类的其他初始化方法时,需要直接或者间接地调用一下自己的designated initializer。
    NSObject的designated initializer方法是init。
    ~在初始化方法里设置成员变量时不要使用accessor method(访问方法)。
    ~把初始化方法的返回值赋给self。
    ~返回self,或者如果初始化失败,返回nil。

    初始化失败时的处理
    如果失败返回nil, 另外如有必要对self调用release方法。
    - (id) init {
      self = [super init]; //给self赋值; 调用super的designated initializer
      if (self) { //只有super的init返回的值不是nil才做下面的事情
        theDate = [ [NSDate alloc] init];
      }
      return self; //如果失败返回,self的值是nil,返回的nil
    }
    另一个例子:
    - (id) iniWithImage:(NSImage *) aImage {
      if (aImage == nil) {
        [self release]; //如果传入的参数有问题,那么调用self的release方法
        return nil;
      }
      self = [super init_xxx: yyy];
      if (self) {
        image = [aImage retian];
      }
      return self;
    }



    子类需要确保所有从父类继承而来的初始化方法都能正确工作。
    比如类A定义了init方法;子类B定义了initWithName方法。类B要保证init消息也能正确地初始化类B。一个简单的方法是类B的init调用类B的initWithName方法来实现自己:
    - init {
      return [self initWithName:"default"];
    }


    The Designated Initializer
    一个类的designated initializer确保所有继承而来的成员都被初始化(通过调用super的方法),同时也做了其他的大部分工作。这个类的其他初始化方法调用这个designated initializer。
    一个类的designated initializer方法必须调用父类的designated initializer,而不是父类的其他初始化方法。如果不这么做可能会引起死循环。
    (具体例子见电子书)


    合并开辟内存和初始化内存这两个步骤(Combine allocation and initialization)
    有些类提供了一些方法,在这些方法里实现了内存开辟和内存初始化这两个步骤。这些方法被称为convenience constructors(便利的构造函数)。一般形式是+className...。
    比如NSArray提供了:
    + (id) array;
    + (id) arrayWithObjects:(id) firstObj, ...;
    有时候这些方法很有用。比如,+ (id) arrayWithObjects:(id) firstObj, ...,只有知道了参数的个数才能知道应该分配多大的内存。所以不能将开辟内存和初始化内存这两个步骤分开。
    再看下面的例子(singleton),如果对象已有就直接返回已有对象,没必要开辟内存:
    + (Soloist *) soloist {
      static Soloist *instance = nil; //note: static
      if (instance == nil) {
        instance = [self alloc] init];
      }
      return instance;
    }
    (返回类型是Soloist *,不是id,在这种情况下是合适的)

  • 相关阅读:
    计算机网络【10】—— Cookie与Session
    计算机网络【9】—— HTTP1.0和HTTP1.1的区别及常见状态码
    计算机网络【8】—— Get和Post请求的区别
    计算机网络【7】—— TCP的精髓
    数据库事务的四大特性以及事务的隔离级别
    JavaWeb基础【1】—— Tomcat
    Get current time and date on Android
    Converting Storyboard from iPhone to iPad
    iPhone OS 开发
    (译)iOS Code Signing: 解惑
  • 原文地址:https://www.cnblogs.com/ljwiOS/p/4817030.html
Copyright © 2020-2023  润新知