1:[UIScreen mainScreen].scale知識點
當屏幕分別為640x940時[[UIScreen mainScreen] scale]=2.0當屏幕分別為320x480時[[UIScreen mainScreen] scale]=1.0
2:如何正確的繪制1像素的線
#define SINGLE_LINE_WIDTH (1 / [UIScreen mainScreen].scale)#define SINGLE_LINE_ADJUST_OFFSET ((1 / [UIScreen mainScreen].scale) / 2)代碼如下:UIView *view = [[UIView alloc] initWithFrame:CGrect(x - SINGLE_LINE_ADJUST_OFFSET, 0, SINGLE_LINE_WIDTH, 100)];注意:如果線寬為偶數(shù)Point的話,則不要去設置偏移,否則線條也會失真
3:socket編程 - Asyncsocket
iphone的標準推薦是CFNetwork 庫編程,其封裝好的開源庫是 cocoa AsyncSocket庫,用它來簡化CFNetwork的調(diào)用,它提供了異步操作 主要特性有: 隊列的非阻塞的讀和寫,而且可選超時。你可以調(diào)用它讀取和寫入,它會當完成后告知你自動的socket接收。如果你調(diào)用它接收連接,它將為每個連接啟動新的實例,當然,也可以立即關閉這些連接委托(delegate)支持。錯誤、連接、接收、完整的讀取、完整的寫入、進度以及斷開連接,都可以通過委托模式調(diào)用基于run loop的,而不是線程的。雖然可以在主線程或者工作線程中使用它,但你不需要這樣做。它異步的調(diào)用委托方法,使用NSRunLoop。委托方法包括socket的參數(shù),可讓你在多個實例中區(qū)分自包含在一個類中。你無需操作流或者socket,這個類幫你做了全部支持基于IPV4和IPV6的TCP流 加入:AsynSocket.h .m與AsynUdpSocket.h .m四個文件 及CFNetwork.framework TCP客戶端 #import "AsyncSocket.h" @interface HelloiPhoneViewController : UIViewController { UITextField * textField; AsyncSocket * asyncSocket; } @PRoperty (retain, nonatomic) IBOutlet UITextField *textField; - (IBAction) buttonPressed: (id)sender; - (IBAction) textFieldDoneEditing: (id)sender; @end 在需要聯(lián)接地方使用connectToHost聯(lián)接服務器 其中initWithDelegate的參數(shù)中self是必須。這個對象指針中的各個Socket響應的函數(shù)將被ASyncSocket所調(diào)用.initWithDelegate把將當前對象傳遞進去,這樣只要在當前對象方法實現(xiàn)相應方法 asyncSocket = [[AsyncSocket alloc] initWithDelegate:self]; NSError *err = nil; if(![asyncSocket connectToHost:host on:port error:&err]) { NSLog(@"Error: %@", err); } 關于NSData對象 無論SOCKET收發(fā)都采用NSData對象.它的定義是 http://developer.apple.com/library/mac /#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html NSData主要是帶一個(id)data指向的數(shù)據(jù)空間和長度 length. NSString 轉換成NSData 對象 NSData* xmlData = [@"testdata" dataUsingEncoding:NSUTF8StringEncoding]; NSData 轉換成NSString對象 NSData * data; NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 發(fā)送數(shù)據(jù) AsyncSocket writeData 方法來發(fā)送數(shù)據(jù),它有如下定義 - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 以下是一個實例語句. NSData* aData= [@"test data" dataUsingEncoding: NSUTF8StringEncoding]; [sock writeData:aData withTimeout:-1 tag:1]; 在onSocket重載函數(shù),有如定義采用是專門用來處理SOCKET的發(fā)送數(shù)據(jù)的: -(void)onSocket(AsyncSocket *)sock didWriteDataWithTag:(long)tag { NSLog(@"thread(%),onSocket:%p didWriteDataWithTag:%d",[[NSThread currentThread] name], sock,tag); } 接收Socket數(shù)據(jù). 在onSocket重載函數(shù),有如定義采用是專門用來處理SOCKET的接收數(shù)據(jù)的. -(void) onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 在中間將其轉換成NSString進行顯示. NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"===%@",aStr); [aStr release]; 6、TCP連接讀取制定長度的數(shù)據(jù) socket連接,可能會讀取固定長度的字節(jié) [socket readDataToLength: withTimeout :tag]各方法的解析 -(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; 發(fā)生錯誤,socket關閉,可以在call-back過程調(diào)用"unreadData"去取得socket的最后的數(shù)據(jù)字節(jié),當連接的時候,該委托方法在 onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前調(diào)用 -(void)onSocketDidDisconnect:(ASyncSocket *)sock; 當socket由于或沒有錯誤而斷開連接,如果你想要在斷開連接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 釋放則不安全 -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; 當產(chǎn)生一個socket去處理連接時調(diào)用,此方法會返回 線程上的run-loop 的新的socket和其應處理的委托,如果省略,則使用[NSRunLoop cunrrentRunLoop] -(BOOL)onSocketWillConnect:(AsyncSocket *)sock; -(void)onSocket:(AsyncSocket *)sock didConnectToHost :(NSString *)host port:(UINt16)port; 當socket連接正準備讀和寫的時候調(diào)用,host屬性是一個IP地址,而不是一個DNS 名稱 -(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long) tag; 當socket已完成所要求的數(shù)據(jù)讀入內(nèi)存時調(diào)用,如果有錯誤則不調(diào)用 -(void)onSocket:(Asyncsocket *)sock didReadPartialDataOfLength:(NSUInteger)partiaLength tag:(long)tag; 當一個socket讀取數(shù)據(jù),但尚未完成讀操作的時候調(diào)用,如果使用 readToData: or readToLength: 方法 會發(fā)生,可以被用來更新進度條等東西 -(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; 當一個socket已完成請求數(shù)據(jù)的寫入時候調(diào)用 -(void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 當一個socket寫入一些數(shù)據(jù),但還沒有完成整個寫入時調(diào)用,它可以用來更新進度條等東西 -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)exapsed bytesDone:(NSUInteger)length 使用讀操作已超時但還沒完成時調(diào)用,此方法允許隨意延遲超時,如果返回一個正的時間間隔,讀取的超時將有一定量的擴展,如果不實現(xiàn)這個方法,或會像往常一樣返回一個負的時間間隔,elapsed參數(shù)是 原超時的總和,加上先前通過這種方法添加的任何補充, length參數(shù)是 讀操作到目前為止已讀取的字節(jié)數(shù), 注意,如果返回正數(shù)的話,這個方法可能被一個單獨的讀取多次調(diào)用 -(NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length; 如果一個寫操作已達到其超時但還沒完成時調(diào)用,同上 -(void)onSocketDidSecure:(AsyncSocket *)sock; 在socket成功完成ssl/tls協(xié)商時調(diào)用,此方法除非你使用提供startTLS方法時候才調(diào)用, 如果ssl/tls是無效的證書,socket將會立即關閉,onSocket:willDisconnectWithError:代理方法竟會與特定的ssl錯誤代碼一起調(diào)用 -(BOOL)canSafelySetDelegate 用來查看在改變它之前,是否帶有與當前的委托有懸而未決的業(yè)務(讀/寫)。當然,應在安全連接或接受委托之前改變委托 一旦接收或連接方法之一被調(diào)用,AsyncSocket實例會被鎖定,其他接收/連接方法在沒有先斷開socket不會被調(diào)用 如果嘗試失敗或超時,這些方法要么返回NO 要么調(diào)用 onSocket:willDisconnectWithError: 或 onSockedDidDisconnect 當傳入的連接被接受,AsyncSocket調(diào)用多個委托方法。這些方法按照時間順序排列: 1.onSocket:didAcceptNewSocket: 2.onSocket:wantsRunLoopForNewSocket: 3. onSocketWillConnect: 你的服務器的代碼將需要保留公認的socket(如果要接受它),最好的地方是要做到這一點可能在onSocket:didAcceptNewSocket:方法 在讀和寫流已經(jīng)為新接受的socket設置,onSocket:didConnectToHost:port 方法將在適當?shù)倪\行循環(huán)調(diào)用 多線程注意,如果要想通過實施onSocket:wantsRunLoopForNewSocket:,移動另一個新接收的socket去到另一個循環(huán)的socket。然后,應該在調(diào)用讀和寫或者startTLS方法前,等待直到onSocket:didConnectToHost:port:方法。否則讀和寫時間原定于不正確的runloop,會發(fā)生混亂 -(BOOL)acceptOnPort:(UInit16)port error:(NSError **)errPtr; 告訴socket開始聽取和接受指定端口上的連接,當一個連接到來的時候,AsyncSocket實例將調(diào)用各種委托方法,socket將聽取所有可用的接口(wifi,以太網(wǎng)等) -(BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error :(NSError **)errPtr; 連接給定的主機和端口,主機hostname可以是域名或者是Ip地址 -(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr; 連接到一個給定的地址,指定一個sockaddr結構包裹住一個NSData對象,例如,NSData對象從NSNetService的地址方法返回,如果有一個現(xiàn)有的sockaddr結構,可以將它轉換到一個NSData對象,像這樣: struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; -(void)disconnect; 立即斷開,任何未處理的讀或?qū)懚紝⒈粊G棄 如果socket還沒有斷開,在這個方法返回之前,onSocketDidDisconnect 委托方法將會被立即調(diào)用 注意推薦釋放AsyncSocket實例的方式: [asyncSocket setDelegate:nil]; [asyncSocket disconnect]; [asyncSocket release]; -(void)disconnectAfterReading; 在已經(jīng)完成了所有懸而未決的讀取時 斷開,在調(diào)用之后,讀取和寫入方法將無用,socket將斷開 即使仍有寫入的東西 - (NSString *)connectedHost; - (UInt16)connectedPort; - (NSString *)localHost; - (UInt16)localPort; 返回本地和遠程主機和端口給連接的socket,如果沒有連接會返回nil或0,主機將會是一個IP地址 -(NSData *)connectedAddress -(NSData *)localAddresss 返回本地和遠程的地址給連接的socket,指定一個socketaddr結構包裹在一個NSData對象 readData和writeData方法不會是block(它們是異步的) 當讀完成 onSocket:didReadData:withTag: 委托方法時調(diào)用 當寫完成 onSocket:didWriteDataWithTag: 委托方法時調(diào)用 可以選擇任何讀/寫操作的超時設置(為了不超時,使用負時間間隔。) 如果讀/寫操作超時,相應的 onSocket:shouldTimeout...委托方法被調(diào)用去選擇性地允許我們?nèi)パ娱L超時 超時后,onSocket:willDisconnectWithError: 方法被調(diào)用,緊接著是 onSocketDidDisconnect tag是為了方便,可以使用它作為數(shù)組的索引、步數(shù)、state id 、指針等 -(void)readDataWithTimeout:(NSTimeInterval)tiemout tag:(long)tag; 讀取socket上第一次成為可用的字節(jié),如果timeout值是負數(shù)的,讀操作將不使用timeout - (void)readDataWithTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInterger)offset tag:(long)tag; 讀取socket上第一次成為可用的字節(jié) 字節(jié)將被追加到給定的字節(jié)緩沖區(qū),從給定的偏移量開始 如果需要,給定的緩沖區(qū)大小將會自動增加 如果timeout值是負數(shù)的,讀操作將不使用timeout 如果緩沖區(qū)為空,socket會為我們創(chuàng)建一個緩沖區(qū) 如果bufferOffset是大于給定的緩沖區(qū)的長度,該方法將無用,委托將不會被調(diào)用 如果你傳遞一個緩沖區(qū),當AsyncSocket在使用它的時候你不能以任何方式改變它 完成之后,onSocket:didReadData:withTag 返回的數(shù)據(jù)將是一個給定的緩沖區(qū)的子集 也就是說,它將會被引用到被追加的給定的緩沖區(qū)的字節(jié) -(void)readDataToLength:(NSUInterger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 讀取給定的字節(jié)數(shù),如果length為0,方法將無用,委托將不會被調(diào)用 -(void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)tiemout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag; 讀取給定的字節(jié)數(shù),在給定的偏移開始,字節(jié)將被追加到給定的字節(jié)緩沖區(qū) -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 讀取字節(jié)直到(包括)傳入的作為分隔的"data"參數(shù) 如果傳遞0或者0長度的數(shù)據(jù),"data"參數(shù),該方法將無用,委托將不會被調(diào)用 從socket讀取一行,使用"data"參數(shù)作為行的分隔符 (如HTTP的CRLF) 注意,此方法不是字符集,因此,如果一個分隔符出現(xiàn),它自然可以作為進行編碼的一部分,讀取將提前結束 -(void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout buffer:(NSMutableData *)buffer bufferOffset:(NSUInteger) offset tag:(long)tag; 讀取字節(jié)直到(包括)傳入的作為分隔的“data”參數(shù),在給定的偏移量開始,字節(jié)將被追加到給定的字節(jié)緩沖區(qū)。 從socket讀取一行,使用"data"參數(shù)作為行的分隔符(如HTTP的CRLF) -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval) timeout tag:(long)tag; 將data寫入socket,當完成的時候委托被調(diào)用 - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 返回當前讀或?qū)懙倪M度,從0.0 到 1.0 或者 如果沒有讀/寫的時候返回Nan(使用isNan來檢查) tag、done、total如果不為空的話,它們將會被填補 - (void)startTLS:(NSDictionary *)tlsSettings; 確保使用ssl/tls連接 這方法可被隨時調(diào)用,tls握手將會發(fā)生在所有懸而未決的讀/寫完成之后。這緊跟著一個發(fā)送依賴 StartTLS消息的協(xié)議選項,在排隊升級到TLS的同一時間,而不必等待寫入完成。在這個方法被調(diào)用后,任何讀寫計劃 將會發(fā)生在安全鏈接 對于可能的keys和TLS設置的值是有據(jù)可查的 一些可能的keys是: * - kCFStreamSSLLevel * - kCFStreamSSLAllowsExpiredCertificates * - kCFStreamSSLAllowsExpiredRoots * - kCFStreamSSLAllowsAnyRoot * - kCFStreamSSLValidatesCertificateChain * - kCFStreamSSLPeerName * - kCFStreamSSLCertificates * - kCFStreamSSLIsServer 如果你傳遞空或者空字典,將使用默認的字典 默認設置將檢查以確保由簽署可信的第三方證書機構和沒有過期的遠程連接的證書 然而,它不會驗證證書上的名字,除非你給它一個名字,通過kCFStreamSSLPeerName鍵去驗證 這對安全的影響是重要的理解 想象一下你正試圖創(chuàng)建一個到MySecureServer.com的安全連接,但因為一個被攻擊的DNS服務器,所以你的socket被定向到MaliciousServer.com 如果你只是使用默認設置,MaliciousServer.com 有一個有效的證書 默認設置將無法監(jiān)測到任何問題,因為證書是有效的 在這個特殊的情況下,要妥善保護你的連接,應設置kCFStreamSSLPeerName性質(zhì)為MySecureServer.com. 如果事前你不知道對等的名字的遠程主機(例如,你不確認它是domain.com" or "www.domain.com"),那么你可以使用默認設置來驗證證書,然后在獲得驗證的發(fā)行后使用X509Certificate類來驗證,X509Certificate類的CocoaAsyncSocket開源項目的一部分 -(void)enablePrebuffering 對于處理readDataToData請求,數(shù)據(jù)是必須從socket以小增量的方式讀取出來的 性能通過允許AsyncSocket去一次性讀大塊的數(shù)據(jù)和存儲任何一個小的內(nèi)部緩沖區(qū)溢出的東西來大大提高 這被稱為預緩沖,就好像一些數(shù)據(jù)在你要求它之前就可能被讀取出來 如果你經(jīng)常使用readDataToData,使用預緩沖會有更好的性能,尤其是在iphone上 默認的預緩沖狀態(tài)是由DEFAULT_PREBUFFERING 定義控制的,強烈建議設置其為yes 這方法存在一些預緩沖需要一些不可預見的原因被默認禁用的情況,這時,這種方法存在允許當就緒時,可輕松啟用預緩沖 -(BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 當你創(chuàng)建一個AsyncSocket,它被添加到當前線程runloop 對于手動創(chuàng)建的socket,在線程上你打算使用它,它是最容易簡單的創(chuàng)建的線程上的socket 當一個新的socket被接受,委托方法 onSocket:wantsRunLoopForNewSocket 會被調(diào)用 允許你在一個單獨的線程上放置socket,這個工作最好結合在同一個線程池設計 如果,但是,在一個單獨的線程上,在之后的時間,你需要移動一個socket,這個方法可以用來完成任務 此方法必須從 當前運行的 線程/runloop 的socket 調(diào)用 注意:此方法調(diào)用后,所有進一步的方法應該從給定的runloop上調(diào)用這個對象 此外,所有委托調(diào)用將會發(fā)送到給定的runloop - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; - (BOOL)addRunLoopMode:(NSString *)runLoopMode; - (BOOL)removeRunLoopMode:(NSString *)runLoopMode; 允許你配置 socket 使用的 運行循環(huán)模式 運行循環(huán)模式設置默認是NSRunLoopCommonModes 如果你想你的socket 在其他模式下繼續(xù)操作,你可能需要添加模式 NSModalPanelRunLoopMode 或者 NSEventTrackingRunLoopMode ,或者你可能只想使用 NSRunLoopCommonModes 可接受的socket將自動 繼承相同的運行循環(huán)模式就像偵聽socket 注意:NSRunLoopCommonModes 定義在10.5,對于之前的版本可使用 kCFRunLoopCommonModes -(NSArray *)runLoopModes 返回當前正在運行的循環(huán)模式的AsyncSocket實例, run loop modes的默認設置是NSDefaultRunLoopMode -(NSData *)unreadData; 一個錯誤的事件,在 onSocket:willDisconnectWithError: 將會被調(diào)用 去讀取留在socket上的任何數(shù)據(jù) + (NSData *)CRLFData; // 0x0D0A + (NSData *)CRData; // 0x0D + (NSData *)LFData; // 0x0A + (NSData *)ZeroData; // 0x00 一些常見的分隔符,為了去使用 readDataToData:.. 方法
新聞熱點
疑難解答