1. 程式人生 > >【IOS學習】基礎知識積累

【IOS學習】基礎知識積累

一.iOS開發之loadViewviewDidLoadviewDidUnload的關係

1.第一次訪問UIViewController的view時,view為nil,然後就會呼叫loadView方法建立view

2.view建立完畢後會呼叫viewDidLoad方法進行介面元素的初始化

3.當記憶體警告時,系統可能會釋放UIViewController的view,將view賦值為nil,並且呼叫viewDidUnload方法

4.當再次訪問UIViewController的view時,view已經在3中被賦值為nil,所以又會呼叫loadView方法重新建立view

5.view被重新建立完畢後,還是會呼叫viewDidLoad方法進行介面元素的初始化

二.load和initialize的區別

  1. @implementation Person  
  2. // 只要程式啟動就會將所有類的程式碼載入到記憶體中, 放到程式碼區(無論該類有沒有被使用到都會被呼叫)
  3. // load方法會在當前類被載入到記憶體的時候呼叫, 有且僅會呼叫一次
  4. // 如果存在繼承關係, 會先呼叫父類的load方法, 再呼叫子類的load方法
  5. + (void)load  
  6. {  
  7.     NSLog(@"Person類被載入到記憶體了");  
  8. }  
  9. // 噹噹前類第一次被使用的時候就會呼叫(建立類物件的時候)
  10. // initialize方法在整個程式的執行過程中只會被呼叫一次, 無論你使用多少次這個類都只會呼叫一次
  11. // initialize用於對某一個類進行一次性的初始化
  12. // initialize和load一樣, 如果存在繼承關係, 會先呼叫父類的initialize再呼叫子類的initialize
  13. + (void)initialize  
  14. {  
  15.     NSLog(@"Person initialize");  
  16. }  
  17. @end

1、+load方法當類或分類新增到object-c runtime時被呼叫,子類的+load方法會在它所有父類的+load方法之後執行,而分類的+load方法會在它的主類的+load方法之後執行。但不同的類之間的+load方法的呼叫順序是不確定的,所以不要在此方法中用另一個類。

2、+load方法不像普通方法一樣,它不遵循那套繼承規則。如果某個類本身沒有實現+load方法,那麼不管其它各級超類是否實現此方法,系統都不會呼叫。+load方法呼叫順序是:SuperClass -->SubClass --> CategaryClass。

3、+initialize是在類或者它的子類接受第一條訊息前被呼叫,但是在它的超類接收到initialize之後。也就是說+initialize是以懶載入的方式被呼叫的,如果程式一直沒有給某個類或它的子類傳送訊息,那麼這個類的+initialize方法是不會被呼叫的。

4、+initialize方法和+load方法還有個區別,就是執行期系統完整度上來講,此時可以安全使用並呼叫任意類中的任意方法。而且,執行期系統也能確保+initialize方法一定會在“執行緒安全的環境”中執行,這就是說,只有執行+initialize的那個執行緒可以操作類或類例項,其他執行緒都要阻塞等著+initialize執行完。

5、+initialize方法和其他類一樣,如果某個類未實現它,而其超類實現了,那麼就會執行超類的實現程式碼。如果本身和超類都沒有實現,超類的分類實現了,就會去呼叫分類的initialize方法。如果本身沒有實現,超類和父類的分類實現了就會去調分類的initialize方法。不管是在超類中還是分類中實現initialize方法都會被調多次,呼叫順序是SuperClass -->SubClass。            

三. UIWindow使用

1) 同一層級的 最後一個顯示出來,上一個被覆蓋

2)UIWindow在顯示的時候是不管KeyWindow是誰,都是Level優先的,即Level最高的始終顯示在最前面。

3)誰最後設定的 makeKeyAndVisible 誰就是keyWindow 其他的也會顯示出來 所有的window都可以監聽鍵盤 和點選的事件 

UIView的功能 

負責渲染區域的內容,並且響應該區域內發生的觸控事件

UIWindow

在iOS App中,UIWindow是最頂層的介面內容,我們使用UIWindow和UIView來呈現介面。UIWindow並不包含任何預設的內容,但是它被當作UIView的容器,用於放置應用中所有的UIView。

從繼承關係來看,UIWindow繼承自UIView,所以UIWindow除了具有UIView的所有功能之外,還增加了一些特有的屬性和方法,而我們最常用的方法,就是在App剛啟動時,呼叫UIWindow的rootViewController(必須指定根控制器) 和 makeKeyAndVisible方法

狀態列和鍵盤都是特殊的UIWindow。

UIWindow的主要作用有

1.作為UIView的最頂層容器,包含應用顯示所有的UIView;

2.傳遞觸控訊息和鍵盤事件給UIView;

UIWindow的層級:

UIWindow的層級由一個UIWindowLevel型別屬性windowLevel,該屬性指示了UIWindow的層級,windowLevel有三種可取值。

並且層級是可以做加減的self.window.windowLevel = UIWindowLevelAlert+1;

Normal ,StatusBar,Alert.輸出他們三個層級的值,我們發現從左到右依次是0,1000,2000,也就是說Normal級別是最低的,StatusBar處於中級,Alert級別最高。而通常我們的程式的介面都是處於Normal這個級別的,系統頂部的狀態列應該是處於StatusBar級別,提醒使用者等操作位於Alert級別。根據window顯示級別優先原則,級別高的會顯示在最上層,級別低的在下面,我們程式正常顯示的view在最底層;

四.NS_ENUM & NS_OPTIONS

從列舉定義來看,NS_ENUM和NS_OPTIONS本質是一樣的,僅僅從字面上來區分其用途。NS_ENUM是通用情況,NS_OPTIONS一般用來定義具有位移操作或特點的情況(bitmask)。

    1.當前viewController隱藏本頁面的鍵盤

    很容易。直接呼叫 [textfield resignFirstResponder]即可。

2.目前前遇到一個需求

     ControllerA出來時候,隱藏當前top 任意view的鍵盤。那麼可以使用這個

  1. [[[UIApplication sharedApplication] keyWindow] endEditing:YES];  
這是有根據的,OC sdk中有一個UIView的類別,就是endEditing。可以參考UITextField.h的標頭檔案
  1. @interface UIView (UITextField)  
  2. - (BOOL)endEditing:(BOOL)force;    // use to make the view or any subview that is the first responder resign (optionally force)
  3. @end

3.如果不方便獲取當前view

    可以使用該方法

  1. [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponser) to:nil from:nil forEvent:nil];  

六.isKindOfClass和isMemberOfClass的區別

isKindOfClass和isMemberOfClass 都是NSObject的比較Class的方法

  但兩個有很大區別:
  isKindOfClass來確定一個物件是否是一個類的成員,或者是派生自該類的成員
  isMemberOfClass只能確定一個物件是否是當前類的成員
  例如:我們已經成NSObject派生了自己的類,isMemberOfClass不能檢測任何的類都是基於NSObject類這一事實,而isKindOfClass可以。
  [[NSMutableData data] isKindOfClass:[NSData class]]; // YES [[NSMutableData data] isMemberOfClass:[NSData class]]; // NO

七.NSString屬性什麼時候用copy,什麼時候用strong

由於NSMutableString是NSString的子類,所以一個NSString指標可以指向NSMutableString物件,讓我們的strongString指標指向一個可變字串是OK的。

而上面的例子可以看出,當源字串是NSString時,由於字串是不可變的,所以,不管是strong還是copy屬性的物件,都是指向源物件,copy操作只是做了次淺拷貝。

當源字串是NSMutableString時,strong屬性只是增加了源字串的引用計數,而copy屬性則是對源字串做了次深拷貝,產生一個新的物件,且copy屬性物件指向這個新的物件。另外需要注意的是,這個copy屬性物件的型別始終是NSString,而不是NSMutableString,因此其是不可變的。

這裡還有一個性能問題,即在源字串是NSMutableString,strong是單純的增加物件的引用計數,而copy操作是執行了一次深拷貝,所以效能上會有所差異。而如果源字串是NSString時,則沒有這個問題。

所以,在宣告NSString屬性時,到底是選擇strong還是copy,可以根據實際情況來定。不過,一般我們將物件宣告為NSString時,都不希望它改變,所以大多數情況下,我們建議用copy,以免因可變字串的修改導致的一些非預期問題。

八.NSArray 各種遍歷方式

 程式設計中經常需要遍歷collection元素,做法有標準的for迴圈,OC1.0的NSEnumerator和OC2.0的fast NSEnumerator。語言引入“塊”這一特性後,又多出來幾種新的遍歷方式。

    for迴圈大家很熟悉,很簡單。但是遍歷字典和set的時候就稍麻煩,for迴圈有一個優勢,可以反向遍歷。在刪除陣列中一個元素的時候採用反向遍歷

    OC 1.0的NSEnumerator是個抽象基類,定義了兩個方法,供具體的子類實現

  1. -(NSArray*) allObjects;  
  2. -(id) nextObject;  

    舉例,遍歷數字

  1. NSArray *anArray=/*....*/;  
  2. NSEnumerator *enumerator = [anArray objectEnumerator];  
  3. id object;  
  4. while((object = [enumerator nextObject]) != nil){  
  5.     //do something 
  6. }  

快速遍歷,就是for-in語句

直接上程式碼,這種辦法比上面兩種都高效,安全,簡單,強烈推薦!在刪除陣列元素的時候,同樣可以反序執行。

  1. NSArray *anArray=/*...*/;  
  2. for (id object in anArray){  
  3.     //do something 
  4. }  
  5. //dictionary
  6. NSDictionary* dic = /*...*/;  
  7. for(id key in dic){  
  8.     id value = dic[key];  
  9.     //do something 
  10. }  
  11. //set
  12. NSSet *aSet = /*...*/;  
  13. for (id object in aSet){  
  14.     //do something 
  15. }  
  16. //反向遍歷
  17. NSArray *anArray=/*...*/;  
  18. for (id object in [anArray reverseObjectEnumerator]){  
  19.     //do something 
  20. }  

基於塊的變數方式

    當前OC中,最新引入的一種做法句ishi基於塊來遍歷。這種做法比前三種效率都高,但是程式碼量比for-in多。

  1. NSArray *anArray=/*...*/;  
  2. [anArray enumerateObjectUsingBlock]:  
  3.     ^(id object,NSUInter idx,BOOLBOOL *stop){  
  4.         // do something
  5.         if(shouldStop){  
  6.             *stop = yes;  
  7.         }  
  8.     }];  
其他collection類似

%@     物件

%d, %i 整數

%u     無符整形

%f     浮點/雙字

%x, %X 二進位制整數

%o     八進位制整數

%zu    size_t

%p     指標

%e     浮點/雙字 (科學計算)

%g     浮點/雙字

%s     C 字串

%.*s   Pascal字串

%c     字元

%C     unichar

%lld   64位長整數(long long)

%llu   無符64位長整數

%Lf    64位雙字

%e 是實數,用科學計數法計的

十.iOS 中幾種常用的鎖總結

多執行緒程式設計中,應該儘量避免資源線上程之間共享,以減少執行緒間的相互作用。 但是總是有多個執行緒相互干擾的情況(如多個執行緒訪問一個資源)。線上程必須互動的情況下,就需要一些同步工具,來確保當它們互動的時候是安全的。

鎖是執行緒程式設計同步工具的基礎。iOS開發中常用的鎖有如下幾種:

  1. @synchronized
  2. NSLock 物件鎖
  3. NSRecursiveLock 遞迴鎖
  4. NSConditionLock 條件鎖
  5. pthread_mutex 互斥鎖(C語言)
  6. dispatch_semaphore 訊號量實現加鎖(GCD)
  7. OSSpinLock (暫不建議使用,原因參見這裡


十一.記憶體洩露

ARC已經出來很久了,自動釋放記憶體的確很方便,但是並非絕對安全絕對不會產生記憶體洩露。導致iOS物件無法按預期釋放的一個無形殺手是——迴圈引用。迴圈引用可以簡單理解為A引用了B,而B又引用了A,雙方都同時保持對方的一個引用,導致任何時候引用計數都不為0,始終無法釋放。若當前物件是一個ViewController,則在dismiss或者pop之後其dealloc無法被呼叫,在頻繁的push或者present之後記憶體暴增,然後APP就duang地掛了。下面列舉我們變成中比較容易碰到的三種迴圈引用的情形。

(1)計時器NSTimer

一方面,NSTimer經常會被作為某個類的成員變數,而NSTimer初始化時要指定self為target,容易造成迴圈引用。 另一方面,若timer一直處於validate的狀態,則其引用計數將始終大於0。先看一段NSTimer使用的例子(ARC模式):

1 #import <Foundation/Foundation.h>
2 @interface Friend : NSObject
3 - (void)cleanTimer;
4 @end
複製程式碼
 1 #import "Friend.h"
 2 @interface Friend ()
 3 {
 4     NSTimer *_timer;
 5 }
 6 @end
 7 
 8 @implementation Friend
 9 - (id)init
10 {
11     if (self = [super init]) {
12         _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:)
13                                                 userInfo:nil repeats:YES];
14     }
15     return  self;
16 }
17 
18 - (void)handleTimer:(id)sender
19 {
20     NSLog(@"%@ say: Hi!", [self class]);
21 }
22 - (void)cleanTimer
23 {
24     [_timer invalidate];
25     _timer = nil;
26 }
27 - (void)dealloc
28 {
29     [self cleanTimer];
30     NSLog(@"[Friend class] is dealloced");
31 }
複製程式碼

在類外部初始化一個Friend物件,並延遲5秒後將friend釋放(外部執行在非arc環境下)

複製程式碼
1         Friend *f = [[Friend alloc] init];
2         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
4             [f release];
5         });
複製程式碼

我們所期待的結果是,初始化5秒後,f物件被release,f的dealloc方法被呼叫,在dealloc裡面timer失效,物件被析構。但結果卻是如此:

相關推薦

IOS學習基礎知識積累

一.iOS開發之loadView、viewDidLoad及viewDidUnload的關係1.第一次訪問UIViewController的view時,view為nil,然後就會呼叫loadView方法建立view2.view建立完畢後會呼叫viewDidLoad方法進行介面元

修煉C++基礎知識筆記-第7章 類

1 this  任何對類成員的直接訪問都被看成this的隱式引用,this是一個常量指標 (class *const),不允許改變this中儲存的地址。 常量成員函式:在引數列表後面加一個const,表示this是一個指向常量的指標(const class *const thi

IOS學習到底什麼時候才需要在ObjC的Block中使用weakSelf/strongSelf

Objective C 的 Block 是一個很實用的語法,特別是與GCD結合使用,可以很方便地實現併發、非同步任務。但是,如果使用不當,Block 也會引起一些迴圈引用問題(retain cycle)—— Block 會 retain ‘self’,而 ‘self‘

ios學習優化 App 的啟動時間實踐 iOS

前言當用戶按下home鍵的時候,iOS的App並不會馬上被kill掉,還會繼續存活若干時間。理想情況下,使用者點選App的圖示再次回來的時候,App幾乎不需要做什麼,就可以還原到退出前的狀態,繼續為使用者服務。這種持續存活的情況下啟動App,我們稱為熱啟動,相對而言冷啟動就是

iOS學習Macbook外接2k顯示器開啟hidpi的方法

一、前言:大家平時用macbook開發的時候一般都喜歡外接一個顯示器開發吧?這裡我用了一臺2k的顯示器,我們要開啟hidpi模式。你們會問到為什麼要開啟hidpi模式呢?我的2k顯示器是2560*1440分別率,如果採用預設的設定,那麼在顯示器上面的字會特別的小。如果我們開啟

IOS學習面試iOS工程師的相關問題

1. OC中,與alloc語義相反的方法是dealloc還是release?與retain語義相反的方法是dealloc還是release?為什麼?需要與alloc配對使用的方法是dealloc還是release,為什麼? 以下是針對MRC(手動記憶體釋放)模式: 與all

IOS學習CocoaPods安裝使用及配置私有庫

如何安裝? 1.安裝ruby環境,新增淘寶ruby映象 $ gem sources --remove https://rubygems.org/ //等有反應之後再敲入以下命令 $ gem sources -a http://ruby.taobao.org/ 2

IOS學習訊息轉發和它的實際應用

訊息轉發,適用於把操作給另外一個類來實現 -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodS

Ado.Net基礎知識+簡單例項

為什麼要學Ado.Net?   作為程式設計師,我們一般都可以在Sql Server 的查詢分析器裡面檢視和操作資料庫中的資料。但是普通的使用者如果要檢視和操作資料庫中的資料,在查詢分析器裡面就不會了,我們不能讓普通團使用者去學Sql server吧。所以,我

IOS學習CoreText學習筆記(二)設定文字屬性和插入圖片

設定文字和圖片的方法: 繪製文字的步驟是:設定NSAttributedString 或NSMutableAttributedString——> 通過attributedString 生成frameSetter ——> 生成CTFrame——>畫出來設定文字

IOS學習http非同步檔案上傳和下載以及進度指示

2016-02-12 13:05:07.330 network-demo[16708:1254465] =================request redirectResponse================= 2016-02-12 13:05:07.331 network-demo[16708:

IOS學習iPhone螢幕尺寸、解析度及適配

1.iPhone尺寸規格 裝置 iPhone 寬 Width 高 Height 對角線 Diagonal 邏輯解析度(point) Scale Factor 裝置解析度(pixel) PPI 3GS 2.4

響應式布局學習筆記1----基礎知識

網頁設計 water com 文章 tar 屏幕分辨率 優點 light gin 本篇文章主要解決:什麽是響應式布局?有什麽優點和缺點? 一 什麽是響應式布局? 伊桑·馬科特(Ethan Marcotte)在2010年首先提出了響應式網頁設計(RWD,Responsive

深度學習Tensorflow基礎知識

Tensorflow簡介 \quad\quad在我們使用以統計方法為核心的機器學習方法的時候,重要的是做特徵工程,然後調一些引數,根據一些領域的經驗來不斷提取特徵,特徵的好壞往往決定模型的好壞。 \qu

python學習2-python基礎知識

的今天繼續學習python,在實現下列問題時遇到點小問題 輸入半徑,輸出面積即周長 我剛開始是這樣寫的  import math r = input('請輸入半徑:') print( '周長是:'+ 2 * math.pi * r) print('面積是:',+

51微控制器學習筆記0——基礎知識

一.微控制器三大資源 1.Flash—-程式儲存空間 相當於計算機的硬碟,可實現斷電後資料不丟失。 2.RAM—-資料儲存空間 相當於計算機的記憶體,用來儲存程式執行過程中產生和需

機器學習SVM基礎知識+程式碼實現

  1. 基本知識 二分類:通過分離超平面對資料點進行分類,訓練分離超平面。 原理:最大化支援向量到分離超平面的距離。支援向量:離分離超平面最近的點。 2. 完全線性可分(硬間隔) 2.1 SVM基本型 分離超平面:。(訓練中更新w和b,或alpha,使得分離超

機器學習邏輯迴歸基礎知識+程式碼實現

1. 基本概念 邏輯迴歸用於二分類,將對輸入的線性表示對映到0和1之間,輸出為label為1的概率。 優點:實現代價低,可輸出分類概率。適用於資料線性不可分。 缺點:容易欠擬合,分類精度可能不高,且僅限二分類。 使用資料型別:數值型和標稱資料。 邏輯迴歸本質也是線性迴歸,但是

大資料學習大資料學習基礎知識

學習之前沒搞清楚的知識 傳統的web應用(LAMP、JavaEE、NODE系等)與大資料什麼關係? 之前一直以為大資料的東西就是來取代傳統的Web應用的,其實並不是這樣;即使是大資料的架構,應用層依然會是傳統的web應用,但是會根據資料特點對資料儲存(結構化資料依然會儲存在傳統的關係型資料庫——如My

Python基礎知識

數據 文件 專用 一切都 元組 內存 引用傳遞 asc ilo 1. python腳本語言的第一行,目的就是指出,你想要你的這個文件中的代碼用什麽可執行程序去運行它 #!/usr/bin/python 是告訴操作系統執行這個腳本的時候,調用/usr/bin下