- 1:ios開發中常見技術的總結(主要是區別)
- 2:作為一個iOS程序員必備的常識問題
- 3:作為面試必備的一份寶典
- 4:初學者快速了解相關技術
- 5:老程序員快速回顧混淆,忘記的知識點
后續我也會一直講本文更新下去,有遺漏點或者錯誤的地方望指出,或者聯系我,相互交流技術,謝謝!
好了開始吧。。。。。。。。。。。
一: weak&strong
- strong表示保留它指向的堆上的內存區域不再指向這塊區域了。 也就是說我強力指向了一個區域,我們不再指向它的條件只有我們指向nil或者我自己也不在內存上,沒有人strong指向我了。
-
weak表示如果還沒有人指向它了,它就會被清除內存,同時被指向nil,因為我不能讀取不存在的東西。
weak只在iOS5.0使用
這並不是垃圾回收,我們用reference count 表示堆上還有多少strong指針,當它變為0就馬上釋放。
本地變量都是strong,編輯器幫你計算.
補充
-
管理機制:使用了一種叫做引用計數的機制來管理內存中的對象。OC中每個對象都對應着他們自己的引用計數,引用計數可以理解為一個整數計數器,當使 用alloc方法創建對象的時候,持有計數會自動設置為1。當你向一個對象發送retain消息 時,持有計數數值會增加1。相反,當你像一個對象發送release消息時,持有計數數值會減小1。當對象的持有計數變為0的時候,對象會釋放自己所占用 的內存。 retain(引用計數加1)->release(引用計數減1) alloc(申請內存空間)->dealloc(釋放內存空間) readwrite: 表示既有getter,也有setter (默認) readonly: 表示只有getter,沒有setter nonatomic:不考慮線程安全 atomic:線程操作安全 (默認) 線程安全情況下的setter和getter:
- (NSString*) value { @synchronized(self) { return [[_value retain] autorelease];
} } - (void) setValue:(NSString)aValue { @synchronized(self) { [aValue retain]; [value release]; value = aValue;
} } retain: release舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1 assign: 簡單賦值,不更改索引計數 (默認) copy: 其實是建立了一個相同的對象,地址不同(retain:指針拷貝 copy:內容拷貝) strong:(ARC下的)和(MRC)retain一樣 (默認) weak:(ARC下的)和(MRC)assign一樣, weak當指向的內存釋放掉后自動nil化,防止野指針 unsafe_unretained 聲明一個弱應用,但是不會自動nil化,也就是說,如果所指向的內存區域被釋放了,這個指針就是一個野指針了。 autoreleasing 用來修飾一個函數的參數,這個參數會在函數返回的時候被自動釋放。1、 類變量的@protected ,@private,@public,@package,聲明各有什么含義? @private:作用范圍只能在自身類 @protected:作用范圍在自身類和繼承自己的子類 (默認) @public:作用范圍最大,可以在任何地方被訪問。 @package:這個類型最常用於框架類的實例變量,同一包內能用,跨包就不能訪問
- (NSString*) value { @synchronized(self) { return [[_value retain] autorelease];
二: category&extension
類別主要有三個作用
-
(1)可以將類的實現分散到多個不同文件或多個不同框架中,方便代碼管理。也可以對框架提供類的擴展(沒有源碼,不能修改)。
-
(2)創建對私有方法的前向引用:如果其他類中的方法未實現,在你訪問其他類的私有方法時編譯器報錯這時使用類別,在類別中聲明這些方法(不必提供方法實現),編譯器就不會再產生警告
-
(3)向對象添加非正式協議:創建一個NSObject的類別稱為“創建一個非正式協議”,因為可以作為任何類的委托對象使用。
他們的主要區別是:
-
1、形式上來看,extension是匿名的category。
-
2、extension里聲明的方法需要在mainimplementation中實現,category不強制要求。
-
3、extension可以添加屬性(變量),category不可以。
Category和Extension都是用來給已定義的類增加新的內容的。
-
Category和原有類的耦合更低一些,聲明和實現都可以寫在單獨的文件里。但是只能為已定義類增加Method,而不能加入instance variable。
-
Extension耦合比較高,聲明可以單獨寫,但是實現必須寫在原有類的@implementation中。可以增加Method和instance variable。
-
Extension給人感覺更像是在編寫類時為了封裝之類的特性而設計,和類是同時編寫的。而category則是在用到某一個framework中的類時臨時增加的特性。
-
Extension的一個特性就是可以redeclare一個instance variable,將之從readonly改為對內readwrite.
使用Extension可以更好的封裝類,在h文件中能看到的都是對外的接口,其余的instance variable和對內的@property等都可以寫在Extension,這樣類的結構更加清晰。
三: define&const
- define在預處理階段進行替換,const常量在編譯階段使用 宏不做類型檢查,僅僅進行替換,const常量有數據類型,會執行類型檢查 define不能調試,const常量可以調試 define定義的常量在替換后運行過程中會不斷地占用內存,而const定義的常量存儲在數據段只有一份copy,效率更高 define可以定義一些簡單的函數,const不可以
四: synthesize&denamic
- 1:通過@synthesize 指令告訴編譯器在編譯期間產生getter/setter方法。
-
2: 通過@dynamic指令,自己實現方法。
有些存取是在運行時動態創建的,如在CoreData的NSManagedObject類使用的某些。如果你想這些情況下,聲明和使用屬性,但要避免缺少方法在編譯時的警告,你可以使用@dynamic動態指令,而不是@synthesize合成指令。
五: UIView的setNeedsDisplay和setNeedsLayout方法
-
1、在Mac OS中NSWindow的父類是NSResponder,而在i OS 中UIWindow 的父類是UIVIew。程序一般只有一個窗口但是會又很多視圖。
-
2、UIView的作用:描畫和動畫,視圖負責對其所屬的矩形區域描畫、布局和子視圖管理、事件處理、可以接收觸摸事件、事件信息的載體、等等。
-
3、UIViewController 負責創建其管理的視圖及在低內存的時候將他們從內存中移除。還為標准的系統行為進行響應。
-
4、layOutSubViews 可以在自己定制的視圖中重載這個方法,用來調整子視圖的尺寸和位置。
-
5、UIView的setNeedsDisplay和setNeedsLayout方法。首先兩個方法都是異步執行的。而 setNeedsDisplay會調用自動調用drawRect方法,這樣可以拿到UIGraphicsGetCurrentContext,就可以畫畫 了。而setNeedsLayout會默認調用layoutSubViews,就可以處理子視圖中的一些數據。
綜上所述:setNeedsDisplay方便繪圖,而layoutSubViews方便出來數據
setNeedDisplay告知視圖它發生了改變,需要重新繪制自身,就相當於刷新界面.
六: UILayer&UIView
-
UIView是iOS系統中界面元素的基礎,所有的界面元素都繼承自它。它本身完全是由CoreAnimation來實現的(Mac下似乎不是這 樣)。它真正的繪圖部分,是由一個叫CALayer(Core Animation Layer)的類來管理。UIView本身,更像是一個CALayer的管理器,訪問它的跟繪圖和跟坐標有關的屬性,例如frame,bounds等等, 實際上內部都是在訪問它所包含的CALayer的相關屬性。
-
UIView有個重要屬性layer,可以返回它的主CALayer實例。
-
UIView的CALayer類似UIView的子View樹形結構,也可以向它的layer上添加子layer,來完成某些特殊的表示。即CALayer層是可以嵌套的。
-
UIView的layer樹形在系統內部,被維護着三份copy。分別是邏輯樹,這里是代碼可以操縱的;動畫樹,是一個中間層,系統就在這一層上更改屬性,進行各種渲染操作;顯示樹,其內容就是當前正被顯示在屏幕上得內容。
-
動畫的運作:對UIView的subLayer(非主Layer)屬性進行更改,系統將自動進行動畫生成,動畫持續時間的缺省值似乎是0.5秒。
-
坐標系統:CALayer的坐標系統比UIView多了一個anchorPoint屬性,使用CGPoint結構表示,值域是0~1,是個比例值。
-
渲染:當更新層,改變不能立即顯示在屏幕上。當所有的層都准備好時,可以調用setNeedsDisplay方法來重繪顯示。
-
變換:要在一個層中添加一個3D或仿射變換,可以分別設置層的transform或affineTransform屬性。
-
變形:Quartz Core的渲染能力,使二維圖像可以被自由操縱,就好像是三維的。圖像可以在一個三維坐標系中以任意角度被旋轉,縮放和傾斜。CATransform3D的一套方法提供了一些魔術般的變換效果。
七: UITableView&UICollection
UICollectionView是iOS6新引進的API,用於展示集合視圖,布局更加靈活,其用法類似於UITableView。而 UICollectionView、UICollectionViewCell與UITableView、UITableViewCell在用法上有相似 的也有不同的,下面是一些基本的使用方法:
對於UITableView,僅需要UITableViewDataSource,UITableViewDelegate這兩個協議,使用 UICollectionView需要實現UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout這三個協議,這是因為 UICollectionViewDelegateFlowLayout實際上是UICollectionViewDelegate的一個子協議,它繼承 了UICollectionViewDelegate,它的作用是提供一些定義UICollectionView布局模式的函數
八:NSProxy&NSObject
NSObjetc:
NSObject協議組對所有的Object-C下的objects都生效。 如果objects遵從該協議,就會被看作是first-class objects(一級類)。 另外,遵從該協議的objects的retain,release,autorelease等方法也服從objects的管理和在Foundation中 定義的釋放方法。一些容器中的對象也可以管理這些objects,比如 說NSArray 和NSDictionary定義的對象。 Cocoa的根類也遵循該協議,所以所有繼承NSObjects的objects都有遵循該協議的特性。
NSProXY:
NSProxy 是一個虛基類,它為一些表現的像是其它對象替身或者並不存在的對象定義一套API。一般的,發送給代理的消息被轉發給一個真實的對象或者代理本身 load(或者將本身轉換成)一個真實的對象。NSProxy的基類可以被用來透明的轉發消息或者耗費巨大的對象的lazy 初始化。
九: layoutSubViews&drawRects
layoutSubviews在以下情況下會被調用:
- 1、init初始化不會觸發layoutSubviews。
- 2、addSubview會觸發layoutSubviews。
- 3、設置view的Frame會觸發layoutSubviews,當然前提是frame的值設置前后發生了變化。
- 4、滾動一個UIScrollView會觸發layoutSubviews。
- 5、旋轉Screen會觸發父UIView上的layoutSubviews事件。
- 6、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件。
- 7、直接調用setLayoutSubviews。
drawRect在以下情況下會被調用:
- 1、如果在UIView初始化時沒有設置rect大小,將直接導致drawRect不被自動調用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 兩方法之后掉用的.所以不用擔心在 控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給View(如果這些View draw的時候需要用到某些變量 值).
- 2、該方法在調用sizeToFit后被調用,所以可以先調用sizeToFit計算出size。然后系統自動調用drawRect:方法。
- 3、通過設置contentMode屬性值為UIViewContentModeRedraw。那么將在每次設置或更改frame的時候自動調用drawRect:。
- 4、直接調用setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,但是有個前提條件是rect不能為0。
drawRect方法使用注意點:
-
1、 若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef並繪圖。如果在其他方法中獲取將獲取到一個invalidate 的ref並且不能用於畫圖。drawRect:方法不能手動顯示調用,必須通過調用setNeedsDisplay 或 者 setNeedsDisplayInRect,讓系統自動調該方法。
-
2、若使用calayer繪圖,只能在drawInContext: 中(類似魚drawRect)繪制,或者在delegate中的相應方法繪制。同樣也是調用setNeedDisplay等間接調用以上方法 3、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時刷新屏幕
十:NSCache&NSDcitionary
NSCache與可變集合有幾點不同:
- NSCache類結合了各種自動刪除策略,以確保不會占用過多的系統內存。如果其它應用需要內存時,系統自動執行這些策略。當調用這些策略時,會從緩存中刪除一些對象,以最大限度減少內存的占用。
- NSCache是線程安全的,我們可以在不同的線程中添加、刪除和查詢緩存中的對象,而不需要鎖定緩存區域。
- 不像NSMutableDictionary對象,一個緩存對象不會拷貝key對象。
NSCache和NSDictionary類似,不同的是系統回收內存的時候它會自動刪掉它的內容。
- (1)可以存儲(當然是使用內存)
- (2)保持強應用, 無視垃圾回收. =>這一點同 NSMutableDictionary
- (3)有固定客戶.
十一:AFNetworking&ASIHttpRequest&MKNetWorking
一、底層實現
1、AFN的底層實現基於OC的NSURLConnection和NSURLSession 2、ASI的底層實現基於純C語言的CFNetwork框架 3、因為NSURLConnection和NSURLSession是在CFNetwork之上的一層封裝,因此ASI的運行性能高於AFN
AFNetworking的下載地址: https://github.com/AFNetworking/AFNetworking
二、對服務器返回的數據處理
1、ASI沒有直接提供對服務器數據處理的方式,直接返回的是NSData/NSString 2、AFN提供了多種對服務器數據處理的方式 (1)JSON處理-直接返回NSDictionary或者NSArray (2)XML處理-返回的是xml類型數據,需對其進行解析 (3)其他類型數據處理
三、監聽請求過程
1、AFN提供了success和failure兩個block來監聽請求的過程(只能監聽成功和失敗)
* success : 請求成功后調用 * failure : 請求失敗后調用 2、ASI提供了3套方案,每一套方案都能監聽請求的完整過程 (監聽請求開始、接收到響應頭信息、接受到具體數據、接受完畢、請求失敗) * 成為代理,遵守協議,實現協議中的代理方法 * 成為代理,不遵守協議,自定義代理方法 * 設置block
四、在文件下載和文件上傳的使用難易度
1、AFN *不容易實現監聽下載進度和上傳進度 *不容易實現斷點續傳 *一般只用來下載不大的文件 2、ASI *非常容易實現下載和上傳 *非常容易監聽下載進度和上傳進度 *非常容易實現斷點續傳 *下載大文件或小文件均可 3、實現下載上傳推薦使用ASI
五、網絡監控
1、AFN自己封裝了網絡監控類,易使用 2、ASI使用的是Reachability,因為使用CocoaPods下載ASI時,會同步下載Reachability,但Reachability作為網絡監控使用較為復雜(相對於AFN的網絡監控類來說) 3、推薦使用AFN做網絡監控-AFNetworkReachabilityManager
六、ASI提供的其他實用功能
1、控制信號旁邊的圈圈要不要在請求過程中轉 2、可以輕松地設置請求之間的依賴:每一個請求都是一個NSOperation對象 3、可以統一管理所有請求(還專門提供了一個叫做ASINetworkQueue來管理所有的請求對象) * 暫停/恢復/取消所有的請求 * 監聽整個隊列中所有請求的下載進度和上傳進度
MKNetworkKit 是一個使用十分方便,功能又十分強大、完整的iOS網絡編程代碼庫。它只有兩個類, 它的目標是使用像AFNetworking這么簡單,而功能像ASIHTTPRequest(已經停止維護)那么強大。它除了擁有 AFNetworking和ASIHTTPRequest所有功能以外,還有一些新特色,包括:
-
1、高度的輕量級,僅僅只有2個主類
-
2、自主操作多個網絡請求
-
3、更加准確的顯示網絡活動指標
-
4、自動設置網絡速度,實現自動的2G、3G、wifi切換
-
5、自動緩沖技術的完美應用,實現網絡操作記憶功能,當你掉線了又上線后,會繼續執行未完成的網絡請求
-
6、可以實現網絡請求的暫停功能
-
7、准確無誤的成功執行一次網絡請求,摒棄后台的多次請求浪費
-
8、支持圖片緩沖
-
9、支持ARC機制
-
10、在整個app中可以只用一個隊列(queue),隊列的大小可以自動調整
十二:load&initialize
- (void)load;
- (void)initialize;
可以看到這兩個方法都是以“+”開頭的類方法,返回為空。通常情況下,我們在開發過程中可能不必關注這兩個方法。如果有需要定制,我們可以在自定義的NSObject子類中給出這兩個方法的實現,這樣在類的加載和初始化過程中,自定義的方法可以得到調用。
load和initialize的共同特點
-
在不考慮開發者主動使用的情況下,系統最多會調用一次
-
如果父類和子類都被調用,父類的調用一定在子類之前
-
都是為了應用運行提前創建合適的運行環境
-
在使用時都不要過重地依賴於這兩個方法,除非真正必要
它們的相同點在於:方法只會被調用一次。(其實這是相對runtime來說的,后邊會做進一步解釋)。 The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses. The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond. -
load是只要類所在文件被引用就會被調用,而initialize是在類或者其子類的第一個方法被調用前調用。所以如果類沒有被引用進項目,就不會有load調用;但即使類文件被引用進來,但是沒有使用,那么initialize也不會被調用。
- 文檔也明確闡述了方法調用的順序:父類(Superclass)的方法優先於子類(Subclass)的方法,類中的方法優先於類別(Category)中的方法。
十三:ARC-Block&MRC-Block
block雖然好用,但是里面也有不少坑,最大的坑莫過於循環引用問題。稍不注意,可能就會造成內存泄漏。這節,我將從源碼的角度來分析造成循環引用問題的根本原因。並解釋變量前加block,和weak的區別。
明確兩點
1,Block可以訪問Block函數以及語法作用域以內的外部變量。也就是說:一個函數里定義了個block,這個block可以訪問該函數的內 部變量(當然還包括靜態,全局變量)-即block可以使用和本身定義范圍相同的變量。 2,Block其實是特殊的Objective-C對象,可以使用copy,release等來管理內存,但和一般的NSObject的管理方式有些不 同,稍后會說明。
MRC:防止 block 對self的引用 解決辦法
__block typeof(self) weakSelf = self;
ARC:防止 block 對self的引用 解決辦法
__weak typeof(self) weakSelf = self;
對於非ARC下, 為了防止循環引用, 我們使用__block來修飾在Block中使用的對象:
對於ARC下, 為了防止循環引用, 我們使用weak來修飾在Block中使用的對象。原理就是:ARC中,Block中如果引用了strong修飾符的自動變量,則相當於Block對該變量的引用計數+1。
十四:MVC&MVVM
-
在MVC里,View是可以直接訪問Model的!從而,View里會包含Model信息,不可避免的還要包括一些業務邏輯。 MVC模型關注的是Model的不變,所以,在MVC模型里,Model不依賴於View,但是 View是依賴於Model的。不僅如此,因為有一些業務邏輯在View里實現了,導致要更改View也是比較困難的,至少那些業務邏輯是無法重用的。
-
MVVM在概念上是真正將頁面與數據邏輯分離的模式,它把數據綁定工作放到一個JS里去實現,而這個JS文件的主要功能是完成數據的綁定,即把model綁定到UI的元素上。
有人做過測試:使用Angular(MVVM)代替Backbone(MVC)來開發,代碼可以減少一半。 -
此外,MVVM另一個重要特性,雙向綁定。它更方便你同時維護頁面上都依賴於某個字段的N個區域,而不用手動更新它們。
總結:
- 優點:MVVM就是在MVC的基礎上加入了一個視圖模型viewModel,用於數據有效性的驗證,視圖的展示邏輯,網絡數據請求及處理,其他的 數據處理邏輯集合,並定下相關接口和協議。相比起MVC,MVVM中vc的職責和復雜度更小,對數據處理邏輯的測試更加方便,對bug的原因排查更加方 便,代碼可閱讀性,重用性和可維護性更高。MVVM耦合性更低。MVVM不同層級的職責更加明確,更有利於代碼的編寫和團隊的協作。 缺點:MVVM相比MVC代碼量有所增加。MVVM相比MVC在代碼編寫之前需要有更清晰的模式思路。
十五:Object&Swift
Obejective-C復雜的語法,更加簡單易用、有未來,讓許多開發者心動不已,Swift明顯的特點有:
-
蘋果宣稱 Swift 的特點是:快速、現代、安全、互動,而且明顯優於 Objective-C 語言
-
可以使用現有的 Cocoa 和 Cocoa Touch 框架
-
Swift 取消了 Objective C 的指針及其他不安全訪問的使用
-
舍棄 Objective C 早期應用 Smalltalk 的語法,全面改為句點表示法
-
提供了類似 Java 的名字空間(namespace)、泛型(generic)、運算對象重載(operator overloading)
-
Swift 被簡單的形容為 “沒有 C 的 Objective-C”(Objective-C without the C)
-
為蘋果開發工具帶來了Xcode Playgrounds功能,該功能提供強大的互動效果,能讓Swift源代碼在撰寫過程中實時顯示出其運行結果;
-
基於C和Objective-C,而卻沒有C的一些兼容約束;
-
采用了安全的編程模式;
-
界面基於Cocoa和Cocoa Touch框架;
-
保留了Smalltalk的動態特性。
十六:TCP&UDP
-
TCP(Transmission Control Protocol,傳輸控制協議)是基於連接的協議,也就是說,在正式收發數據前,必須和對方建立可靠的連接。一個TCP連接必須要經過三次“對話”才能 建立起來,其中的過程非常復雜,我們這里只做簡單、形象的介紹,你只要做到能夠理解這個過程即可。
-
UDP(User Data Protocol,用戶數據報協議)是與TCP相對應的協議。它是面向非連接的協議,它不與對方建立連接,而是直接就把數據包發送過去! UDP適用於一次只傳送少量數據、對可靠性要求不高的應用環境。
十七:POST&GET
- get是從服務器上獲取數據,post是向服務器傳送數據。
- get是把參數數據隊列加到提交表單的ACTION屬性所指的URL中,值和表單內各個字段一一對應,在URL中可以看到。post是通過 HTTP post機制,將表單內各個字段與其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址。用戶看不到這個過程。
- 對於get方式,服務器端用Request.QueryString獲取變量的值,對於post方式,服務器端用Request.Form獲取提交的數據。
- get傳送的數據量較小,不能大於2KB。post傳送的數據量較大,一般被默認為不受限制。但理論上,IIS4中最大量為80KB,IIS5中為100KB。
- get安全性非常低,post安全性較高。但是執行效率卻比Post方法好。
建議: 1、get方式的安全性較Post方式要差些,包含機密信息的話,建議用Post數據提交方式; 2、在做數據查詢時,建議用Get方式;而在做數據添加、修改或刪除時,建議用Post方式;
十八:長鏈接&短鏈接
-
TCP短連接
我們模擬一下TCP短連接的情況,client向server發起連接請求,server接到請求,然后雙方建立連接。client向server 發送消息,server回應client,然后一次讀寫就完成了,這時候雙方任何一個都可以發起close操作,不過一般都是client先發起 close操作。為什么呢,一般的server不會回復完client后立即關閉連接的,當然不排除有特殊的情況。從上面的描述看,短連接一般只會在 client/server間傳遞一次讀寫操作
-
TCP長連接
接下來我們再模擬一下長連接的情況,client向server發起連接,server接受client連接,雙方建立連接。Client與server完成一次讀寫之后,它們之間的連接並不會主動關閉,后續的讀寫操作會繼續使用這個連接。
長連接短連接操作過程
短連接的操作步驟是:
建立連接——數據傳輸——關閉連接…建立連接——數據傳輸——關閉連接
-
長連接的操作步驟是:
建立連接——數據傳輸…(保持連接)…數據傳輸——關閉連接
什么時候用長連接,短連接?
-
長連接多用於操作頻繁,點對點的通訊,而且連接數不能太多情況,。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話 那么處理速度會降低很多,所以每個操作完后都不斷開,次處理時直接發送數據包就OK了,不用建立TCP連接。例如:數據庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。
-
而像WEB網站的http服務一般都用短鏈接,因為長連接對於服務端來說會耗費一定的資源,而像WEB網站這么頻繁的成千上萬甚至上億客戶端的連接 用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以並發量大,但每個用戶無需頻繁操 作情況下需用短連好。
長連接和短連接的優點和缺點
由上可以看出,長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間。對於頻繁請求資源的客戶來說,較適用長連接。不過這里存在一個問 題,存活功能的探測周期太長,還有就是它只是探測TCP連接的存活,屬於比較斯文的做法,遇到惡意的連接時,保活功能就不夠使了。在長連接的應用場景 下,client端一般不會主動關閉它們之間的連接,Client與server之間的連接如果一直不關閉的話,會存在一個問題,隨着客戶端連接越來越 多,server早晚有扛不住的時候,這時候server端需要采取一些策略,如關閉一些長時間沒有讀寫事件發生的連接,這樣可 以避免一些惡意連接導致server端服務受損;如果條件再允許就可以以客戶端機器為顆粒度,限制每個客戶端的最大長連接數,這樣可以完全避免某個蛋疼的 客戶端連累后端服務。
-
短連接對於服務器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段。但如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬。
-
長連接和短連接的產生在於client和server采取的關閉策略,具體的應用場景采用具體的策略,沒有十全十美的選擇,只有合適的選擇。
十九:內存泄露&內存溢出
-
內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。
-
內存泄露 memory leak,是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。
memory leak會最終會導致out of memory!
內存溢出就是你要求分配的內存超出了系統能給你的,系統不能滿足需求,於是產生溢出。
二十:CoreData&SQLite3
首先,coredata和sqlite的概念不同,core為對象周期管理,而sqlite為dbms。
- 使用方便性。實際上,一個成熟的工程中一定是對數據持久化進行了封裝的,因此底層使用的到底是core data還是sqlite,不應該被業務邏輯開發者關心。因此,即使習慣寫SQL查詢的人,也應該避免在業務邏輯中直接編寫SQL語句。
- 存儲性能,在寫入性能上,因為都是使用的sqlite格式作為磁盤存儲格式,因此其性能是一樣的,如果你覺得用core data寫的慢,很可能是你用sqlite的時候寫的每條數據的內容沒有core data時多,或者是你批量寫入的時候每寫入一條就調用了一次save。
- 查詢性能,core data因為要兼容多種后端格式,因此查詢時,其可用的語句比直接使用sqlite少,因此有些fetch實際上不是在sqlite中執行的。但這樣未必 會降低查詢效率。因為iPhone的flash memory速度還是很快的。我的經驗是大部分時候,在內存不是很緊張時,直接fetch一個entity的所有數據然后在內存中做filter往往比使 用predicate在fetch時過濾更快。如果你覺的查詢慢,很可能是查詢方式有問題,可以把core data的debug模式打開,看一下到底執行了多少SQL語句,相信其中大部分是可以通過改寫core data的調用方式避免的。
- core data的一個比較大的痛點是多人合作開發的時候,管理coredata的模型需要很小心,尤其是合並的時候,他的data model是XML格式的,手動resolve比較煩心。
- core data還有其他sql所不具備的優點,比如對undo的支持,多個context實現sketchbook類似的功能。為ManagedObject優化的row cash等。
- 另外core data是支持多線程的,但需要thread confinement的方式實現,使用了多線程之后可以最大化的防止阻塞主線程。
二十一:傳值通知&推送通知(本地&遠程)
- 傳值通知:類似通知,代理,Block實現值得傳遞
-
推送通知:推送到用戶手機對應的App上(主要是不再前台的情況)
本地通知。
local notification,用於基於時間行為的通知,比如有關日歷或者todo列表的小應用。另外,應用如果在后台執行,iOS允許它在受限的時間內運 行,它也會發現本地通知有用。比如,一個應用,在后台運行,向應用的服務器端獲取消息,當消息到達時,比如下載更新版本的提示消息,通過本地通知機制通知 用戶。
本地通知是UILocalNotification的實例,主要有三類屬性:
-
scheduled time,時間周期,用來指定iOS系統發送通知的日期和時間;
- notification type,通知類型,包括警告信息、動作按鈕的標題、應用圖標上的badge(數字標記)和播放的聲音;
-
自定義數據,本地通知可以包含一個dictionary類型的本地數據。
對本地通知的數量限制,iOS最多允許最近本地通知數量是64個,超過限制的本地通知將被iOS忽略。
遠程通知(需要服務器)。
流程大概是這樣的
-
1.生成CertificateSigningRequest.certSigningRequest文件
-
2.將CertificateSigningRequest.certSigningRequest上傳進developer,導出.cer文件
-
3.利用CSR導出P12文件
-
4.需要准備下設備token值(無空格)
-
5.使用OpenSSL合成服務器所使用的推送證書
一般使用極光推送,步驟是一樣的,只是我們使用的服務器是極光的,不需要自己大服務器!
二十二:第三方庫&第三方平台
-
第三方庫:一般是指大牛封裝好的一個框架(庫),或者第三方給我們提供的一個庫,這里比較籠統 *第三方平台:指第三方提供的一些服務,其實很多方面跟第三方庫是一樣的,但是還是存在一些區別。
區別: -
庫:AFN,ASI,Alomofire,MJRefresh,MJExtension,MBProgressHUD
- 平台:極光,百度,友盟,Mob,環信
二十三:KVO&KVC
底層實現:
-
KVC運用了一個isa-swizzling技術。isa-swizzling就是類型混合指針機制。KVC主要通過isa- swizzling,來實現其內部查找定位的。isa指針,如其名稱所指,(就是is a kind of的意思),指向維護分發表的對象的類。該分發表實際上包含了指向實現類中的方法的指針,和其它數據。
-
當觀察者為一個對象的屬性進行了注冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以isa指 針其實不需要指向實例對象真實的類。所以我們的程序最好不要依賴於isa指針。在調用類的方法的時候,最好要明確對象實例的類名。
KVO概述
KVO,即:Key-Value Observing,它提供一種機制,當指定的對象的屬性被修改后,則對象就會接受到通知。簡單的說就是每次指定的被觀察的對象的屬性被修改后,KVO就會自動通知相應的觀察者了。
使用方法
系統框架已經支持KVO,所以程序員在使用的時候非常簡單。
1: 注冊,指定被觀察者的屬性,
2: 實現回調方法
3: 移除觀察
KVC概述
KVC是KeyValueCoding的簡稱,它是一種可以直接通過字符串的名字(key)來訪問類屬性(實例變量)的機制。而不是通過調用Setter、Getter方法訪問。
當使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)時,KVC是關鍵技術。
使用方法
關鍵方法定義在:NSKeyValueCodingprotocol
KVC支持類對象和內建基本數據類型。
-
獲取值
-
valueForKey:,傳入NSString屬性的名字。
-
valueForKeyPath:,傳入NSString屬性的路徑,xx.xx形式。
-
valueForUndefinedKey它的默認實現是拋出異常,可以重寫這個函數做錯誤處理。
-
-
修改值
-
setValue:forKey:
-
setValue:forKeyPath:
-
setValue:forUndefinedKey:
-
setNilValueForKey:當對非類對象屬性設置nil時,調用,默認拋出異 常。
-
-
一對多關系成員的情況
-
mutableArrayValueForKey:有序一對多關系成員 NSArray
-
mutableSetValueForKey:無序一對多關系成員 NSSet
補充:KVO與Notification之間的區別:
-
-
notification是需要一個發送notification的對象,一般是notificationCenter,來通知觀察者。
-
KVO是直接通知到觀察對象,並且邏輯非常清晰,實現步驟簡單。
二十四:時間傳遞&響應者鏈
事件的產生和傳遞過程:
-
1.發生觸摸事件后,系統會將該事件加入到一個由UIApplication管理的隊列事件中
-
2.UIApplication會從事件隊列中取出最前面的事件,並將事件分發下去以便處理,通常會先發送事件給應用程序的主窗口(keyWindow)
-
3.主窗口會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件
-
4.找到合適的視圖控件后,就會調用視圖控件的touches方法來作事件的具體處理:touchesBegin… touchesMoved…touchesEnded等
-
5.這些touches方法默認的做法是將事件順着響應者鏈條向上傳遞,將事件叫個上一個相應者進行處理
一般事件的傳遞是從父控件傳遞到子控件的
如果父控件接受不到觸摸事件,那么子控件就不可能接收到觸摸事件 UIView不能接收觸摸事件的三種情況:
-
1.不接受用戶交互:userInteractionEnabled = NO;
-
2.隱藏:hidden = YES;
-
3.透明:alpha = 0.0~0.01
用戶的觸摸事件首先會由系統截獲,進行包裝處理等。 然后遞歸遍歷所有的view,進行碰觸測試(hitTest),直到找到可以處理事件的view。 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds 大致的過程application –> window –> root view –>……–>lowest view響應者鏈
響應者鏈條其實就是很多響應者對象(繼承自UIResponder的對象)一起組合起來的鏈條稱之為響應者鏈條
一般默認做法是控件將事件順着響應者鏈條向上傳遞,將事件交給上一個響應者進行處理。那么如何判斷當前響應者的上一個響應者是誰呢?有以下兩個規則:
-
1.判斷當前是否是控制器的View,如果是控制器的View,上一個響應者就是控制器
-
2.如果不是控制器的View,上一個響應者就是父控件
當有view能夠處理觸摸事件后,開始響應事件。 系統會調用view的以下方法:
- (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; 可以多對象共同響應事件。只需要在以上方法重載中調用super的方法。 大致的過程initial view –> super view –> …..–> view controller –> window –> Application 需要特別注意的一點是,傳遞鏈中時沒有controller的,因為controller本身不具有大小的概念。但是響應鏈中是有controller的,因為controller繼承自UIResponder。
UIApplication–>UIWindow–>遞歸找到最合適處理的控件–>控件調用touches方法–>判斷是 否實現touches方法–>沒有實現默認會將事件傳遞給上一個響應者–>找到上一個響應者–>找不到方法作廢
PS:利用響應者鏈條我們可以通過調用touches的super 方法,讓多個響應者同時響應該事件。
二十五:堆&棧
一、堆棧空間分配區別:
* 1、棧(操作系統):由操作系統自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧; * 2、堆(操作系統): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似於鏈表。
二、堆棧緩存方式區別:
* 1、棧使用的是一級緩存, 他們通常都是被調用時處於存儲空間中,調用完畢立即釋放; * 2、堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定(並不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。
三、堆棧數據結構區別:
* 堆(數據結構):堆可以被看成是一棵樹,如:堆排序; * 棧(數據結構):一種先進后出的數據結構。
內存其他補充:
- 全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 - 程序結束后有系統釋放
- 文字常量區—常量字符串就是放在這里的。 程序結束后由系統釋放
- 程序代碼區—存放函數體的二進制代碼。
二十六:UDID&UUID
-
UDID是Unique Device Identifier的縮寫,中文意思是設備唯一標識.
在很多需要限制一台設備一個賬號的應用中經常會用到,在Symbian時代,我們是使用IMEI作為設備的唯一標識的,可惜的是Apple官方不允許開發者獲得設備的IMEI.
[UIDevice currentDevice] uniqueIdentifier]但是我們需要注意的一點是,對於已越獄了的設備,UDID並不是唯一的.使用Cydia插件UDIDFaker,可以為每一個應用分配不同的UDID. 所以UDID作為標識唯一設備的用途已經不大了.
-
UUID是Universally Unique Identifier的縮寫,中文意思是通用唯一識別碼.
由網上資料顯示,UUID是一個軟件建構的標准,也是被開源軟件基金會(Open Software Foundation,OSF)的組織在分布式計算環境(Distributed Computing Environment,DCE)領域的一部份.UUID的目的,是讓分布式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資 訊的指定.
二十七:CPU&GPU
-
CPU:中央處理器(英文Central Processing Unit)是一台計算機的運算核心和控制核心。CPU、內部存儲器和輸入/輸出設備是電子計算機三大核心部件。其功能主要是解釋計算機指令以及處理計算機軟件中的數據。
-
GPU:英文全稱Graphic Processing Unit,中文翻譯為“圖形處理器”。一個專門的圖形核心處理器。GPU是顯示卡的“大腦”,決定了該顯卡的檔次和大部分性能,同時也是2D顯示卡和3D 顯示卡的區別依據。2D顯示芯片在處理3D圖像和特效時主要依賴CPU的處理能力,稱為“軟加速”。3D顯示芯片是將三維圖像和特效處理功能集中在顯示芯 片內,也即所謂的“硬件加速”功能。
二十八:點(pt)&像素(px)
-
像素(pixels)是數碼顯示上最小的計算單位。在同一個屏幕尺寸,更高的PPI(每英寸的像素數目),就能顯示更多的像素,同時渲染的內容也會更清晰。
-
點(points)是一個與分辨率無關的計算單位。根據屏幕的像素密度,一個點可以包含多個像素(例如,在標准Retina顯示屏上1 pt里有2 x 2個像素)。
當你為多種顯示設備設計時,你應該以“點”為單位作參考,但設計還是以像素為單位設計的。這意味着仍然需要以3種不同的分辨率導出你的素材,不管你以哪種分辨率設計你的應用。
二十九:屬性與成員變量:
成員變量是不與外界接觸的變量,應用於類的內部,如果你說那用@Public外部不就是可以訪問了么。簡單的說public只能適當使用,不要泛濫,否則就像你把鑰匙插在你自己家門上了。誰來都可以開門。毫無安全性。
由於成員變量的私有性,為了解決外部訪問的問題就有了屬性變量。屬性變量個人認為最大的好處就是讓其他對象訪問這個變量。而且你可以設置只讀、可寫等等屬性,同時設置的方法我們也可以自己定義。記住一點,屬性變量主要是用於與其他對象相互交互的變量。
如果對於上面所說還是含糊不清那就記住這幾點吧!
- 1.只有類內使用,屬性為private,那么就定義成員變量。
- 2.如果你發現你需要的這個屬性需要是public的,那么毫不猶豫就用屬性在.h中定義。
- 3.當你自己內部需要setter實現一些功能的時候,用屬性在.m中定義。
-
4.當你自己內部需要getter實現一些功能的時候,用屬性在.m中定義。
.........
待續。。。。。。。。。。
