動態類型
:即運行時再決定對象的類型,這種動態特性在平常的應用中很是常見,簡單來講就是id類型。事實上,因爲靜態類型的固定性和可預知性,從而使用的更加普遍。靜態類型是強類型,而動態類型屬於弱類型,運行時決定接受者。動態綁定
:基於動態類型,在某個實例對象被肯定後,其類型便被肯定了,該對象對應的屬性和響應消息也被徹底肯定。動態加載
:根據需求加載所須要的資源,最基本就是不一樣機型的適配,例如,在Retina設備上加載@2x的圖片,而在老一些的普通蘋設備上加載原圖,讓程序在運行時添加代碼模塊以及其餘資源,用戶可根據須要加載一些可執行代碼和資源,而不是在啓動時就加載全部組件,可執行代碼能夠含有和程序運行時整合的新類。alloc
、copy(mutableCopy)
或者retian
一個對象時,你就有義務,向它發送一條release
或者autorelease
消息。其餘方法建立的對象,不須要由你來管理內存。autorelease
消息,這個對象並不會當即銷燬, 而是將這個對象放入了自動釋放池,待池子釋放時,它會向池中每個對象發送 一條release
消息,以此來釋放對象.release
消息,並不意味着這個對象被銷燬了,而是當這個對象的引用計數爲0時,系統纔會調用dealloc
方法,釋放該對象和對象自己它所擁有的實例。new
開頭。若是非要以new
開頭命名屬性的名字,須要本身定製get方法名,如@property(getter=theString) NSString * newString;
@autoreleasepool{}
MVC是一種架構模式,M表示MOdel,V表示視圖View,C表示控制器Controller:html
ViewModel
層,就是View和Model層的粘合劑,他是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其餘各類各樣的代碼的極好的地方。說白了,就是把原來ViewController
層的業務邏輯和頁面邏輯等剝離出來放到ViewModel層。Garbage collection
簡稱GC
),可是apple的移動終端中,是不支持GC的,Mac桌面系統開發中是支持的.Automatic Reference Counting
的簡稱),ARC是在IOS5以後推出的新技術,它與GC的機制是不一樣的。咱們在編寫代碼時, 不須要向對象發送release
或者autorelease
方法,也不能夠調用delloc
方法,編譯器會在合適的位置自動給用戶生成release
消息(autorelease
),ARC 的特色是自動引用技術簡化了內存管理的難度.OC中的協議是一個方法列表,且多少有點相關。它的特色是能夠被任何類使用(實現),但它並非類(這裏咱們須要注意),自身不會實現這樣方法, 而是又其餘人來實現協議常常用來實現委託對象(委託設計模式)。若是一個類採用了一個協議,那麼它必須實現協議中必須須要實現的方法,在協議中的方法默認是必須實現(@required),添加關鍵字@optional,代表一旦採用該協議,這些「可選」的方法是能夠選擇不實現的。java
category
優勢和缺點super
消息的斷裂。所以,最好不要覆蓋原始類中的方法。+ (NSIndexPath *)indexPathForRow:(NSInteger)row
inSection:(NSInteger)section
property
描述setter方法,就不會報錯。
多個對象間依然會存在循環引用問題,造成一個環,在編程中,造成的環越大越不容易察覺,以下圖所示:ios
解決方法:程序員
事先知道存在循環引用的地方,在合理的位置主動斷開一個引用,是對象回收;正則表達式
使用弱引用的方法。數據庫
鍵路徑(keyPath)、鍵值編碼(KVC)和鍵值觀察(KVO)編程
鍵路徑設計模式
在一個給定的實體中,同一個屬性的全部值具備相同的數據類型。數組
鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。 - 鍵路徑是一個由用點做分隔符的鍵組成的字符串,用於指定一個鏈接在一塊兒的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每一個鍵的值也是相對於其前面的性質。瀏覽器
鍵路徑使您能夠以獨立於模型實現的方式指定相關對象的性質。經過鍵路徑,您能夠指定對象圖中的一個任意深度的路徑,使其指向相關對象的特定屬性。
鍵值編碼KVC
鍵值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是經過調用存取方法,直接或經過實例變量訪問的機制,非對象類型的變量將被自動封裝或者解封成對象,不少狀況下會簡化程序代碼;
KVC的缺點:一旦使用 KVC 你的編譯器沒法檢查出錯誤,即不會對設置的鍵、鍵路徑進行錯誤檢查,且執行效率要低於合成存取器方法和自定的 setter 和 getter 方法。由於使用 KVC 鍵值編碼,它必須先解析字符串,而後在設置或者訪問對象的實例變量。
鍵值觀察KVO
鍵值觀察機制是一種能使得對象獲取到其餘對象屬性變化的通知 ,極大的簡化了代碼。
實現 KVO 鍵值觀察模式,被觀察的對象必須使用 KVC 鍵值編碼來修 改它的實例變量,這樣才能被觀察者觀察到。所以,KVC是KVO的基礎。
Demo
好比我自定義的一個button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil]; #pragma mark KVO - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"highlighted"] ) { [self setNeedsDisplay]; } }
對於系統是根據keypath去取的到相應的值發生改變,理論上來講是和kvc機制的道理是同樣的。
KVC機制經過key找到value的原理。
當經過KVC調用對象時,好比:[self valueForKey:@」someKey」]時,程序會自動試圖經過下面幾種不一樣的方式解析這個調用。
首先查找對象是否帶有 someKey 這個方法,若是沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),若是尚未找到,程序會繼續試圖調用 -(id) valueForUndefinedKey:這個方法。若是這個方法仍是沒有被實現的話,程序會拋出一個NSUndefinedKeyException異常錯誤。
補充:KVC查找方法的時候,不只僅會查找someKey這個方法,還會查找getsomeKey這個方法,前面加一個get,或者_someKey以_getsomeKey這幾種形式。同時,查找實例變量的時候也會不只僅查找someKey這個變量,也會查找_someKey這個變量是否存在。
設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象可以在錯誤發生前,有最後的機會響應這個請求。
在 Objective-C 中如何實現 KVO
註冊觀察者(注意:觀察者和被觀察者不會被保留也不會被釋放)
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
接收變動通知
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
KVO中誰要監聽誰註冊,而後對響應進行處理,使得觀察者與被觀察者徹底解耦。KVO只檢測類中的屬性,而且屬性名都是經過NSString來查找,編譯器不會檢錯和補全,所有取決於本身。
assign
的緣由:防止循環引用,以致對象沒法獲得正確的釋放。NSArray
和NSMutableArray
,前者在初始化後的內存控件就是固定不可變的,後者能夠添加等,能夠動態申請新的內存空間[super dealloc]
方法, 來釋放父類擁有的實例,其實也就是子類自己的。通常來講咱們優先釋放子類擁 有的實例,最後釋放父類所擁有的實例。NSPredicate
的類,該類主要用於指定過濾器的條件, 每個對象經過謂詞進行篩選,判斷條件是否匹配。若是須要了解使用方法,請看謂詞的具體使用static
變量的做用範圍爲該函數體,不一樣於auto
變量,該變量的內存只被分配一次,所以其值在下次調用時仍維持上次的值.static
全局變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問.static
函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明.static
成員變量屬於整個類所擁有,對類的全部對象只有一份拷貝.#include
和#import
其效果相同,都是查詢類中定義的行爲(方法);#import
不會引發交叉編譯,確保頭文件只會被導入一次;@class
的代表,只定 義了類的名稱,而具體類的行爲是未知的,通常用於.h 文件;@class
比#import
編譯效率更高。@class
和#import
的主要區別在於解決引用死鎖的問題。@public
:對象的實例變量的做用域在任意地方均可以被訪問 ;@protected
:對象的實例變量做用域在本類和子類均可以被訪問 ;@private
:實例變量的做用域只能在本類(自身)中訪問 .任意類型對象,程序運行時才決定對象的類型。
均表示條件的判斷,switch語句表達式只能處理的是整型、字符型和枚舉類型,而選擇流程語句則沒有這樣的限制。但switch語句比選擇流程控制語句效率更高。
isKindOfClass
不只用來肯定一個對象是不是一個類的成員,也能夠用來肯定一個對象是否派生自該類的類的成員 ,而isMemberOfClass
只能作到第一點。ClassA
派 生 自NSObject
類 , ClassA *a = [ClassA alloc] init]
;,[a isKindOfClass:[NSObject class]]
能夠檢查出 a 是不是 NSObject
派生類 的成員,但 isMemberOfClass
作不到。數據存儲的核心都是寫文件。
CoreData的介紹:
CoreData的特徵:
NSCopying
和NSMutableCopying
協議的類的對象才能被拷貝,分爲不可變拷貝和可變拷貝,具體區別戳這;NSCopying
協議方法爲:- (id)copyWithZone:(NSZone *)zone { MyObject *copy = [[[self class] allocWithZone: zone] init]; copy.username = [self.username copyWithZone:zone]; return copy; }
NSAutorelease
類的一個實例,當向一個對象發送autorelease
消息時,該對象會自動入池,待池銷燬時,將會向池中全部對象發送一條release
消息,釋放對象。[pool release]、 [pool drain]
表示的是池自己不會銷燬,而是池子中的臨時對象都被髮送release
,從而將對象銷燬。assign
:普通賦值,通常經常使用於基本數據類型,常見委託設計模式, 以此來防止循環引用。(咱們稱之爲弱引用).retain
:保留計數,得到到了對象的全部權,引用計數在原有基礎上加1.copy
:通常認爲,是在內存中從新開闢了一個新的內存空間,用來 存儲新的對象,和原來的對象是兩個不一樣的地址,引用計數分別爲1。可是當copy
對象爲不可變對象時,那麼copy
的做用至關於retain
。由於,這樣能夠節約內存空間棧區(stack)
由編譯器自動分配釋放 ,存放方法(函數)的參數值, 局部變量的值等,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。即棧頂的地址和棧的最大容量是系統預先規定好的。堆區(heap)
通常由程序員分配釋放, 若程序員不釋放,程序結束時由OS回收,向高地址擴展的數據結構,是不連續的內存區域,從而堆得到的空間比較靈活。碎片問題
:對於堆來說,頻繁的new/delete
勢必會形成內存空間的不連續,從而形成大量的碎片,使程序效率下降。對於棧來說,則不會存在這個問題,由於棧是先進後出的隊列,他們是如此的一一對應,以致於永遠都不可能有一個內存塊從棧中間彈出.分配方式
:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,他的動態分配是由編譯器進行釋放,無需咱們手工實現。分配效率
:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很複雜的。全局區(靜態區)(static)
,全局變量和靜態變量的存儲是放在一塊 的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。程序結束後有系統釋放。文字常量區
—常量字符串就是放在這裏的。程序結束後由系統釋放。程序代碼區
—存放函數體的二進制代碼performSelector
的API中,並無提供三個參數。所以,咱們只能傳數組或者字典,可是數組或者字典只有存入對象類型,而結構體並非對象類型,咱們只能經過對象放入結構做爲屬性來傳過去了.- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject: (id)object1 withObject:(id)object2;
具體實現以下:
typedef struct HYBStruct { int a; int b; } *my_struct; @interface HYBObject : NSObject @property (nonatomic, assign) my_struct arg3; @property (nonatomic, copy) NSString *arg1; @property (nonatomic, copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的內存,咱們要手動釋放掉 - (void)dealloc { free(self.arg3); } @end
測試:
my_struct str = (my_struct)(malloc(sizeof(my_struct))); str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc] init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [self performSelector:@selector(call:) withObject:obj]; // 在回調時獲得正確的數據的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d", obj.arg3->a, obj.arg3->b); }
這是否刷新取決於timer加入到Run Loop中的Mode是什麼。Mode主要是用來指定事件在運行循環中的優先級的,分爲:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
:默認,空閒狀態UITrackingRunLoopMode
:ScrollView滑動時會切換到該ModeUIInitializationRunLoopMode
:run loop啓動時,會切換到該modeNSRunLoopCommonModes(kCFRunLoopCommonModes)
:Mode集合NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)
NSTimer
對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
添加到主運行循環中的時候, ScrollView滾動過程當中會由於mode的切換,而致使NSTimer
將再也不被調度。當咱們滾動的時候,也但願不調度,那就應該使用默認模式。可是,若是但願在滾動時,定時器也要回調,那就應該使用common mode。UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:defineString]
修改成:UITableViewCell *cell = [tableview cellForRowAtIndexPath:indexPath];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ /*任務a */ }); dispatch_group_async(group, queue, ^{ /*任務b */ }); dispatch_group_async(group, queue, ^{ /*任務c */ }); dispatch_group_async(group, queue, ^{ /*任務d */ }); dispatch_group_notify(group,dispatch_get_main_queue(), ^{ // 在a、b、c、d異步執行完成後,會回調這裏 });
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES callback:^() { weakSelf.secondsLabel.text = ... } [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
有2種方法解決:
NSThread
:當須要進行一些耗時操做時會把耗時的操做放到線程中。線程同步:多個線程同時訪問一個數據會出問題,NSlock、線程同步塊、@synchronized(self){}。NSOperationQueue操做隊列
(不需考慮線程同步問題)。編程的重點都放在main裏面,NSInvocationOperation
、BSBlockOperation
、自定義Operation。建立一個操做綁定相應的方法,當把操做添加到操做隊列中時,操做綁定的方法就會自動執行了,當把操做添加到操做隊列中時,默認會調用main方法。`Grand Central Dispatch
)宏大的中央調度,串行隊列、併發隊列、主線程隊列;多線程編程是防止主線程堵塞、增長運行效率的最佳方法。
GET和POST的區別
:
GET請求:參數在地址後拼接,沒有請求數據,不安全(由於全部參數都拼接在地址後面),不適合傳輸大量數據(長度有限制,爲1024個字節)。
GET提交、請求的數據會附在URL以後,即把數據放置在HTTP協議頭<requestline>中。 以?分割URL和傳輸數據,多個參數用&鏈接。若是數據是英文字母或數字,原樣發送, 若是是空格,轉換爲+,若是是中文/其餘字符,則直接把字符串用BASE64加密。
POST請求:參數在請求數據區放着,相對GET請求更安全,而且數據大小沒有限制。把提交的數據放置在HTTP包的包體<request-body>
中.
傳輸數據的大小:
安全性:
Secure Hypertext Transfer Protocol
),它是一個安全通訊通道,基於HTTP開發,用於客戶計算機和服務器之間交換信息,使用安全套結字層(SSI
)進行信息交換,即HTTP的安全版。startSynchronous
方法;AFNetWorking默認沒有封裝同步請求,若是開發者須要使用同步請求,則須要重寫getPath:paraments:success:failures
方法,對於AFHttpRequestOperation進行同步處理。鑰匙串
建立一個鑰匙(key);調用類別的方法:
1. 應用程序在本身的沙盒中運做,可是不能訪問任何其餘應用程序的沙盒; 2. 應用之間不能共享數據,沙盒裏的文件不能被複制到其餘 應用程序的文件夾中,也不能把其餘應用文件夾複製到沙盒中; 3. 蘋果禁止任何讀寫沙盒之外的文件,禁止應用程序將內容寫到沙盒之外的文件夾中; 4. 沙盒目錄裏有三個文件夾:Documents——存儲 應用程序的數據文件,存儲用戶數據或其餘按期備份的信息; Library下有兩個文件夾,Caches存儲應用程序再次啓動所需的信息, Preferences包含應用程序的偏好設置文件,不可在這更改偏好設置; temp存放臨時文件即應用程序再次啓動不須要的文件。
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).
viewDidLoad
在view從nib文件初始化時調用,loadView
在controller的view爲nil時調用。memory warning notification
,當view controller
的任何view沒有用的時候,viewDidUnload
會被調用,在這裏實現將retain
的view release
,若是是retain
的IBOutlet view
屬性則不要在這裏release
,IBOutlet
會負責release
。volatile
的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile
變量的幾個例子:@synthesize
是系統自動生成getter和setter屬性聲明;@synthesize
的意思是,除非開發人員已經作了,不然由編譯器生成相應的代碼,以知足屬性聲明;@dynamic
是開發者自已提供相應的屬性聲明,@dynamic
意思是由開發人員提供相應的代碼:對於只讀屬性須要提供setter
,對於讀寫屬性須要提供 setter
和getter
。查閱了一些資料肯定@dynamic
的意思是告訴編譯器,屬性的獲取與賦值方法由用戶本身實現, 不自動生成。- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
UIResponder
的對象均可以在這個N叉樹中扮演一個節點。[NSRunLoop currentRunLoop]
的話,就不會去查詢是否存在當前線程的RunLoop,也就不會去加載,更不會建立。優勢:
缺點:
NSString *timeStr = @"2015-04-10"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd"; formatter.timeZone = [NSTimeZone defaultTimeZone]; NSDate *date = [formatter dateFromString:timeStr]; // 2015-04-09 16:00:00 +0000 NSLog(@"%@", date);
在iOS中隊列分爲如下幾種:
dispatch_queue_t q = dispatch_queue_create("...", DISPATCH_QUEUE_SERIAL);
並行隊列: 隊列中的任務一般會併發執行;
dispatch_queue_t q = dispatch_queue_create("......",DISPATCH_QUEUE_CONCURRENT);
全局隊列:是系統的,直接拿過來(GET)用就能夠;與並行隊列相似;
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
主隊列:每個應用程序對應惟一主隊列,直接GET便可;在多線程開發中,使用主隊列更新UI;
dispatch_queue_t q = dispatch_get_main_queue();
更多細節見下圖:
NSDateFormatter
和NSCalendar
,但又不可避免地須要使用它們。一般是做爲屬性存儲起來,防止反覆建立。-[ViewController initWithNibName:bundle:]; -[ViewController init]; -[ViewController loadView]; -[ViewController viewDidLoad]; -[ViewController viewWillDisappear:]; -[ViewController viewWillAppear:]; -[ViewController viewDidAppear:]; -[ViewController viewDidDisappear:];
imgView.layer.cornerRadius = 10; // 這一行代碼是很消耗性能的 imgView.clipsToBounds = YES;
**這是離屏渲染(off-screen-rendering),消耗性能的**
- (UIImage *)imageWithCornerRadius:(CGFloat)radius { CGRect rect = (CGRect){0.f, 0.f, self.size}; UIGraphicsBeginImageContextWithOptions(self.size, NO, UIScreen.mainScreen.scale); CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath); CGContextClip(UIGraphicsGetCurrentContext()); [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
原文:http://www.jianshu.com/p/5d2163640e26