iOS学习之new与allocinit,[NSArrayarray]和[[NSArrayalloc]init]及self.和_的区别

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

一 [className new]和 [[className alloc] init] 的区别

1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init]

但是并不意味着你不会接触到new,在一些代码中还是会看到[[className alloc] init],

还有去面试的时候,也很可能被问到这个问题。

2.那么,他们两者之间到底有什么区别呢

我们看源码:

+ new { id newObject = (*_alloc)((Class)self, 0); Class metaClass = self->isa; if (class_getVersion(metaClass) > 1) return [newObject init]; else return newObject; } //而 alloc/init 像这样: + alloc { return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); } - init { return self; } 通过源码中我们发现,[className new]基本等同于[[className alloc] init];

区别只在于alloc分配内存的时候使用了zone.

这个zone是个什么东东呢?

它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度;

3.而为什么不推荐使用new?

不知大家发现了没有:如果使用new的话,初始化方法被固定死只能调用init.

而你想调用initXXX怎么办?没门儿!据说最初的设计是完全借鉴Smalltalk语法来的。

传说那个时候已经有allocFromZone:这个方法,

但是这个方法需要传个参数id myCompanion = [[TheClass allocFromZone:[self zone]] init];

这个方法像下面这样:

+ allocFromZone:(void *) z { return (*_zoneAlloc)((Class)self, 0, z); } //后来简化为下面这个: + alloc { return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); } 但是,出现个问题:这个方法只是给对象分配了内存,并没有初始化实例变量。

是不是又回到new那样的处理方式:在方法内部隐式调用init方法呢?

后来发现“显示调用总比隐式调用要好”,所以后来就把两个方法分开了。

概括来说,new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。

差别在于,采用new的方式只能采用默认的init方法完成初始化,

采用alloc的方式可以用其他定制的初始化方法。

二 再来说一个突然想起来的问题:[NSArray array]和 [[NSArray alloc]init](包括字典等同类) 的使用方法的区别:

alloc (内存分配)以及init(初始化) Objective-C 协议分为非正式协议和正式协议 .

这两个方式都是建立一个空的Array

[NSArray array]不需要release,使用autoreleasepool机制。

[[NSArray alloc] init]需要自己手动release

项目使用崩溃实例:

在ViewDidLoad中

jsonDataDic = [NSMutableDictionary dictionary];

[self jsonParse];

创建一个空字典,在jsonParse中使用了这个词典,导致程序崩溃

解决方法:在jsonDataDic前面加上self.即可

原因:不加的话,指针的作用域仅在ViewDidLoad中,进入jsonParse后该指针已释放,成为了一个野指针,再对其进行操作,使程序崩溃。

注意:字典是没有顺序的,字典的allkeys或者allvalues存放到数组中是随机的。

总结:

new做的事情和alloc init是一样的,当然你要构造方法是init的时候完全可以用new来代替 ,alloc 不仅仅可以使用init构造方法,更可以自定义构造方法e.g initWithFrame等等。

另外,alloc开辟空间后能够自动清空新开辟内存空间中的老数据,不会出现莫名奇妙的错误,见《Objective-C基础教程》

说到这个问题,可能有小伙伴又懵了,那self.和 _有什么区别呢,再说下这两个 :

self.PRogramStack等于[self programStack],会走你的懒加载方法;而_programStack类似于self->_programStack。

用self点出属性是更好的选择,因为这样可以兼容懒加载,同时也避免了使用下划线的时候忽视了self这个指针,后者容易在block中造成循环引用。

科普:懒加载(Load On Demand)是一种独特而又强大的数据获取方法,它能够在用户滚动页面的时候自动获取更多的数据,而新得到的数据不会影响原有数据的显示,同时最大程度上减少服务器端的资源耗用。

这两种使用方式显然是不一样的。

主要是涉及到内存管理的问题。self.propertyName 使用self. 是对属性的访问。使用_ 是对局部变量的访问。

所有被声明为属性的成员,在ios5 之前需要使用编译器指令@synthesize 来告诉编译器帮助生成属性的getter,setter方法。之后这个指令可以不用人为指定了,默认情况下编译器会帮我们生成。 编译器在生成getter,setter方法时是有优先级的,它首先查找当前的类中用户是否已定义属性的getter,setter方法,如果有,则编译器会跳过,不会再生成,使用用户定义的方法。 也就是说你在使用self.propertyName 时是在调用一个方法。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航