iOS開發-小知識(二)

ios的一些知識點

一 非ARC的內存管理情況 
1-autorelease,當用戶的代碼在持續運行時,自動釋放池是不會被銷燬的,這段時間內用戶可以安全地使用自動釋放的對象。當用戶的代碼運行告一段落,開始等待用戶的操作,自動釋放池就會被釋放掉(調用dealloc),池中的對象都會收到一個release,有可能會因此被銷燬。 
2-成員屬性: 
readonly:不指定readonly,默認合成getter和setter方法。外界毫不關心的成員,則不要設置任何屬性,這樣封裝能增加代碼的獨立性和安全性。相當於私有成員? 
assign:表示只進行簡單的賦值,不會發送retain消息。 
retain:會向舊值發送release消息,向新值發送retain消息。 
copy:向舊值發release消息,向新值發送copy消息。 
3-引用計數特殊情況: 
NSArray:當把一個對象添加到NSArray時,對象的引用計數會加1,移除時會減1。 
UIView:addGestureRecognizer會對手勢識別器的引用計數加1,removeGestureRecognizer會減1。 
二 圖形API 
這個講的好,清晰明確:http://www.cocoachina.com/bbs/read.php?tid=77731&page=1 
1-Quartz2D,的繪圖總是發生在圖形環境(Graphics Context)中。視圖會在調用drawRect:方法進行繪圖之前,創建好圖形環境, 
通過UIGraphicsGetCurrentContext函數來獲得這個圖形環境。 
如果直接在圖像或者PDF上繪圖,需要調用CGBitmapContextCreate或者CGPDFContextCreate函數來創建圖形環境。 
Quartz2D繪圖的基礎元素是路徑。路徑可以是一些基礎幾何形狀,也可以是這些幾何形狀的組合。 
當需要創建一條路徑時,應當調用CGContextBeginPath函數; 
當需要將路徑繪製的起點移動到一個位置時,應當調用CGContextMoveToPoint函數; 
當想繪製一條線段時,應當調用CGContextAddLineToPoint。 CTM(當前變換矩陣)將繪圖從用戶空間映射到設備控件。 
當圖形環境剛剛創建時,CTM初始化爲一個單位矩陣。 
對CTM進行平移變換應當調用CGContextTranslateCTM函數,進行旋轉變換應當調用CGContextRotateCTM函數,進行縮放變換應當調用CGContextScaleCTM函數。 
2-UIBezierPath 
使用UIBezierPath繪圖的好處: 
-採用系統座標系 
-在Core Graphics的基礎上封裝,具有Core Graphics的主要功能,無需考慮圖形環境。 
UIBezierPath* pathLines = [UIBezierPath bezierPath]; 
[pathLines moveToPoint:point1]; // 移動到point1位置 
[pathLines addLineToPoint:point2]; // 畫一條從point1到point2的線 
pathLines.lineWidth = 5.0; // 線寬 
[UIColor redColor] set]; // 顏色設置 
[pathLines stroke]; // 開始描繪 
在同一UIBazierPath中,只能採用相同的顏色和線寬。 
可以調用closePath,從當前點畫一條直線到當前子路徑的初始點。如果要填充路徑,應當使用fill方法,此方法會填充路徑中得所有封閉子路徑。 
三 容器 
-NSArray和NSMutableArray 
+array:創建一個空數組 
+arrayWithArray:從另一個數組創建新的數組 
+arrayWithContentsOfFile:讀文件創建數組 
+arrayWithObject:創建一個數組,其中包含一個給定對象 
+arrayWithObjects 
+arrayWithObjects:count: 從C數組創建 
-containsObject:是否包含一個元素 
-count:數量 
-lastObject:返回最後一個 
-objectAtIndex:返回某一個 
-objectsAtIndexes:返回一組,類型爲NSArray 
-indexOfObject:返回對象索引 
-arrayByAddingObject:原數組最後加一個對象,產生一個新的數組 
-arrayByAddingObjectsFromArray:在原數組的最後添加另一個數組中的所有對象,產生一個新數組 
-subarrayWithRange:抽取原數組中得一部分,產生一個新的數組 
-isEqualToArray:比較兩個數組是否相同 
-writeToFile:atomically:保存數組至一個文件 
-writeToURL:atomically:保存數組至一個URL 
-addObject:在數組最後添加一個對象 
-addObjectsFromArray:在原數組最後添加另一個數組的全部對象 
-insertObject:atIndex:向原數組制定位置添加一個對象 
-insertObjects:atIndexes:向原數組中一系列位置添加一系列對象 
-removeAllObjects:移除數組中的全部對象 
-removeLastObject:移除數組中最後一個對象 
-removeObject:移除一個對象 
-removeObjectAtIndex:移除位於指定位置的對象 
-removeObjectsAtIndexes:移除位於一系列位置的對象 
-replaceObjectAtIndex:withObject用給定對象替換位於指定位置的對象 
-replaceObjectsAtIndexes:withObjects:多對象,多位置版本 
-setArray:用另一個數組中的所有對象來替換當前數組中的所有對象 
-NSDictionary與NSMutableDictionary 
+dictionary 
+dictionaryWithContentsOfFile 
+dictionaryWithContentsOfURL 
+dictionaryWithDictionary 
+dictionaryWithObject:forKey 
+dictionaryWithObjects:forKeys 
+dictionaryWithObjectsAndKeys 
-count:數量 
-allKeys:返回一個數組,包含字典中的所有關鍵字。 
-allKeysForObject:返回一個數組,包含所有對應到給定對象的關鍵字。 
-valueForKey:通過字符串查找數值。 
-writeToFile:atomically 
-writeToURL:atomically 
-setValue:forKey: 加鍵-值對 
-addEntriesFromDictionary: 添加另一個字典中得所有條目 
-setDictionary:將原字典中條目設置爲另一個字典中得所有條目 
-removeObjectForKey:移除一個關鍵字的對應條目 
-removeAllObjects:移除所有條目 
-removeObjectsForKeys:移除一系列關鍵字的對應條目 

四 文件系統 
1- 概述 
bundle(沙盒):一個應用只能在自己的沙盒中讀取或存儲文件,而不能操作其他沙盒中的文件。好處:保護應用的隱私不受侵犯,保護系統文件的安排,應用刪除後相關文件也能被全部清除。 
每個應用都有自己的沙盒,沙盒的根目錄的獲取方法是NSHomeDirectory()。 
根目錄下的內容: 
-.app文件,實際上是一個文件夾,包含了可執行文件、Nib文件、圖片資源、plist等。XCode中能看到的資源,及編譯後的可執行文件,都封裝在app中。 
-Documents文件夾,用於存放你的應用所產生的數據,該文件夾可通過iTunes備份,可以存儲遊戲進度等。 
-Library文件夾,用於存放用戶偏好和臨時文件。 
-tmp文件夾是系統的中轉站。 
2-文件管理器 
NSFileManager,defaultManager()返回一個文件管理器的單例(多線程下不安全)。init(),在多線程編程中應儘量使用init()。 
代理方法:-fileManager:shouldRemoveItemAtPath和-fileManager:shouldRemoveItemAtURL在移除操作之前被調用。 
-removeItemAtPath:error:刪除位於指定路徑的文件、連接、目錄(及其所有子目錄、文件)。 
-removeItemAtURL:error:同上。 
-contentOfDirectoryAtPath:查找所有位於給定路徑的子路徑和文件。返回值爲一個數組,其中包含了NSString對象。查找只在當前目錄進行,不會進入下一層目錄。 
-subpathsAtPath:查找給定路徑下的所有子路徑。深度查找,不限於當前層,也會查找package的內容。 
-fileExistsAtPath:判斷文件是否位於一個路徑下面。 
-isReadableFileAtPath:查詢文件的可讀性 
-isWritableFileAtPath:可寫性 
-isExecutableFileAtPath:查詢文件的可執行性 
-isDeletableFileAtPath:可刪除性 
3-NSString的路徑功能 
-pathWithComponent:參數是一堆components構成的數組,返回的路徑是由這些components連接而成的路徑字符串,相鄰components之間用/隔開。 
-pathComponents:返回一個數組,包含路徑中的components。 
-fileSystemRepresentation:返回C字符串 
-isAbsolutePath:判斷是否爲絕對路徑 
-pathExtension:返回文件的擴展名,沒有的就返回空字符串 
-stringByAppendingPathComponents :向現有路徑添加一個component。斜槓/會被自動加上 
-stringByAppendingPathExtension:向現有路徑加上文件的擴展名 
-stringByDeletingLastPathComponent:移除最後一個路徑component 
-stringByDeletingPathExtension:刪除路徑擴展名 
-stringByAppendingPaths:參數爲一個數組,此方法將數組中的字符串對象作爲路徑一次添加到源字符串後面。 
例子: 
NSString *homePath = NSHomeDirectory(); 
NSString *docPath = [homePath stringByAppendingFormat:@"/Documents"]; 

五 UIActionSheet 按鈕列表 
六 旋轉 
1- interfaceOrientation屬性查詢當前的界面方向。 
2- rotatingHeaderView方法來查詢當前導航視圖。 
3- rotatingFooterView來查詢當前的標籤條。 
七 快速撥打電話接口 
openURL能幫助你運行Maps,SMS,Browser,Phone甚至其他的應用程序。這是Iphone開發中我經常需要用到的一段代碼,它僅僅只有一行而已。 
[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://8004664411"]; 
這個程序通過基礎的協議支持撥打電話的功能。 
摘自:http://blog.csdn.net/smilelance/article/details/6213125 

八 區分設備類型的方法 
打電話功能只有iPhone支持,對於其他設備對應按鈕應該禁用。 
1. 用[UIDevice currentDevice].model,這個返回的是一個NSString,你可以做如下判斷就能知道設備是iPad還是iPhone. 

if ([UIDevice currentDevice].model rangeOfString:@"iPad"].location != NSNotFound) { 
NSLog(@"This is an iPad!"); 


2. 用UI_USER_INTERFACE_IDIOM()方法,這是系統定義的一條宏。使用方法也很簡單。 

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 
NSLog(@"This is an iPad!"); 


摘自:http://blog.sina.com.cn/s/blog_3f88614f0100sdcm.html 

九 併發編程 
1-GCD-Grand Central Dispatch,GCD使用隊列來管理多個任務,而每個任務是以塊(其定義類似於函數)來描述的。GCD從隊列中讀取這些要完成的任務,然後其多核執行引擎負責將這些任務分配給它所管理的線程。和手動線程管理相比,GCD能極大地優化線程管理,並極大地減少創建和銷燬線程所帶來的額外開銷。除了在多核系統上得性能改進之外,GCD還能幫助提高應用的響應速度,並讓代碼更爲乾淨,易於維護。 
2-NSOperationQueue-操作隊列,可以極大地減少開發者在併發編程中的負擔,並且操作隊列有一套Objective-C的API,使用起來方便。 
基本操作單位-NSOperation,操作。 
操作是封裝了一個與任務有關的代碼與數據的抽象類,需要繼承NSOperation,並且描述相關的任務。操作對象是一次性的,它只能執行一次,下一次,需要創建一個新的實例。 
可以通過addDependency:方法爲操作添加相互依賴性。假設操作A依賴於操作B,如果操作B沒有結束,操作A就不會開始執行。完成是指執行完,或者取消了操作。有時需要對操作是否成功作出判斷。通過removeDependency:方法來移除操作的相互依賴性。 
操作的一個屬性是isConcurrent。當使用操作隊列來管理這些操作時,isConcurrent應當設置爲NO,這時應當重載NSOperation的main函數(在類中保存controller對象-weak,並在main中調用controller的方法)。isReady屬性用於描述操作是否已經可以開始執行,isExecuting屬性表示操作是否正在執行當中,isFinished屬性表示操作是否順利完成,isCancelled屬性則表示操作已經取消。 
可以在操作運行中取消它的運行,只需要給它發送cancel消息即可。在繼承NSOperation類時,也需要支持cancel方法。 
如果只需要簡單的操作,不想繼承NSOperation類,可以使用NSInvocationOperation類,這個類中的-initWithTarget:selector:object:方法能幫助你方便地選擇人物的對象和相應的功能。 
操作的執行順序取決於各自的優先級和相互之間的依賴性。 
操作隊列有兩種方式來執行其中的操作。第一種是開闢新線程來運行這些操作,第二種則是通過GCD來運行這些操作。但是無論如何,都不需要手動管理線程。儘量使用操作隊列,只有在操作隊列的效率明顯不足時才轉向GCD。因爲操作隊列是封裝在GCD的基礎之上的,雖然增加了一些額外開銷,但是也具有更加完善的功能。例子是TestNSOperation。 

十 忙碌指示器 
UIActivityIndicator。 
UIActivityIndicatorView *activityIndicatior = [UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge]; 
activityIndicator.center = CGPointMake(512, 384); 
[self.view addSubview: activityIndicator]; 
[activityIndicator startAnimating]; 
[activityIndicator stopAnimating]; 
[activityIndicator removeFromSuperView]; 

十一 媒體播放 

1- 音頻 
[1] 音樂往往是存儲在iPod曲庫(注意位置)中的,可以通過媒體選擇器(media picker)或者媒體查詢(media query)讀取,然後用音樂播放器MPMusicPlayerController播放。 
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; 
[musicPlayer setShufleMode: MPMusicShuffleModeSongs]; 
[musicPlayer setRepeatMode: MPMusicRepeatModeAll]; 
[musicPlayer setQueueWithQuery: [MPMediaQuery songsQuery]; 
[musicPlayer play]; 

applicationMusicPlayer返回的播放器,在你的應用中播放音樂。它不會影響到iPod播放器,也不能從iPod播放器重獲取信息。 
iPodMusicPlayer返回的是iPod播放器,在你推出應用後,所有的設置都會影響到之後設備上的iPod播放器。 
獲得音樂播放器後,需要爲它設置一個播放隊列。可以用setQueueWithQuery:放方法,通過媒體查詢MPMediaQuery來設置播放隊列,也可以用setQueueWithItemCollection:方法,通過MPMdiaItemCollection來設置播放隊列。 
重複模式repeatMode可以設置爲不重複、重複當前曲目、或整個播放列表;亂序播放shuffleMode可以設置爲不亂序、亂序播放曲目或亂序播放專輯;音量volume的設置與音頻播放器一樣。 
skipToNextItem跳到下一首,skipToPreviousItem跳到上一首,skipToBegin跳到第一首。 
對應的宏都是以MPMusic開頭。 


[2] 利用系統聲音服務來播放短暫音效(時長30秒以內),並震動: 
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 

播放指定音效: 
NSURL *fileURL = [NSURL fileURLWithPath: path isDirectory: NO]; 
// 創建音效ID 
SystemSoundID soundID; 
AudioServiceCreateSystemSoundID((CFURLRef) fileURL, &soundID); 
// 播放聲音 
AudioServicesPlaySystemSound(soundID); 

[3] 音頻播放器 
沒有時長限制 
NSURL *fileURL = [NSURL fileURLWithPath: path isDirectory: NO]; 
// 用URL來初始化音頻播放器-播放的不是iPod曲庫中的音樂 
AVAudioPlayer* player = [AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: NO]; 
// 準備播放 
[player prepareToPlay]; 
// 設置代理 
[player setDelegate: self]; 

方法:play、pause、stop。可以通過playing屬性查詢播放器是否正在播放當中,可以通過volume屬性來修改和查詢播放器的播放增益(從0.0到1.0),可通過setting屬性查詢播放器其他設置。 

duration表示音頻的時間長度, currentTime表示當前播放到的時間。播放結束後可以通過代理方法audioPlayerDidFinishPlaying:來處理播放後設置。 

2- 視頻 
視頻播放可以採用網頁視圖(UIWebView)進行嵌入式播放(能播放YouTube視頻),或者採用電影播放器(MPMoviePlayerController)進行播放。 
[1] 電影播放器 
MPMoviePlayerController *player = [MPMoviePlayerController alloc]initWithContentURL: url]; 
// 設置播放器的大小,並將其加入視圖中 
[player.view setFrame: rectFrame]; 
[self.view addSubView: player.view]; 
播放器的背景視圖backgroundView。 
全屏[player setFullscreen: YES animated: YES]; 
播放另一個影片[player setContentURL: newURL]; 
[player requestThumbnailImagesAtTimes:arrayTimes timeOption:MPMovieTimeOptionNearestKeyFrame]; // 表示播放器不會在你所指定的時間去截取預覽,而是在絕對時間的附近幾幀中尋找效果最好的幀做爲預覽。 
scalingMode規定了影片的縮放模式。 
initialPlaybackTime用來控制視頻開始播放的時間,單位是秒。 
如果視頻源在網絡上,那麼需要正確設置服務器端的mimeType。 




十二 運行環-runloop 
運行環作用於一個iOS應用的整個生命週期。它負責監視各種輸入事件,並且在合適的時候對這些輸入進行分配。應用的每一個線程都有且僅有一個運行環。你自己不需要創建也不需要銷燬運行環,但是可以通過currentRunLoop方法來獲取當前的運行環。 

十三 定時器 
由於運行環機制,定時器的精度不高,只能用於一般性延時。 
例子:拼圖遊戲,DeskViewController.m。 
NSObject類的定時方法。 
performSelector: withObject: afterDelay: 運行方法,參數,時間(秒)。 
performSelectorOnMainThread: withObject: waitUntilDone: 在主線程中,運行參數selector所指定的方法,如果waitUntilDone參數爲YES,那麼當前線程會被阻攔,直到selector運行完。 
performSelector: onThread: withObject: waitUntilDone:同上,但不一定在主線程中運行。 
performSelectorInBackground: withObject: 開啓一個新線程,用於運行selector方法,selector方法應負責線程的初始化。 
cancelPreviousPerformRequestsWithTarget:取消與一個目標相關的所有計劃好的動作。 
cancelPreviousPerformRequestsWithTraget: selector: object只取消特定的計劃動作。 

十三 隨機數 
0~1之間隨機數 
CG_INLINE float genRandomNum() 

return (float)arc4random/ARCRANDOM_MAX; 


十四 加速度傳感器 
獲得加速度傳感器讀數: 
UIAccelerometer *accelerometer = [UIAccelerometer shareAccelerometer]; // 單例 
accelerometer.delegate = self; 
accelerometer.updateInterval = 1.0f / 10.0f; // 傳感器更新頻率,普通遊戲10~30HZ,虛擬現實類遊戲,30~60HZ 
accelerometer.x, accelerometer.y, accelerometer.z // 傳感器讀數 

若不想再接受傳感器讀數,可將代理設置爲nil 
[UIAccelerometer shareAccelerometer].delegate = nil; 


#define alpha 0.05 
// 獲得重力引起的加速度讀數: 
- (void)accelerometer: (UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration 

// 簡單低通濾波器 
accelX = (acceleration.x * alpha) + (accelX) * (1.0 - alpha); 
accelY = (acceleration.y * alpha) + (accelY) * (1.0 - alpha); 
accelZ = (acceleration.z * alpha) + (accelZ) * (1.0 - alpha); 


// 獲得動作引起的加速度讀數: 
- (void)accelerometer: (UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration 

// 減去低通濾波輸出,得到高通濾波輸出 
accelX = acceleration.x - ((acceleration.x * alpha) + (accelX) * (1.0 - alpha)); 
accelY = acceleration.y - ((acceleration.y * alpha) + (accelY) * (1.0 - alpha)); 
accelZ = acceleration.z - ((acceleration.z * alpha) + (accelZ) * (1.0 - alpha)); 



十五 地圖與連接服務器 
[1] 添加框架MapKit.framework。使用MKMapView來呈現地圖。注意應當直接使用此類,而不是繼承之。如果希望在MKMapView類之上添加功能,可以使用MKMapViewDelegate協議。 
初始化: 
MKMapView *mapView = [MKMapView alloc] initWithFrame: rect]; 

初始化之後並不直接顯示,還需要指定顯示的地圖區域: 
CLLocationCoordinate2D coordinate; 
coordinate.latitude = latitudeValue; // 緯度 
coordinate.longtitude = longtitudeValue; // 精度 
mapView.region = MKCoordinateRegionMakeWithDistance(coordinate, width, height); // 指定顯示區域,width和height單位都是米 
之後可以通過addSubview添加地圖。 
屬性:showsUserLocation-爲YES,系統會持續跟蹤用戶的位置 
userLocationVisible-爲YES,將顯示用戶所在位置 
顯示地圖之後,常常希望在地圖上添加標註,這需要創建一個類,並實現MKAnnotation協議,這個類叫做標註對象。標註對象往往實現setCoordinate:方法來設置其座標。在地圖視圖上,可以設置標註對象的座標,然後添加進去,這樣地圖上就會出現一個標註。代理方法title和subtitle能夠在標註上顯示標題和副標題。 
// 初始化 
mapView = [MKMapView alloc] initWithFrame: CGRectMake(100, 100, 550, 700)]; 
mapView.showsUserLocation = TRUE; 
mapView.mapType = MKMapTypeStandard; 
mapView.delegate = self; 
// 設置座標 
CLLocationCoordinate2D coordinate; 
coordinate.latitude = 37.31; 
coordinate.longtitude = -122.03; 
mapView.region = MKCoordinateRegionMakeWithDistance(coordinate, 4000, 6000); // 4000米寬,6000米高的區域 
[self.view insertSubview: mapView atIndex: 0]; 

十六 通過storyboard來初始化一個controller 
CBigDesignImageViewController *imageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"BigImageController"]; 
BigImageController是要在storyboard中設置的Identifier屬性。 

十七 給UIView子類設置陰影,包括各種控件 
1 導入QuartzCore framework 
2 #import 
3 編碼: 
[imgView layer] setShadowOffset:CGSizeMake(5, 5)]; // 陰影的範圍 
[imgView layer] setShadowRadius:2]; // 陰影擴散的範圍控制 
[imgView layer] setShadowOpacity:1]; // 陰影透明度 
[imgView layer] setShadowColor:[UIColor brownColor].CGColor]; // 陰影的顏色 

十八 設置UIScrollView滾動速度 
// 自動滾動太快,效果不好,這裏把動畫設置慢點,注意下面要直接賦值contentOffset,不要用帶animated參數的函數,否則動畫會出問題,因爲兩處都是動畫效果。 
[UIScrollView animateWithDuration:1.0f 
delay:0 
options:UIViewAnimationCurveLinear 
animations:^{ 
scrollView.contentOffset = CGPointMake(0, 0); 

completion:^(BOOL finished){} 
]; 
// 如果在減速滾動過程中,按了刷新按鈕,執行上面的動畫,會出現重置的位置,y不是0的情況,這裏再調用一次,滾動到0。 
[scrollView setContentOffset:CGPointMake(0, 0) animated:YES]; 

十九 EXC_BAD_ACCESS 
Here’s the advice I generally give to developers when you hit an EXC_BAD_ACCESS error: 
-Set the NSZombieEnabled argument in your executable options, which sometimes helps narrow down the cause 
-Run with Apple Instruments such as Leaks to look for memory issues 
-Set a breakpoint in your code and step through until you narrow down where it’s crashing 
Tried and true “comment out code till it works” then backtrack from there :] 

Xcode4 下設置 NSZombieEnabled 的方法: 
你可以點擊 Xcode4 菜單 Product -> Edit Scheme -> Arguments, 然後將點擊”加號”, 將 NSZombieEnabled 參數加到 Environment Variables 窗口中, 後面的數值寫上 ”YES”. 

或者在 Xcode4 菜單 Product -> Edit Scheme -> Diagnostics 設置窗口中直接勾上 Enable Zombie Objects 即可,Xcode 可用 cmd+shift+< 進到這個窗口。 
Xcode4 已經考慮到了現在的要求,所以提供了更便捷的設置的方式,你也可以在這個窗口中設置其他一些參數,你肯定能由此獲得更多的幫助信息。
發佈了18 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章