iOS开发中 new与alloc/init的区别 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的区别

[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 时是在调用一个方法。

你可能感兴趣的:(iOS开发中 new与alloc/init的区别 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的区别)