美文网首页
OC为何很少new一个对象?

OC为何很少new一个对象?

作者: Invisible_He | 来源:发表于2021-03-05 14:44 被阅读0次
    image.png

    前言

    对于OC,我们最常用的生成一个对象的方式是下面这样的

    NSObject *obj = [[NSObject alloc] init];
    

    当然也会有下面这种方式

    NSObject *obj = [NSObject new];
    

    但是这种方式是很少用的。对于大部分人的理解,其实new的效果和结果是和alloc组合init是一样的,那么既然如此,为何大家均选择了调用两个方法的稍微复杂点的方式,而并没选择调用一个方法new的简单方式呢?

    OC为何很少new一个对象?

    苹果官方解释

    下面是苹果官方文档

    Type Method
    
    # new
    
    Allocates a new instance of the receiving class, sends it an [init] 
    message, and returns the initialized object.
    
    Framework
    
    *   Objective-C Runtime
    
    ## Declaration
    
    + (instancetype)new;
    
    ## Return Value
    
    A new instance of the receiver.
    
    ## Discussion
    
    This method is a combination of [alloc] and [init]. Like [alloc], it 
    initializes the `isa` instance variable of the new object so it points to 
    the class data structure. It then invokes the [init] method to complete 
    the initialization process.
    

    关键则是后面的两句

    Allocates a new instance of the receiving class, sends it an [init] 
    message, and returns the initialized object.
    //生成一个新的实例对象,并发送一个[init]方法,然后返回初始化过的对象
    This method is a combination of [alloc] and [init]. Like [alloc], it 
    initializes the `isa` instance variable of the new object so it points to 
    the class data structure. It then invokes the [init] method to complete 
    the initialization process.
    //[new]方法是后面两个方法的结合,也就是:[alloc]和[init].  [alloc]:
    初始化一个新对象的isa实例变量,并且指向其对应的类数据结构。然后调用[init]方法去完成初始化过程
    

    从解释可以看出,[new]方法是后面两个方法的结合,也就是:[alloc]和[init]。并且作用也是和这两个方法是一样的。从权威的官方文档解释,我们仍然看不出两者之间的区别。

    GNUstep解释

    偶然间,我在另一个权威的代码文档中发现了他们之间的不同点,那就是GNUstep。GNUstep是GNU对OC的开源,可以说是除苹果外,对于OC最权威以及正确的一份代码资料了。下面则是GNUstep对于new的解释

    /**
     *   This method is a short-hand for alloc followed by init, that is,
     *    NSObject *object = [NSObject new];
    
     * is exactly the same as
     *    NSObject *object = [[NSObject alloc] init];
    
     *   This is a general convention: all <code>new...</code>
     *   methods are supposed to return a newly allocated and
     *   initialized instance, as would be generated by an
     *   <code>alloc</code> method followed by a corresponding
     *   <code>init...</code> method.  Please note that if you are
     *   not using a garbage collector, this means that instances
     *   generated by the <code>new...</code> methods are not
     *   autoreleased, that is, you are responsible for releasing
     *   (autoreleasing) the instances yourself.  So when you use
     *   <code>new</code> you typically do something like:
    
     *      NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);
    
     *   You do not normally need to override <code>new</code> in
     *   subclasses, because if you override <code>init</code> (and
     *   optionally <code>allocWithZone:</code> if you really
     *   need), <code>new</code> will automatically use your
     *   subclass methods.
    
     *   You might need instead to define new <code>new...</code>
     *   methods specific to your subclass to match any
     *   <code>init...</code> specific to your subclass.  For
     *   example, if your subclass defines an instance method
    
     *   initWithName:
    
     *   it might be handy for you to have a class method
    
     *    newWithName:
    
     *   which combines <code>alloc</code> and
     *   <code>initWithName:</code>.  You would implement it as follows:
    
    
     *     + (id) newWithName: (NSString *)aName
     *     {
     *       return [[self alloc] initWithName: aName];
     *     }
     */
    + (id) new
    {
      return [[self alloc] init];
    }
    

    我给大家找出了关键点,如下

     *   Please note that if you are
     *   not using a garbage collector, this means that instances
     *   generated by the <code>new...</code> methods are not
     *   autoreleased, that is, you are responsible for releasing
     *   (autoreleasing) the instances yourself.  So when you use
     *   <code>new</code> you typically do something like:
    
     *      NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);
    

    这句话的意思很明显了,就是说,如果你没使用垃圾回收(这里的意思是指,ARC,因为OC一直是一门具有垃圾回收机制的一门语言)的话,也就是在MRC下,使用new生成的实例对象,将不会自动释放,将由你手动管理对象的release。
    其实我理解这句话的意思就是,如果在MRC下,使用new的时候,写代码的话,主要就得写成下面这样:

    NSMutableArray *array = AUTORELEASE ([NSMutableArray new]);
    

    这样的写法也是和普通的写法有很大不同的,之后现在在来看看这个AUTORELEASE


    image.png

    从图中可以看到:AUTORELEASE函数的这种隐式声明早已经在c99就不合法了。

    最终解释

    OC是一门上世纪八十年代就诞生的一门语言,但是ARC则是Xcode4开始才支持的,而Xcode4则是在2011年才发布的。也就是说,在长达接近三十年的时间里,OC都是在MRC下编写代码的,从上面GNU文档里的解释可以看出:
    1、在MRC下,new的对象release方式的不同点,因此大家就选择了相对复杂的[alloc]和[init]的组合方式,并在长达三十年的代码风格中形成了风俗和习惯,并衍生至今。
    2、当然,如果用new生成一个对象的话,那么初始化方法就只能调用到init,而不能调用到自定义的initWith等方法,然而我们实际开发中,却常自定义init方法,因此new就在此种情况下不太合适

    image.png image.png

    从上面文档解释也能知道的一点是:在如今的ARC下,其实[new]和[[alloc] init]是没什么区别的,从官方文档的解释和GNU源码也能看得出来,他两是一样的。

    相关文章

      网友评论

          本文标题:OC为何很少new一个对象?

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