不須要釋放
markdown
咱們知道當一個對象銷燬的時候會調用dealloc
方法,那麼咱們先看下dealloc
都進行了哪些操做。ide
dealloc
函數調用了_objc_rootDealloc
函數_objc_rootDealloc
函數調用rootDealloc
函數void
_objc_rootDealloc(id obj)
{
ASSERT(obj);
obj->rootDealloc();
}
複製代碼
rootDealloc
函數查看inline void
objc_object::rootDealloc()
{
if (isTaggedPointer()) return; // fixme necessary?
if (fastpath(isa.nonpointer &&
!isa.weakly_referenced &&
!isa.has_assoc &&
!isa.has_cxx_dtor &&
!isa.has_sidetable_rc))
{
assert(!sidetable_present());
free(this);
}
else {
object_dispose((id)this);
}
}
複製代碼
從rootDealloc
函數中咱們看到了判斷isa相關屬性的地方,實際上當一個對象存在會進入else
中,即object_dispose
函數函數
object_dispose
函數查看id
object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
複製代碼
經過objc_destructInstance
函數找到對象,而後free
,咱們看objc_destructInstance
函數this
objc_destructInstance
函數重點查看
_object_remove_assocations
函數spa
_object_remove_assocations
函數分析非+load
方法同名時,分類的方法在類的方法前面(注意不是覆蓋
),由於分類的方法是在類realize以後 attach進去的
,因此 優先分類,其次類
+load
方法同名時,優先類,其次分類
@property
定義的變量只會生成setter
以及getter
方法的聲明,可是不會生成對應的方法實現以及帶有下劃線的成員變量
@property
定義的變量只能是這個ViewController的.m文件使用runtime是由C和C++彙編實現的一套API,爲OC語言添加了面向對象和運行時功能。3d
方法的本質是消息的發送
,涉及到消息發送的流程有指針
objc_msgSend
~cache_t中查找lookUpImpOrForward
resolveInstanceMethod
forwardingTargetForSelector
mesthodSignatureForSelector & forwardInvocation
編譯後實例變量存儲到 ro 中,一旦編譯完成,內存結構就徹底肯定了,沒法再次修改
咱們先看如下以下代碼打印結果,其中self是LGTeacher類,LGTeacher繼承於LGPerson,LGPerson繼承於NSObject從打印結果中咱們看到不管是
[self class]
仍是[super class]
的結果是同樣的,爲何呢?code
(id self , sel _cmd)
,其中self
是消息接收者。對於[self class]
來講,它的消息接收者是 自身LGTeacher
沒什麼可說的,因此打印的是LGTeacher
。super
只是關鍵字,它意思是說從父類調用方法,所以[super class]
就是直接調用的就是父類的class
方法,它的本質是objc_msgSendSuper
,只是objc_msgSendSuper
速度更快,直接跳過self
。但須要注意的是,[super class]
的消息接受者依然是LGTeacher
,因此最終打印的是LGTeacher
。咱們先準備代碼,定義IFPerson
類,代碼以下咱們再看ViewController代碼
從上述代碼中咱們延伸出兩個問題:
代碼是否崩潰
、doSomething打印結果是什麼
。先不回答這兩個問題,咱們運行代碼看結果如何,運行結果以下圖 從運行結果中咱們能夠看出
代碼不會崩潰且運行結果也出來了
.orm
[(__bridge id)kc doSomething]
爲何不會崩潰?首先咱們知道對於一個對象,它的指針地址指向的是isa
,同時isa
地址指向當前的class
,因此kc
指向的是IFPerson
的isa
,而person
的指針指向的也是isa
,這樣它們都是isa
從cache_t
中查找doSomething
方法,所以不會崩潰。對象
[(__bridge id)kc doSomething]
打印的結果是ViewController
?[person doSomething]
打印出出來shifx
是沒有什麼問題的,畢竟給person.name賦值shifx
,可是[(__bridge id)kc doSomething]
打印的結果是ViewController
呢?要解決這個問題首先咱們須要知道person
可以找到name
是指針從isa內存平移了8個字節
移動到了name
。那麼對於kc
來講,它也須要指針平移,可是爲何平移後的結果是viewController
呢?這就須要明白棧地址是從高到低存儲的,且是先進後出
,因爲前面先調用了[super viewDidLoad]
方法,且viewDidLoad
的隱藏參數是(id self, SEL _cmd)
,因此self
會先入棧,其次是cls
->kc
->person
,出棧的順序恰好相反,因爲[(__bridge id)kc doSomething]
時須要指針平移,天然指向了self(即ViewController)
,因此打印的結果是ViewController
。IFPerson *person = [[IFPerson alloc] init]
放在[super viewDidLoad]
以後,即此時咱們按照咱們上面的分析self
會先入棧,其次是person
->cls
->kc
,猜想[(__bridge id)kc doSomething]
打印結果應該是IFPerson (person的isa指向其Class)
,咱們運行代碼結果能夠看出咱們的分析是正確的。