新手開發IOS的疑惑,待補充


 

1.Prefix.pch 是做什么用的?

是一個加快編譯速度的工具。只有永遠不會變化或很少發生變化的頭文件才能被添加到前綴文件中。這樣做可以使框架的代碼提前編譯,並對所有類可見。但是,如果添加到前綴文件中的頭文件發生變化,那么所有的代碼會被重新編譯,這也是為什么只能向前綴文件添加不變文件的原因。

2.if((self = [super init])) 為什么會這么寫?

- (id) init
{
    if((self = [super init]))
    {
        //do init stuff here ...
    }
    return self;
}

在 self = [super init] 的調用中,self被賦值為向父對象發送 init 消息后的返回值。如果你之前是一名C++程序員,看到這一幕一定會感到痛苦萬分。請不必太過沮喪。這行代碼表示:在Objective-C中,我們必須手動調用父類的 init 方法,改操作不會自動完成。我們之所以用 self 來接受返回值,是為了防止返回值為 nil 的情況發生。

如果你無法很好的理解Objective-C程序員調用[super init]的方式,另一種方法也許能令你比較容易接受。這種方式基本上和上面的方法一樣,但它也是有別於傳統的寫法的:

- (id) init
{
    self = [super init];
    if(self != nil)
    {
        //do init stuff here ...
    }
    return self;
}

3.IOS目前版本的內存管理差異

iOS6.0以前版本

UIViewController 增加了 viewDidUnload 方法。該方法和 viewDIdLoad 相配對。當系統內存不足時,首先 UIViewController 的 didReceiveMemoryWarining 方法會被調用,而 didReceiveMemoryWarining 會判斷當前 ViewController 的 view 是否顯示在 window 上,如果沒有顯示在 window 上,則 didReceiveMemoryWarining 會自動將 viewcontroller 的view 以及其所有子  view全部銷毀,然后調用 viewcontroller 的 viewdidunload 方法。如果當前 UIViewController 的 view 顯示在 window 上,則不銷毀該 viewcontroller 的 view,當然,viewDidunload 也不會被調用了。

收到內存警告:調用 didReceiveMemoryWarning 內調用 super 的 didReceiveMemoryWarning 會將 controller 的 view 進行釋放。所以我們不能將controller的view再次釋放。
處理方法:

-(void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];//如沒有顯示在window上,會自動將self.view釋放。
    // ios6.0以前,不用在此做處理,self.view釋放之后,會調用下面的viewDidUnload函數,在viewDidUnload函數中做處理就可以了。
}
-(void)viewDidUnload
{
    // Release any retained subviews of the main view.不包含self.view
    [super viewDidUnload];
    //處理一些內存和資源問題。
}

但是到了IOS 6.0之后,這里又有所變化,IOS 6.0內存警告的 viewDidUnload 被屏蔽,即又回到了IOS 6.0以前版本時期的內存管理方式。   

收到內存警告:調用 didReceiveMemoryWarning 內調用 super 的 didReceiveMemoryWarning 調只是釋放 controller 的 resouse,不會釋放view。
處理方法:

-(void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];//即使沒有顯示在window上,也不會自動的將self.view釋放。
    // Add code to clean up any of your own resources that are no longer necessary.
    
    // 此處做兼容處理需要加上ios6.0的宏開關,保證是在6.0下使用的,6.0以前屏蔽以下代碼,否則會在下面使用self.view時自動加載viewDidLoad
    if ([self.view window] == nil)// 是否是正在使用的視圖
    {
        // Add code to preserve data stored in the views that might be
        // needed later.
        
        // Add code to clean up other strong references to the view in
        // the view hierarchy.
        self.view = nil;// 目的是再次進入時能夠重新加載調用viewDidLoad函數。
    }
}

 

 4.消息調度 @selector

 看到 @selector(...) 語句的時候可能覺得有些陌生,這在 Objective-C 中用來指定某個特定方法。關鍵在於,絕不能忘記函數后面的冒號!冒號告訴 Objective-C:“去找一個名為XXX的方
 法,這個方法有且只有一個參數”。如果忘記寫冒號,編譯器還是可以通過的,但是程序一運行就會發生崩潰。在 Debugger Console 窗口中,你會看到這樣的錯誤日志:“unrecoginized  
 selector sent to instance...”。

 @selector(...) 中的冒號個數一定要與所指定的方法參數個數相同。例如:

- (void) example:(ccTime)delta sender:(id)sender flag:(bool)aBool

 那么,對應的@selector語句就應該是:

@selector(example:sender:flag:);

 不論是在調度消息時還是在其他情況下使用 @selector(...), 都需要注意一個很重要的問題:在默認情況下,如果方法名不存在,編譯器並不會報錯;但是,一旦程序運行時調用用了指向不存在的方法的 @selector 語句,應用程序就會立即崩潰。由於這個調用是在內部完成的,所以很難找到問題所在。好在,xcode可以設置來強制編譯器報錯。

如圖:

 

5.#import與@class的區別

1.import會包含這個類的所有信息,包括實體變量和方法,而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,后面會再告訴你。

2.在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變量和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。 而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。

3.在編譯效率方面考慮,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,后面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。

4.如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那么就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。

所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個類型來用的。 在實現這個接口的實現類中,如果需要引用這個類的實體變量或者方法之類的,還是需要import在@class中聲明的類進來.

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM