在探索Alloc
与Init
时,先输出两个对象的地址以及指向对象指针的地址,查看有什么区别。下面是一段Objective-C
的代码
UIView *p1 = [UIView alloc];
UIView *p2 = [UIView alloc];
UIView *p3 = [p1 init];
UIView *p4 = [p2 init];
UIView *p5 = [p2 init];
NSLog(@"对象p1%@ - 指针地址%p",p1,&p1);
NSLog(@"对象p2%@ - 指针地址%p",p2,&p2);
NSLog(@"对象p3%@ - 指针地址%p",p3,&p3);
NSLog(@"对象p4%@ - 指针地址%p",p4,&p4);
NSLog(@"对象p5%@ - 指针地址%p",p5,&p5);
得到结果,可知P1 与 P3 指向地址空间相同, 指针地址不同;P2 与 P4、P5 指向地址空间相同,指针地址不同

如何查看alloc方法源码出处
通过添加断点进行查看
-
在代码处添加断点
添加断点.png
-
按住ctrl键,点step按钮
Step.png
-
查看系统函数
objc_alloc
ojbc_alloc.png
-
添加符号断点
objc_alloc
Symbol.png
-
找到对应库
libobjc.A.dylib.png
alloc
的流程
通过在objc源码 找到NSObject.mm
中我们找到alloc
方法的实现。
alloc
在alloc
类方法下,执行_objc_rootAlloc
函数。
+ (id)alloc {
return _objc_rootAlloc(self);
}
_objc_rootAlloc
在_objc_rootAlloc
函数内,执行callAlloc函数
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
callAlloc
通过符号断点调试,发现在callAlloc
函数下执行objc-runtime-new.mm
文件下的_objc_rootAllocWithZone
函数。
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
if (slowpath(checkNil && !cls)) return nil;
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
return _objc_rootAllocWithZone(cls, nil);
}
#endif
// No shortcuts available.
if (allocWithZone) {
return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
}
return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
_objc_rootAllocWithZone
在_objc_rootAllocWithZone
,执行_class_createInstanceFromZone
函数
id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
// allocWithZone under __OBJC2__ ignores the zone parameter
return _class_createInstanceFromZone(cls, 0, nil,
OBJECT_CONSTRUCT_CALL_BADALLOC);
}
_class_createInstanceFromZone
(核心函数)
- 计算开辟空间的大小
cls->instanceSize
,(16字节对齐) - 开辟内存空间
calloc
- 将指针与类进行绑定
obj->initInstanceIsa
static ALWAYS_INLINE id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
int construct_flags = OBJECT_CONSTRUCT_NONE,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
ASSERT(cls->isRealized());
// Read class's info bits all at once for performance
bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
size_t size;
size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
if (zone) {
obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (slowpath(!obj)) {
if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
return _objc_callBadAllocHandler(cls);
}
return nil;
}
if (!zone && fast) {
obj->initInstanceIsa(cls, hasCxxDtor);
} else {
// Use raw pointer isa on the assumption that they might be
// doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (fastpath(!hasCxxCtor)) {
return obj;
}
construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
return object_cxxConstructFromClass(obj, cls, construct_flags);
}
Init
Init
方法
- (id)init {
return _objc_rootInit(self);
}
_objc_rootInit
函数
id
_objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}
通过查看源码,我们可以发现init
返回的是它本身。
new
new
函数中直接调用了callAlloc
函数,且调用了init函数,所以可以得出new 其实就等价于 [alloc init]
的结论。
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}
网友评论