一、同步請求能夠從因特網請求數據,一旦發送同步請求,程序將中止用戶交互,直至服務器返回數據完成,才能夠進行下一步操做,php
二、異步請求不會阻塞主線程,而會創建一個新的線程來操做,用戶發出異步請求後,依然能夠對UI進行操做,程序能夠繼續運行css
三、GET請求,將參數直接寫在訪問路徑上。操做簡單,不過容易被外界看到,安全性不高,地址最多255字節;html
四、POST請求,將參數放到body裏面。POST請求操做相對複雜,須要將參數和地址分開,不過安全性高,參數放在body裏面,不易被捕獲。java
查看源碼打印?android
001ios
一、 同步GET請求git
//第一步,建立URL程序員
NSURL*url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];github
//第二步,經過URL建立網絡請求web
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//NSURLRequest初始化方法第一個參數:請求訪問路徑,第二個參數:緩存協議,第三個參數:網絡請求超時時間(秒)
其中緩存協議是個枚舉類型包含:
NSURLRequestUseProtocolCachePolicy(基礎策略)
NSURLRequestReloadIgnoringLocalCacheData(忽略本地緩存)
NSURLRequestReturnCacheDataElseLoad(首先使用緩存,若是沒有本地緩存,才從原地址下載)
NSURLRequestReturnCacheDataDontLoad(使用本地緩存,從不下載,若是本地沒有緩存,則請求失敗,此策略多用於離線操做)
NSURLRequestReloadIgnoringLocalAndRemoteCacheData(無視任何緩存策略,不管是本地的仍是遠程的,老是從原地址從新下載)
NSURLRequestReloadRevalidatingCacheData(若是本地緩存是有效的則不下載,其餘任何狀況都從原地址從新下載)
//第三步,鏈接服務器
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
NSLog(@"%@",str);
二、同步POST請求
//第一步,建立URL
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"];
//第二步,建立請求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@"POST"];//設置請求方式爲POST,默認爲GET
NSString *str = @"type=focus-c";//設置參數
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
//第三步,鏈接服務器
NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
NSLog(@"%@",str1);
072
三、異步GET請求
//第一步,建立url
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];
//第二步,建立請求
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//第三步,鏈接服務器
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
085
四、異步POST請求
//第一步,建立url
NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do"];
//第二步,建立請求
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
[request setHTTPMethod:@"POST"];
NSString *str = @"type=focus-c";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
//第三步,鏈接服務器
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
五、異步請求的代理方法
//接收到服務器迴應的時候調用此方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%@",[res allHeaderFields]);
self.receiveData = [NSMutableData data];
}
//接收到服務器傳輸數據的時候調用,此方法根據數據大小執行若干次
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.receiveData appendData:data];
}
//數據傳完以後調用此方法
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *receiveStr = [[NSString alloc]initWithData:self.receiveData encoding:NSUTF8StringEncoding];
NSLog(@"%@",receiveStr);
}
//網絡請求過程當中,出現任何錯誤(斷網,鏈接超時等)會進入此方法
-(void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
NSLog(@"%@",[error localizedDescription]); }
從表面的意思看get 和 post的區別get就是獲取數據,post就是發送數據。這個是誤區。其實二者均可以的,在IOS向服務器發送請求裏面能夠帶參數。
那麼這些誤區是怎麼出現的呢?先看看一下對http的解釋
通常在瀏覽器中輸入網址訪問資源都是經過GET方式;在FORM提交中,能夠經過Method指定提交方式爲GET或者POST,默認爲GET提交
Http定義了與服務器交互的不一樣方法,最基本的方法有4種,分別是GET,POST,PUT,DELETE
URL全稱是資源描述符,咱們能夠這樣認爲:一個URL地址,它用於描述一個網絡上的資源,而HTTP中的GET,POST,PUT,DELETE就對應着對這個資源的查 ,改 ,增 ,刪 4個操做。到這裏,你們應該有個大概的瞭解了,GET通常用於獲取/查詢 資源信息,而POST通常用於更新 資源信息(我的認爲這是GET和POST的本質區別,也是協議設計者的本意,其它區別都是具體表現形式的差別 )。
再進一步瞭解下他們兩個的區別:
1. GET使用URL或Cookie傳參。而POST將數據放在BODY中。
2. GET的URL會有長度上的限制,則POST的數據則能夠很是大。
3. POST比GET安全,由於數據在地址欄上不可見。
這些也是有點誤區的,就像同步請求必定的慢嗎?
GET和POST與數據如何傳遞沒有關係?
GET和POST是由HTTP協議定義的。在HTTP協議中,Method和Data(URL, Body, Header)是正交的兩個概念,也就是說,使用哪一個Method與應用層的數據如何傳輸是沒有相互關係的。
HTTP沒有要求,若是Method是POST數據就要放在BODY中。也沒有要求,若是Method是GET,數據(參數)就必定要放在URL中而不能放在BODY中。
那麼,網上流傳甚廣的這個說法是從何而來的呢?我在HTML標準中,找到了類似的描述。這和網上流傳的說法一致。可是這只是HTML標準對HTTP協議的用法的約定。怎麼能當成GET和POST的區別呢?
並且,現代的Web Server都是支持GET中包含BODY這樣的請求。雖然這種請求不可能從瀏覽器發出,可是如今的Web Server又不是隻給瀏覽器用,已經徹底地超出了HTML服務器的範疇了。
HTTP協議對GET和POST都沒有對長度的限制?
HTTP協議明確地指出了,HTTP頭和Body都沒有長度的要求。而對於URL長度上的限制,有兩方面的緣由形成:
1. 瀏覽器。聽說早期的瀏覽器會對URL長度作限制。聽說IE對URL長度會限制在2048個字符內(流傳很廣,並且無數同事都表示認同)。但我本身試了一下,我構造了90K的URL經過IE9訪問live.com,是正常的。網上的東西,哪怕是Wikipedia上的,也不能信。
2. 服務器。URL長了,對服務器處理也是一種負擔。本來一個會話就沒有多少數據,如今若是有人惡意地構造幾個幾M大小的URL,並不停地訪問你的服務器。服務器的最大併發數顯然會降低。另外一種攻擊方式是,把告訴服務器Content-Length是一個很大的數,而後只給服務器發一點兒數據,嘿嘿,服務器你就傻等着去吧。哪怕你有超時設置,這種故意的次次訪問超時也能讓服務器吃不了兜着走。有鑑於此,多數服務器出於安全啦、穩定啦方面的考慮,會給URL長度加限制。可是這個限制是針對全部HTTP請求的,與GET、POST沒有關係。
這個貌似聽着對點吧。
3.對於安全不安全講。
get:
.所謂安全的意味着該操做用於獲取信息而非修改信息。換句話說,GET請求通常不該產生反作用。就是說,它僅僅是獲取資源信息,就像數據庫查詢同樣,不會修改,增長數據,不會影響資源的狀態。
* 注意:這裏安全的含義僅僅是指是非修改信息。
POST的安全性要比GET的安全性高。注意:這裏所說的安全性和上面GET提到的「安全」不是同個概念。上面「安全」的含義僅僅是不做數據修改,而這裏安全的含義是真正的Security的含義,好比:經過GET提交數據,用戶名和密碼將明文出如今URL上,由於(1)登陸頁面有可能被瀏覽器緩存, (2)其餘人查看瀏覽器的歷史紀錄,那麼別人就能夠拿到你的帳號和密碼了,除此以外,使用GET提交數據還可能會形成Cross-site request forgery攻擊 .
看出來區別了吧
單例建立:
建立一個單例不少辦法。我先列舉一個蘋果官方文檔中的寫法。
static AccountManager *DefaultManager = nil;
+ (AccountManager *)defaultManager {
固然,在iOS4以後有了另一種寫法:
+ (AccountManager *)sharedManager
{
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}
該寫法來自 objcolumnist,文中提到,該寫法具備如下幾個特性:
1. 線程安全。
2. 知足靜態分析器的要求。
3. 兼容了ARC
http://duxinfeng.com/2015/07/14/iOS%E5%BC%80%E6%BA%90App%E6%95%B4%E7%90%86/
使用支付寶進行一個完整的支付功能,大體有如下步驟:
支付寶提供了Demo讓開發人員快速瞭解支付的接入流程:http://club.alipay.com/thread.php?fid=703,遇到技術上的問題也以到論壇提問
假設簽約之類工做已經完成,咱們開幹
要想集成支付功能,依賴如下文件夾的庫文件(把這3個添加到你的客戶端中)
接口調用步驟
1.封裝訂單模型
AlixPayOrder *order = [[AlixPayOrder alloc] init];
// 生成訂單描述
NSString *orderSpec = [order description];
2.簽名
id<DataSigner> signer = CreateRSADataSigner(@「私鑰key」);
// 傳入訂單描述 進行 簽名
NSString *signedString = [signer signString:orderSpec];
3.生成訂單字符串
NSString *orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
4.調用支付接口
AlixPay * alixpay = [AlixPay shared];
// appScheme:商戶本身的協議頭
int ret = [alixpay pay:orderString applicationScheme:appScheme];
如今隨着移動開發的快速發展,愈來愈多的應用要求在線支付功能。最近作了一個關於支付寶支付功能的應用,在使用支付寶的過程當中,遇到一些沒必要要的彎路,所以,寫了這篇文章總結一下關於ios開發如何使用支付寶。
首先,咱們須要支付寶的功能,應該去支付寶的開發平臺,下載sdk以及demo。地址:點擊進入下載頁面。
如圖:
上面就是咱們所要獲得的結果。
targets->Build Setting ->Search Paths->Head Search Paths和 Library Search Paths
切記:Head Search Paths 和 Library Search Paths的路徑必定要根據這個地址能找到對應的頭文件。否則設置總會有這個錯誤(我就在這兒耗了不少時間),如圖:
#include <openssl/rsa.h> 'openssl/rsa.h' file not found
下面是我設置的正確路徑,如圖:
好的,這裏設置已經完成了,編譯成功。
我這裏和官方demo同樣都是設置在-info文件中,固然,你也能夠自行決定放在其餘地方。
如圖:
這裏的參數來自其餘地方。。
注意代碼中有這句代碼:
因此,咱們還須要設置回調的標示。
一樣在-info文件中,添加個節點。如圖:
注意:上面的item0的值就是appScheme。
(1)官方下載ShareSDK iOS 2.8.8,地址:http://sharesdk.cn/
(2)根據實際狀況,引入相關的庫,參考官方文檔。
(3)在項目的AppDelegate中通常狀況下有三個操做,第一是註冊ShareSDK,第二是註冊各個平臺的帳號,第三是關於微信等應用的回調處理。
(4)信息分享。
(5)登陸、登出、獲取受權信息、關注制定微博
(5)你可能會看到一些應用須要第三方登陸的,一種是彈出webView加載的新浪微博或者qq的網頁受權,還有一種是跳轉到本地的已經安裝的新浪微博應用或者qq應用進行受權。第二種受權方式較SSO受權,體驗會比較好一些,由於不須要用戶輸入新浪微博或QQ的用戶名與密碼。
第二種受權方式須要在plist中配置Scheme。SSO默認是打開的不須要配置。在AppDelegate中實現回調。
(6)測試DEMO截圖:
AFNetworking是一個討人喜歡的網絡庫,適用於iOS以及Mac OS X. 它構建於在NSURLConnection, NSOperation, 以及其餘熟悉的Foundation技術之上. 它擁有良好的架構,豐富的api,以及模塊化構建方式,使得使用起來很是輕鬆.例如,他能夠使用很輕鬆的方式從一個url來獲得json數據:
1 |
NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"]; |
2 |
NSURLRequest *request = [NSURLRequest requestWithURL:url]; |
3 |
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { |
4 |
NSLog(@"Public Timeline: %@", JSON); |
5 |
} failure:nil]; |
6 |
[operation start]; |
AFURLConnectionOperation:一個 NSOperation 實現了NSURLConnection 的代理方法.
HTTP Requests:
AFHTTPRequestOperation:AFURLConnectionOperation的子類,當request使用的協議爲HTTP和HTTPS時,它壓縮了用於決定request是否成功的狀態碼和內容類型.
AFJSONRequestOperation:AFHTTPRequestOperation的一個子類,用於下載和處理jason response數據.
AFXMLRequestOperation:AFHTTPRequestOperation的一個子類,用於下載和處理xml response數據.
AFPropertyListRequestOperation:AFHTTPRequestOperation的一個子類,用於下載和處理property list response數據.
AFHTTPClient:捕獲一個基於http協議的網絡應用程序的公共交流模式.包含:
AFImageRequestOperation:一個AFHTTPRequestOperation的子類,用於下載和處理圖片.
UIImageView+AFNetworking:添加一些方法到UIImageView中,爲了從一個URL中異步加載遠程圖片
如何經過URL獲取json數據
第一種,利用AFJSONRequestOperation,官方網站上給的例子:
[objc] view plaincopy
第二種方法,利用AFHTTPRequestOperation 先獲取到字符串形式的數據,而後轉換成json格式,將NSString格式的數據轉換成json數據,利用IOS5自帶的json解析方法:
[objc] view plaincopy
若是發生Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x14defc80 {NSUnderlyingError=0x14deea10 "bad URL", NSLocalizedDescription=bad URL這個錯誤,請檢查URL編碼格式。有沒有進行stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
如何經過URL獲取圖片
異步獲取圖片,經過隊列實現,並且圖片會有緩存,在下次請求相同的連接時,系統會自動調用緩存,而不從網上請求數據。
[objc] view plaincopy
若是使用第一種URLWithString: placeholderImage:會有更多的細節處理,其實實現仍是經過AFImageRequestOperation處理,能夠點擊URLWithString: placeholderImage:方法進去看一下就一目瞭然了。因此我以爲仍是用第一種好。
如何經過URL獲取plist文件
經過url獲取plist文件的內容,用的不多,這個方法在官方提供的方法裏面沒有
[objc] view plaincopy
如何經過URL獲取XML數據
xml解析使用AFXMLRequestOperation,須要實現蘋果自帶的NSXMLParserDelegate委託方法,XML中有一些不須要的協議格式內容,因此就不能像json那樣解析,還得實現委託。我以前有想過可否全部的XML連接用一個類處理,並且跟服務端作了溝通,結果很不方便,效果很差。XML大多標籤不一樣,格式也不固定,因此就有問題,使用json就要方便的多。
第一步;在.h文件中加入委託NSXMLParserDelegate
第二步;在.m文件方法中加入代碼
[objc] view plaincopy
第三步;在.m文件中實現委託方法
//在文檔開始的時候觸發
-
[objc] view plaincopy
運行的結果:
如何使用AFHTTPClient進行web service操做
[objc] view plaincopy
運行結果:
若是須要顯示網絡活動指示器,能夠用下面方法:
[objc] view plaincopy
01 |
NSURL *url = [NSURL URLWithString:@"http://api-base-url.com"]; |
02 |
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; |
03 |
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"avatar.jpg"], 0.5); |
04 |
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) { |
05 |
[formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg" mimeType:@"image/jpeg"]; |
06 |
}]; |
07 |
|
08 |
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease]; |
09 |
[operation setUploadProgressBlock:^(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { |
10 |
NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite); |
11 |
}]; |
12 |
[operation start]; |
1 |
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/encode"]]; |
2 |
|
3 |
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease]; |
4 |
operation.inputStream = [NSInputStream inputStreamWithFileAtPath:[[NSBundle mainBundle] pathForResource:@"large-image" ofType:@"tiff"]]; |
5 |
operation.outputStream = [NSOutputStream outputStreamToMemory]; |
6 |
[operation start]; |
CoreData
1. 經常使用類和方法 ( 注意須要導入 coredata 框架 )
表結構:NSEntityDescription
表記錄:NSManagedObject 數據庫存放方式:NSPersistentStoreCoordinator(持久化存儲協調者) 數據庫操做:NSManagedObjectContext(被管理的對象上下文)
2. xcode 圖形管理
2. 3.
4.
2. 操做數據庫
一.鏈接數據庫
二.添加,更新,刪除
添加:
1. 新建實體 INST (插入) 2. 設置實體的屬性
3. 保存上下文
更新:
1. 判斷是否已有如出一轍的模型 2. 設置實體屬性
3. 保存上下文
刪除
三.查詢
1.使用 NSFetchedResultsController 控制器
2.1 當操做數據上下文的內容改變的時候,會自動調用抓取結果控制器的代理方 法
3.
注意:必定要執行抓取請求,返回的數據在 sections 裏,這個數組中裝的都是遵 守 NSFetchedResultsSectionInfo 這個協議的對象。經過
numberOfObjects 就能獲取一組有多少數據對象了。
第一部分coredata的用法
先創建一個使用use coredata的工程,
在。xcdatamodeld文件中創建表格併爲表格添加屬性
爲表格添加關係,
下一步生成表格model
其中生成的model:User和Department裏面的屬性用的是@dynamic
@property有兩個對應的詞,一個是@synthesize,一個是@dynamic。若是@synthesize和@dynamic都沒寫,那麼默認的就是@syntheszie var = _var;
@synthesize的語義是若是你沒有手動實現setter方法和getter方法,那麼編譯器會自動爲你加上這兩個方法。
@dynamic告訴編譯器,屬性的setter與getter方法由用戶本身實現,不自動生成。(固然對於readonly的屬性只需提供getter便可)。假如一個屬性被聲明爲@dynamic var,而後你沒有提供@setter方法和@getter方法,編譯的時候沒問題,可是當程序運行到instance.var =someVar,因爲缺setter方法會致使程序崩潰;或者當運行到 someVar = var時,因爲缺getter方法一樣會致使崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。
而後會再appdelegate裏自動生成如下代碼:
#pragma mark - Core Data stack
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
//存儲在沙盒裏的具體位置
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named eims.CoreDatatest in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
//託管對象
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@CoreDatatest withExtension:@momd];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
//持久化存儲協調器
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@CoreDatatest.sqlite];
NSError *error = nil;
NSString *failureReason = @There was an error creating or loading the application's saved data.;
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @Failed to initialize the application's saved data;
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@YOUR_ERROR_DOMAIN code:9999 userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@Unresolved error %@, %@, error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
//託管上下文
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@Unresolved error %@, %@, error, [error userInfo]);
abort();
}
}
}
這些代碼知道具體做用就好,若是想本身手動創建起來coredata文件,也能夠本身手動寫
下面就是在viewcontroller的具體操做,
先引入appdelegate和User,Department的頭文件
在viewcontroller裏添加
@property (strong, nonatomic)AppDelegate *myAppDelegate;屬性
而後,
具體操做,
添加:
User*user = (User*)[NSEntityDescription insertNewObjectForEntityForName:@User inManagedObjectContext:self.myAppDelegate.managedObjectContext];
[user setName:_nametextfield.text];
[user setAge:[NSNumber numberWithInteger:[_agetextfield.text integerValue]]];
[user setSex:_sextextfield.text];
NSError*error;
BOOL isSaveSuccess = [myAppDelegate.managedObjectContext save:&error];//保存(容易忘)
if (!isSaveSuccess) {
NSLog(@Error:%@,error);
_attentiontextview.text = [NSString stringWithFormat:@Error:%@,error];
}else{
NSLog(@Save Successful!);
_attentiontextview.text = @Save Successful!;
}
查詢:
//數據請求(請求):命令集
NSFetchRequest*request = [[NSFetchRequest alloc]init];
//NSEntityDescription(實體描述):表
NSEntityDescription*user = [NSEntityDescription entityForName:@Department inManagedObjectContext:myAppDelegate.managedObjectContext];
[request setEntity:user];
NSError*error;
NSArray*mutablefetchResult = [myAppDelegate.managedObjectContext
executeFetchRequest:request error:&error];
if (mutablefetchResult == nil) {
NSLog(@Error: %@,mutablefetchResult);
}
NSLog(@the count of entry:%lu,[mutablefetchResult count]);
NSString*str = @;
for (Department*user in mutablefetchResult) {
// NSLog(@name:%@------age:%@-------sex:%@,user.name,user.age,user.sex);
// str = [str stringByAppendingFormat:@name:%@------age:%@-------sex:%@ ---depart:%@ ,user.name,user.age,user.sex,user.userrelationship.departmentname];
str = [str stringByAppendingFormat:@name:%@------ ,user.departmentname];
}
NSLog(@str:%@,str);
更新:
//NSFetchRequest 數據請求(請求):命令集
NSFetchRequest*request = [[NSFetchRequest alloc]init];
//NSEntityDescription(實體描述):表
NSEntityDescription*user = [NSEntityDescription entityForName:@User inManagedObjectContext:myAppDelegate.managedObjectContext];
[request setEntity:user];
//設置查詢條件 NSPredicate (謂詞):查詢語句
NSPredicate*predicate = [NSPredicate predicateWithFormat:@name == %@,@lisi];
[request setPredicate:predicate];
NSError*error;
NSArray * mutablFetchResult = [myAppDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (mutablFetchResult == nil) {
NSLog(@Error:%@,error);
_attentiontextview.text = [NSString stringWithFormat:@Error:%@,error];
}
NSLog(@the count of entry:%lu,[mutablFetchResult count]);
for (User*user in mutablFetchResult) {
[user setAge:[NSNumber numberWithInteger:999]];
}
//判斷是否修改爲功
BOOL isSaveSuccess = [myAppDelegate.managedObjectContext save:&error];//保存(容易忘)
if (!isSaveSuccess) {
NSLog(@Error:%@,error);
_attentiontextview.text = [NSString stringWithFormat:@Error:%@,error];
}else{
NSLog(@update Successful!);
_attentiontextview.text = @update Successful!;
}
刪除:
//數據請求(命令集)
NSFetchRequest*request = [[NSFetchRequest alloc]init];
//實體描述(表)
NSEntityDescription*user = [NSEntityDescription entityForName:@Department inManagedObjectContext:myAppDelegate.managedObjectContext];
[request setEntity:user];
//設置查詢條件
NSPredicate* predicate = [NSPredicate predicateWithFormat:@departmentname == %@,@公共事業部];
[request setPredicate:predicate];
NSError*error;
NSArray*mutableFetchResult = [myAppDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (mutableFetchResult == nil) {
NSLog(@Error:%@,error);
_attentiontextview.text = [NSString stringWithFormat:@Error:%@,error];
}
NSLog(@mutableFetchResult %lu,[mutableFetchResult count]);
for (User*user in mutableFetchResult) {
[myAppDelegate.managedObjectContext deleteObject:user];
}
//判斷是否刪除成功
BOOL isDeleteSuccess = [myAppDelegate.managedObjectContext save:&error];//保存(容易忘)
if (!isDeleteSuccess) {
NSLog(@Error:%@,error);
_attentiontextview.text = [NSString stringWithFormat:@Error:%@,error];
}else{
NSLog(@delete Successful!);
_attentiontextview.text = @delete Successful!;
}
coredata並不是嚴格的說是對sqlite數據庫的一個封裝,也能夠用其餘的數據庫,並不必定要使用sqlite3,固然了coredata的好處仍是很是多的,高效,簡介,能節省至少50%的代碼量,條目清新
ViewController.m
#import "ViewController.h"
#import <CoreData/CoreData.h>
#import "Person.h"
@interface ViewController ()
@property(nonatomic,retain) NSManagedObjectContext *context;
@end
@implementation ViewController
#pragma mark -生命週期方法
- (void)viewDidLoad
{
[super viewDidLoad];
[self LoadData];
//[self UdataData];
// [self addData];
//[self deleteData];
// [self searchdata];
//面向對象操做
[self addPerson];
[self searchPerson];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidUnload{
[super viewDidUnload];
self.context=nil;
}
- (void)dealloc
{
[_context release];
[super dealloc];
}
#pragma mark-加載數據方式
-(void)LoadData{
//Nil表是從主bundles中加對應的模型實體
NSManagedObjectModel *model=[NSManagedObjectModel mergedModelFromBundles:nil];
for (NSEntityDescription *desc in model.entities) {
NSLog(@"%@",desc.name);
}
//經過模型 和數據庫持久化
NSPersistentStoreCoordinator *storeCoordinator=[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
//持久化到coredata中
NSString *document= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
document=[document stringByAppendingPathComponent:@"coredata.db"];
NSURL *url=[NSURL fileURLWithPath:document];
NSError *error=nil;
[storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
if(error){
NSLog(@"打開數據庫失敗");
return;
}
self.context=[[[NSManagedObjectContext alloc] init] autorelease];
self.context.persistentStoreCoordinator=storeCoordinator;
}
-(void)addData{
//把實體對象和實體上下文相關聯
for (int i=0; i<10; i++) {
NSManagedObject *obj=[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.context];
NSString *name=[NSString stringWithFormat:@"gcb%i",i];
int age=i;
[obj setValue: name forKey:@"name"];
[obj setValue:@(age) forKey:@"age"];
//保存上下文中相關聯的對象便可
}
[self.context save:nil];
}
-(void)searchdata{
NSFetchRequest *fetch=[NSFetchRequest fetchRequestWithEntityName:@"Person"];
//排序
NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
fetch.sortDescriptors=@[sort];
//加入查詢條件 age>20
// fetch.predicate=[NSPredicate predicateWithFormat:@"age>%i",20];
//加入like *c1"
//fetch.predicate=[NSPredicate predicateWithFormat:@"name like %@",@"*cb1*"];
NSArray *arr=[self.context executeFetchRequest:fetch error:nil];
for (NSManagedObject *mode in arr) {
NSString *name=[mode valueForKey:@"name"];
int age =[[mode valueForKey:@"age"] intValue];
NSLog(@"%zi--%@",age,name);
}
}
//先查詢出要修改的數據
-(void)UdataData{
//要操做那一張表
NSFetchRequest *Fetch=[NSFetchRequest fetchRequestWithEntityName:@"Person"];
//先建立排序描述,在排序
NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
Fetch.sortDescriptors=@[sort];
//加入查詢條件
Fetch.predicate=[NSPredicate predicateWithFormat:@"age>%i",5];
//把條件加入到上下文進行操做,獲得查詢集合
NSArray * arr=[self.context executeFetchRequest:Fetch error:nil];
for (NSManagedObject *obj in arr) {
//更改實體的數據
[obj setValue:@(50) forKey:@"age"];
}
//同步更數據庫相關聯的數據
[self.context save:nil];
}
//刪除數據, 從數據庫中取出來的對象,叫作NSManaedObject對象
-(void)deleteData{
//要找出上下文中操做的一張表
NSFetchRequest *FectchRequest=[NSFetchRequest fetchRequestWithEntityName:@"Person"];
FectchRequest.predicate=[NSPredicate predicateWithFormat:@"age<%i",50];
NSArray *arr=[self.context executeFetchRequest:FectchRequest error:nil];
for (NSManagedObject *obj in arr) {
[self.context deleteObject:obj];
}
//同步數據庫
[self.context save:nil];
}
#pragma mark-面向對象開發
-(void)addPerson{
//把要插入的實體和當前上下文相關聯
Person *ps=[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.context];
ps.name=@"mj__itcast";
ps.age=@28;
//同步數據和上下文相關聯的
[self.context save:nil];
}
-(void)searchPerson{
NSFetchRequest *FetchRequest=[NSFetchRequest fetchRequestWithEntityName:@"Person"];
NSArray *arr=[self.context executeFetchRequest:FetchRequest error:nil];
for (Person *ps in arr) {
NSLog(@"name=%@,age=%@",ps.name,ps.age);
}
}
@end
1 多線程是什麼
多線程是個複雜的概念,按字面意思是同步完成多項任務,提升了資源的使用效率,從硬件、操做系統、應用軟件不一樣的角度去看,多線程被賦予不一樣的內涵,對於硬件,如今市面上多數的CPU都是多核的,多核的CPU運算多線程更爲出色;從操做系統角度,是多任務,如今用的主流操做系統都是多任務的,能夠一邊聽歌、一邊寫博客;對於應用來講,多線程可讓應用有更快的迴應,能夠在網絡下載時,同時響應用戶的觸摸操做。在iOS應用中,對多線程最初的理解,就是併發,它的含義是原來先作燒水,再摘菜,再炒菜的工做,會變成燒水的同時去摘菜,最後去炒菜。
2 iOS 中的多線程
iOS中的多線程,是Cocoa框架下的多線程,經過Cocoa的封裝,可讓咱們更爲方便的使用線程,作過C++的同窗可能會對線程有更多的理解,好比線程的創立,信號量、共享變量有認識,Cocoa框架下會方便不少,它對線程作了封裝,有些封裝,可讓咱們建立的對象,自己便擁有線程,也就是線程的對象化抽象,從而減小咱們的工程,提供程序的健壯性。
GCD是(Grand Central Dispatch)的縮寫 ,從系統級別提供的一個易用地多線程類庫,具備運行時的特色,能充分利用多核心硬件。GCD的API接口爲C語言的函數,函數參數中多數有Block,關於Block的使用參看這裏,爲咱們提供強大的「接口」,對於GCD的使用參見本文
NSOperation與Queue
NSOperation是一個抽象類,它封裝了線程的細節實現,咱們能夠經過子類化該對象,加上NSQueue來同面向對象的思惟,管理多線程程序。具體可參看這裏:一個基於NSOperation的多線程網絡訪問的項目。
NSThread
NSThread是一個控制線程執行的對象,它不如NSOperation抽象,經過它咱們能夠方便的獲得一個線程,並控制它。但NSThread的線程之間的併發控制,是須要咱們本身來控制的,能夠經過NSCondition實現。
參看
其餘多線程
在Cocoa的框架下,通知、Timer和異步函數等都有使用多線程,(待補充).
3 iOS多線程常見面試題
在項目何時選擇使用GCD,何時選擇NSOperation?
項目中使用NSOperation的優勢是NSOperation是對線程的高度抽象,在項目中使用它,會使項目的程序結構更好,子類化NSOperation的設計思路,是具備面向對象的優勢(複用、封裝),使得實現是多線程支持,而接口簡單,建議在複雜項目中使用。
項目中使用GCD的優勢是GCD自己很是簡單、易用,對於不復雜的多線程操做,會節省代碼量,而Block參數的使用,會是代碼更爲易讀,建議在簡單項目中使用。
使用GCD處理多線程,在多核心CPU下,會提升執行效率,下面是一段在項目中使用的GCD代碼。
[cpp] view plaincopyprint?
能夠向queue裏放多個併發block。
Grand Central Dispatch (GCD) 是 Apple 開發的一個多核編程的解決方法。該方法在 Mac OS X 10.6 雪豹中首次推出,並隨後被引入到了 iOS4.0 中。GCD 是一個替代諸如 NSThread, NSOperationQueue, NSInvocationOperation 等技術的很高效和強大的技術。
GCD 和 block 的配合使用,能夠方便地進行多線程編程。
讓咱們來看一個編程場景。咱們要在 iPhone 上作一個下載網頁的功能,該功能很是簡單,就是在 iPhone 上放置一個按鈕,點擊該按鈕時,顯示一個轉動的圓圈,表示正在進行下載,下載完成以後,將內容加載到界面上的一個文本控件中。
雖然功能簡單,可是咱們必須把下載過程放到後臺線程中,不然會阻塞 UI 線程顯示。因此,若是不用 GCD, 咱們須要寫以下 3 個方法:
這 3 個方法的代碼以下。能夠看到,雖然 開始下載 –> 下載中 –> 下載完成 這 3 個步驟是整個功能的三步。可是它們卻被切分紅了 3 塊。他們之間由於是 3 個方法,因此還須要傳遞數據參數。若是是複雜的應用,數據參數極可能就不象本例子中的 NSString 那麼簡單了,另外,下載可能放到 Model 的類中來作,而界面的控制放到 View Controller 層來作,這使得原本就分開的代碼變得更加散落。代碼的可讀性大大下降。
使用 GCD 後
若是使用 GCD,以上 3 個方法均可以放到一塊兒,以下所示:
// 原代碼塊一 self.indicator.hidden = NO; [self.indicator startAnimating]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 原代碼塊二 NSURL * url = [NSURL URLWithString:@"http://www.youdao.com"]; NSError * error; NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; if (data != nil) { // 原代碼塊三 dispatch_async(dispatch_get_main_queue(), ^{ [self.indicator stopAnimating]; self.indicator.hidden = YES; self.content.text = data; }); } else { NSLog(@"error when download:%@", error); } }); |
首先咱們能夠看到,代碼變短了。由於少了原來 3 個方法的定義,也少了相互之間須要傳遞的變量的封裝。
另外,代碼變清楚了,雖然是異步的代碼,可是它們被 GCD 合理的整合在一塊兒,邏輯很是清晰。若是應用上 MVC 模式,咱們也能夠將 View Controller 層的回調函數用 GCD 的方式傳遞給 Modal 層,這相比之前用 @selector 的方式,代碼的邏輯關係會更加清楚。
block 的定義有點象函數指針,差異是用 ^ 替代了函數指針的 * 號,以下所示:
1 2 3 4 5 6 7 8 9 |
// 申明變量 (void) (^loggerBlock)(void); // 定義
loggerBlock = ^{ NSLog(@"Hello world"); }; // 調用 loggerBlock(); |
可是大多數時候,咱們一般使用內聯的方式來定義 block,即將它的程序塊寫在調用的函數裏面,例如這樣:
1 2 3 |
dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something }); |
從上面你們能夠看出,block 有以下特色:
爲了方便地使用 GCD,蘋果提供了一些方法方便咱們將 block 放在主線程 或 後臺線程執行,或者延後執行。使用的例子以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 後臺執行: dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something }); // 主線程執行: dispatch_async(dispatch_get_main_queue(), ^{ // something }); // 一次性執行: static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // code to be executed once }); // 延遲 2 秒執行: double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // code to be executed on the main queue after delay }); |
dispatch_queue_t 也能夠本身定義,如要要自定義 queue,能夠用 dispatch_queue_create 方法,示例以下:
1 2 3 4 5 |
dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL); dispatch_async(urls_queue, ^{ // your code }); dispatch_release(urls_queue); |
另外,GCD 還有一些高級用法,例如讓後臺 2 個線程並行執行,而後等 2 個線程都結束後,再彙總執行結果。這個能夠用 dispatch_group, dispatch_group_async 和 dispatch_group_notify 來實現,示例以下:
1 2 3 4 5 6 7 8 9 10 |
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 並行執行的線程一 }); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ // 並行執行的線程二 }); dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{ // 彙總結果 }); |
默認狀況下,在程序塊中訪問的外部變量是複製過去的,即寫操做不對原變量生效。可是你能夠加上 __block 來讓其寫操做生效,示例代碼以下:
1 2 3 4 5 6 |
__block int a = 0; void (^foo)(void) = ^{ a = 1; } foo(); // 這裏,a 的值被修改成 1 |
使用 block 的另外一個用處是可讓程序在後臺較長久的運行。在之前,當 app 被按 home 鍵退出後,app 僅有最多 5 秒鐘的時候作一些保存或清理資源的工做。可是應用能夠調用 UIApplication 的beginBackgroundTaskWithExpirationHandler方法,讓 app 最多有 10 分鐘的時間在後臺長久運行。這個時間能夠用來作清理本地緩存,發送統計數據等工做。
讓程序在後臺長久運行的示例代碼以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// AppDelegate.h 文件 @property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask;
// AppDelegate.m 文件 - (void)applicationDidEnterBackground:(UIApplication *)application { [self beingBackgroundUpdateTask]; // 在這裏加上你須要長久運行的代碼 [self endBackgroundUpdateTask]; }
- (void)beingBackgroundUpdateTask { self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self endBackgroundUpdateTask]; }]; }
- (void)endBackgroundUpdateTask { [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask]; self.backgroundUpdateTask = UIBackgroundTaskInvalid; } |
整體來講,GCD 可以極大地方便開發者進行多線程編程。你們應該儘可能使用 GCD 來處理後臺線程和 UI 線程的交互。
1.、NSThread
2、Cocoa NSOperation (iOS多線程編程之NSOperation和NSOperationQueue的使用)
3、GCD 全稱:Grand Central Dispatch( iOS多線程編程之Grand Central Dispatch(GCD)介紹和使用)
這三種編程方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡單,也是Apple最推薦使用的。
這篇咱們主要介紹和使用NSThread,後面會繼續2、3 的講解和使用。
NSThread:
優勢:NSThread 比其餘兩個輕量級
缺點:須要本身管理線程的生命週期,線程同步。線程同步對數據的加鎖會有必定的系統開銷
NSThread實現的技術有下面三種:
通常使用cocoa thread 技術。
Cocoa operation
優勢:不須要關心線程管理,數據同步的事情,能夠把精力放在本身須要執行的操做上。
Cocoa operation 相關的類是 NSOperation ,NSOperationQueue。NSOperation是個抽象類,使用它必須用它的子類,能夠實現它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。建立NSOperation子類的對象,把對象添加到NSOperationQueue隊列裏執行。
GCD
Grand Central Dispatch (GCD)是Apple開發的一個多核編程的解決方法。在iOS4.0開始以後才能使用。GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術的很高效和強大的技術。如今的iOS系統都升級到6了,因此不用擔憂該技術不能使用。
介紹完這三種多線程編程方式,咱們這篇先介紹NSThread的使用。
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一個是實例方法,第二個是類方法
[cpp] view plaincopy
selector :線程執行的方法,這個selector只能有一個參數,並且不能有返回值。
target :selector消息發送的對象
argument:傳輸給target的惟一參數,也能夠是nil
第一種方式會直接建立線程而且開始運行線程,第二種方式是先建立線程對象,而後再運行線程操做,在運行線程操做前能夠設置線程的優先級等線程信息
用NSObject的類方法 performSelectorInBackground:withObject: 建立一個線程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
新建項目,並在xib文件上放置一個imageView控件。按住control鍵拖到viewControll
er.h文件中建立imageView IBOutlet
ViewController.m中實現:
[cpp] view plaincopy
線程下載完圖片後怎麼通知主線程更新界面呢?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法,除了能夠更新主線程的數據外,還能夠更新其餘線程的好比:
用:performSelector:onThread:withObject:waitUntilDone:
運行下載圖片:
圖片下載下來了。
咱們演示一個經典的賣票的例子來說NSThread的線程同步:
.h
[cpp] view plaincopy
[cpp] view plaincopy
若是沒有線程同步的lock,賣票數多是-1.加上lock以後線程同步保證了數據的正確性。
上面例子我使用了兩種鎖,一種NSCondition ,一種是:NSLock。 NSCondition我已經註釋了。
他們均可以經過
[ticketsCondition signal]; 發送信號的方式,在一個線程喚醒另一個線程的等待。
好比:
[cpp] view plaincopy
wait是等待,我加了一個 線程3 去喚醒其餘兩個線程鎖中的wait
咱們能夠使用指令 @synchronized 來簡化 NSLock的使用,這樣咱們就沒必要顯示編寫建立NSLock,加鎖並解鎖相關代碼。
- (void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
還有其餘的一些鎖對象,好比:循環鎖NSRecursiveLock,條件鎖NSConditionLock,分佈式鎖NSDistributedLock等等
1 什麼是block
對於閉包(block),有不少定義,其中閉包就是可以讀取其它函數內部變量的函數,這個定義即接近本質又較好理解。對於剛接觸Block的同窗,會以爲有些繞,由於咱們習慣寫這樣的程序main(){ funA();} funA(){funB();} funB(){.....}; 就是函數main調用函數A,函數A調用函數B... 函數們依次順序執行,但現實中不全是這樣的,例如項目經理M,手下有3個程序員A、B、C,當他給程序員A安排實現功能F1時,他並不等着A完成以後,再去安排B去實現F2,而是安排給A功能F1,B功能F2,C功能F3,而後可能去寫技術文檔,而當A遇到問題時,他會來找項目經理M,當B作完時,會通知M,這就是一個異步執行的例子。在這種情形下,Block即可大顯身手,由於在項目經理M,給A安排工做時,同時會告訴A若果遇到困難,如何能找到他報告問題(例如打他手機號),這就是項目經理M給A的一個回調接口,要回掉的操做,好比接到電話,百度查詢後,返回網頁內容給A,這就是一個Block,在M交待工做時,已經定義好,而且取得了F1的任務號(局部變量),倒是在當A遇到問題時,才調用執行,跨函數在項目經理M查詢百度,得到結果後回調該block。
2 block 實現原理
Objective-C是對C語言的擴展,block的實現是基於指針和函數指針。
從計算語言的發展,最先的goto,高級語言的指針,到面嚮對象語言的block,從機器的思惟,一步步接近人的思惟,以方便開發人員更爲高效、直接的描述出現實的邏輯(需求)。
下面是兩篇很好的介紹block實現的博文
3 block的使用
使用實例
使用typed聲明block
typedef void(^didFinishBlock) (NSObject *ob);
這就聲明瞭一個didFinishBlock類型的block,
而後即可用
@property (nonatomic,copy) didFinishBlock finishBlock;
聲明一個block對象,注意對象屬性設置爲copy,接到block 參數時,便會自動複製一份。
__block是一種特殊類型,
使用該關鍵字聲明的局部變量,能夠被block所改變,而且其在原函數中的值會被改變。
4 常見系列面試題
面試時,面試官會先問一些,是否瞭解block,是否使用過block,這些問題至關於開場白,每每是下面一系列問題的開始,因此必定要如實根據本身的狀況回答。
1 使用block和使用delegate完成委託模式有什麼優勢?
首先要了解什麼是委託模式,委託模式在iOS中大量應用,其在設計模式中是適配器模式中的對象適配器,Objective-C中使用id類型指向一切對象,使委託模式更爲簡潔。瞭解委託模式的細節:
使用block實現委託模式,其優勢是回調的block代碼塊定義在委託對象函數內部,使代碼更爲緊湊;
適配對象再也不須要實現具體某個protocol,代碼更爲簡潔。
2 多線程與block
GCD與Block
使用 dispatch_async 系列方法,能夠以指定的方式執行block
dispatch_async的完整定義
void dispatch_async(
dispatch_queue_t queue,
dispatch_block_t block);
功能:在指定的隊列裏提交一個異步執行的block,不阻塞當前線程
經過queue來控制block執行的線程。主線程執行前文定義的 finishBlock對象
dispatch_async(dispatch_get_main_queue(),^(void){finishBlock();});
1 談談對Block 的理解?並寫出一個使用Block執行UIVew動畫?
答案:Block是能夠獲取其餘函數局部變量的匿名函數,其不但方便開發,而且能夠大幅提升應用的執行效率(多核心CPU可直接處理Block指令)
[cpp] view plaincopyprint?
2 寫出上面代碼的Block的定義。
答案:
typedef void(^animations) (void);
typedef void(^completion) (BOOL finished);
3 試着使用+ beginAnimations:context:以及上述Block的定義,寫出一個能夠完成
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);操做的函數執行部分
答案:無
網絡部分
3 作過的項目是否涉及網絡訪問功能,使用什麼對象完成網絡功能?
答案:ASIHTTPRequest與NSURLConnection
4 簡單介紹下NSURLConnection類及+ sendSynchronousRequest:returningResponse:error:與– initWithRequest:delegate:兩個方法的區別?
答案: NSURLConnection主要用於網絡訪問,其中+ sendSynchronousRequest:returningResponse:error:是同步訪問數據,即當前線程會阻塞,並等待request的返回的response,而– initWithRequest:delegate:使用的是異步加載,當其完成網絡訪問後,會經過delegate回到主線程,並其委託的對象。
動畫效果是IOS界面重要的特點之一,其中CAAnimation是全部動畫對象的抽象父類,做爲新人,使用較多的是UIView下的動畫方法(類方法)。使用UIView下的動畫,有下面幾個方法。
方法一:設置beginAnimations
其中memberView爲須要添加的子視圖的視圖,mivc.view爲子視圖,在使用的時候,須要將這兩個地方替換
[cpp] view plaincopyprint?
須要注意的是,必定要使用[UIView commitAnimations];動畫纔會生效
經過[UIView setAnimationDuration:1]; 設置持續時間。
在IOS4.0後,咱們有了新的方法,+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion,依然是UIView的類方法,但使用到了Block對象,Block對象是一組指令,能夠傳遞(像變量同樣),能夠把它想像成C語言的函數指針。
方法二:
其中在當前視圖下,刪除[blueViewController view],添加[yellowViewController view],在使用時,這兩個地方要替換
[cpp] view plaincopyprint?
其中animations:後的block爲對特定視圖發生的改變,其不能爲是NULL,completion:後block爲動畫執行完後,須要執行的代碼塊,能夠爲NULL。
根據手冊,在整個動畫過程當中,用戶交互對於此視圖是暫時無效的(而IOS5.0前,動畫過程當中,用戶交互對於整個應用是無效的),若是想要用戶能夠和視圖交互,能夠改變 UIViewAnimationOptionAllowUserInteraction 的值。
Cocoa Touch框架下使用大量使用委託(delegation),根據蘋果公司的文檔,delegate是Cocoa Touch框架所採用的委託模式的一種形式。實例代碼下載傳送門
理解委託,所須要的準備
(一)協議
Objective-C的協議,相似於C++的抽象類,JAVA的接口。其具體定義以下
[cpp] view plaincopyprint?
@protocol爲協議關鍵字,MyButtonDelegate爲協議名,didPressButton爲協議裏的方法。
(二)id類型
id類型能夠理解爲能夠指向任意對象的指針,
其定義爲:
[cpp] view plaincopyprint?
(三)適配器模式
在設計模式中,並無委託模式。但有適配器模式,適配器模式能夠這樣來理解,假如咱們去了香港,要給我電腦接電源,發現有些插板怎麼也插不上(香港使用的是英式插頭),只能先插個轉換器,在把電腦接到轉換器上。這就是生活中的適配器模式,大多數委託模式,就是實現的對象適配器的功能,
(四)實例
咱們想實現一個本身構建的相似於UIButton功能的組件。首先,從UIView繼承下來Mybutton,這時候遇到一個問題,咱們不知道將來誰會用到Mybutton,但咱們知道每一個用到mybutton的,都須要在這個按鈕被按下時,得到一個消息,來告訴用到mybutton的對象(Adaptee),mybuttton被按下。
這時候咱們的適配的<Target>以下:
[cpp] view plaincopyprint?
個人Adapter是Mybutton,其經過
[cpp] view plaincopyprint?
[cpp] view plaincopyprint?
來實現對Adaptee的調用,其中Adaptee能夠是任意對象,在這個例子中,是RootViewController(實現了<MyButtonDelegate>協議)
(五)委託模式的深刻理解
委託模式的實現,也能夠經過Block來實現,但僅適合一次性回調執行的代碼。
1.When to use NSMutableArray and when to use NSArray?
何時使用NSMutableArray,何時使用NSArray?
答案:當數組在程序運行時,須要不斷變化的,使用NSMutableArray,當數組在初始化後,便再也不改變的,使用NSArray。須要指出的是,使用NSArray只代表的是該數組在運行時不發生改變,即不能往NSAarry的數組裏新增和刪除元素,但不代表其數組內的元素的內容不能發生改變。NSArray是線程安全的,NSMutableArray不是線程安全的,多線程使用到NSMutableArray須要注意。
2.Give us example of what are delegate methods and what are data source methods of uitableview.
給出委託方法的實例,而且說出UITableVIew的Data Source方法
答案:CocoaTouch框架中用到了大量委託,其中UITableViewDelegate就是委託機制的典型應用,是一個典型的使用委託來實現適配器模式,其中UITableViewDelegate協議是目標,tableview是適配器,實現UITableViewDelegate協議,並將自身設置爲talbeview的delegate的對象,是被適配器,通常狀況下該對象是UITableViewController。
UITableVIew的Data Source方法有- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
3.How many autorelease you can create in your application? Is there any limit?
在應用中能夠建立多少autorelease對象,是否有限制?
答案:無
4.If we don’t create any autorelease pool in our application then is there any autorelease pool already provided to us?
若是咱們不建立內存池,是否有內存池提供給咱們?
答案:界面線程維護着本身的內存池,用戶本身建立的數據線程,則須要建立該線程的內存池
5.When you will create an autorelease pool in your application?
何時須要在程序中建立內存池?
答案:用戶本身建立的數據線程,則須要建立該線程的內存池
6.When retain count increase?
何時內存計數會增長?
答案:見iOS面試題(一)
7.What are commonly used NSObject class methods?
類NSObject的那些方法常常被使用?
答案:NSObject是Objetive-C的基類,其由NSObject類及一系列協議構成。
其中類方法alloc、class、 description 對象方法init、dealloc、– performSelector:withObject:afterDelay:等常常被使用
8.What is convenience constructor?
什麼是簡便構造方法?
答案:簡便構造方法通常由CocoaTouch框架提供,如NSNumber的 + numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:
Foundation下大部分類均有簡便構造方法,咱們能夠經過簡便構造方法,得到系統給咱們建立好的對象,而且不須要手動釋放。
9.How to design universal application in Xcode?
如何使用Xcode設計通用應用?
答案:使用MVC模式設計應用,其中Model層完成脫離界面,即在Model層,其是可運行在任何設備上,在controller層,根據iPhone與iPad(獨有UISplitViewController)的不一樣特色選擇不一樣的viewController對象。在View層,可根據現實要求,來設計,其中以xib文件設計時,其設置其爲universal。
10.What is keyword atomic in Objective C?
在Objetive-C什麼時原子關鍵字
答案:atomic,nonatomic見iOS面試題(一)
11.What are UIView animations?
UIView的動畫效果有那些?
答案:有不少,如 UIViewAnimationOptionCurveEaseInOut UIViewAnimationOptionCurveEaseIn UIViewAnimationOptionCurveEaseOut UIViewAnimationOptionTransitionFlipFromLeft UIViewAnimationOptionTransitionFlipFromRight UIViewAnimationOptionTransitionCurlUpUIViewAnimationOptionTransitionCurlDown
12.How can you store data in iPhone applications?
在iPhone應用中如何保存數據?
答案:有如下幾種保存機制:
1.經過web服務,保存在服務器上
2.經過NSCoder固化機制,將對象保存在文件中
3.經過SQlite或CoreData保存在文件數據庫中
13.What is coredata?
什麼是coredata?
答案:coredata框架是apple提供的一套通用自動的解決方案,包括了對象生存週期、對象關係圖、持久化機制。
補充答案:上面是翻譯的,按我我的理解coredata提供一種一機制,讓咱們能夠方便的把內存中對象,及對象間的關係,映射到coredata,而後由它爲咱們持久化數據。相比普通的文件數據庫SQlite,它的功能更強大,不須要咱們先將對象數據format成SQL語句,存入數據庫,再用select語句讀出,而如今是從內存到coredata的數據管理,咱們只需管理coredata的managed對象。
是蘋果提供一套數據保存
14.What is NSManagedObject model?
什麼是NSManagedObject模型?
答案:NSManagedObject是NSObject的子類 ,也是coredata的重要組成部分,它是一個通用的類,實現了core data 模型層所需的基本功能,用戶可經過子類化NSManagedObject,創建本身的數據模型。
15.What is NSManagedobjectContext?
什麼是NSManagedobjectContext?
答案:NSManagedobjectContext對象負責應用和數據庫之間的交互。
16.What is predicate?
什麼是謂詞?
答案:謂詞是經過NSPredicate,是經過給定的邏輯條件做爲約束條件,完成對數據的篩選。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];
17.What kind of persistence store we can use with coredata?
coredata有哪幾種持久化存儲機制?
答案:coredatat提供如下幾種存儲機制:XML(iOS系統不支持),自動存儲,SQLite,內存存儲。
補充說明:這個問題問的是,coredate框架的存儲機制,平時使用coredata時,更多關注的是managed的對象,這裏是coerdata框架的存儲實現細節。BTW: 其餘經常使用的持久化存儲方法 :存入到文件、 存入到NSUserDefaults(系統plist文件中)。
1.Difference between shallow copy and deep copy?
淺複製和深複製的區別?
答案:淺層複製:只複製指向對象的指針,而不復制引用對象自己。
深層複製:複製引用對象自己。
意思就是說我有個A對象,複製一份後獲得A_copy對象後,對於淺複製來講,A和A_copy指向的是同一個內存資源,複製的只不過是是一個指針,對象自己資源
仍是隻有一份,那若是咱們對A_copy執行了修改操做,那麼發現A引用的對象一樣被修改,這其實違背了咱們複製拷貝的一個思想。深複製就好理解了,內存中存在了
兩份獨立對象自己。
2.What is advantage of categories? What is difference between implementing a category and inheritance?
類別的做用?繼承和類別在實現中有何區別?
答案:category 能夠在不獲悉,不改變原來代碼的狀況下往裏面添加新的方法,只能添加,不能刪除修改。
而且若是類別和原來類中的方法產生名稱衝突,則類別將覆蓋原來的方法,由於類別具備更高的優先級。
類別主要有3個做用:
(1)將類的實現分散到多個不一樣文件或多個不一樣框架中。
(2)建立對私有方法的前向引用。
(3)向對象添加非正式協議。
繼承能夠增長,擴展父類方法,而且能夠增長屬性。
3.Difference between categories and extensions?
類別和類擴展的區別。
答案:category和extensions的不一樣在於 後者能夠添加屬性。另外後者添加的方法是必需要實現的。
extensions能夠認爲是一個私有的Category。
4.Difference between protocol in objective c and interfaces in java?
oc中的協議和java中的接口概念有何不一樣?
答案:OC中的協議有2層含義,官方定義爲 formal和informal protocol。前者和Java接口同樣。
informal protocol中的方法屬於設計模式考慮範疇,不是必須實現的,可是若是有實現,就會改變類的屬性。
其實關於正式協議,類別和非正式協議我很早前學習的時候大體看過,也寫在了學習教程裏
「非正式協議概念其實就是類別的另外一種表達方式「這裏有一些你可能但願實現的方法,你能夠使用他們更好的完成工做」。
這個意思是,這些是可選的。好比我門要一個更好的方法,咱們就會申明一個這樣的類別去實現。而後你在後期能夠直接使用這些更好的方法。
這麼看,總以爲類別這玩意兒有點像協議的可選協議。"
如今來看,其實protocal已經開始對二者都統一和規範起來操做,由於資料中說「非正式協議使用interface修飾「,
如今咱們看到協議中兩個修飾詞:「必須實現(@requied)」和「可選實現(@optional)」。
OC中的協議(formal protocol)與java中的接口概念基本一致,OC中非正式協議(informal protocol)就是類別。在java中若是繼承了接口,但不實現其方法,會獲得一個error(沒法編譯);在OC中的正式協議,若是不實現,會獲得一個warning(可編譯執行),若是想去除waring,還能夠加關鍵字(@optional),讓它可選實現方法。
5.What are KVO and KVC?
答案:kvc:鍵 - 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是經過調用存取方法,直接或經過實例變量訪問的機制。
不少狀況下能夠簡化程序代碼。apple文檔其實給了一個很好的例子。
kvo:鍵值觀察機制,他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對於按鈕點擊變化狀態的的監控。
好比我自定義的一個button
[cpp]
[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異常錯誤。
(cocoachina.com注:Key-Value Coding查找方法的時候,不只僅會查找someKey這個方法,還會查找getsomeKey這個方法,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時,查找實例變量的時候也會不只僅查找someKey這個變量,也會查找_someKey這個變量是否存在。)
設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象可以在錯誤發生前,有最後的機會響應這個請求。這樣作有不少好處,下面的兩個例子說明了這樣作的好處。「
來至cocoa,這個說法應該挺有道理。
由於咱們知道button倒是存在一個highlighted實例變量.所以爲什麼上面咱們只是add一個相關的keypath就好了,
能夠按照kvc查找的邏輯理解,就說的過去了。
6.What is purpose of delegates?
代理的做用?
答案:代理的目的是改變或傳遞控制鏈。容許一個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。能夠減小框架複雜度。
另一點,代理能夠理解爲java中的回調監聽機制的一種相似。
7.What are mutable and immutable types in Objective C?
oc中可修改和不能夠修改類型。
答案:可修改不可修改的集合類。這個我我的簡單理解就是可動態添加修改和不可動態添加修改同樣。
好比NSArray和NSMutableArray。前者在初始化後的內存控件就是固定不可變的,後者能夠添加等,能夠動態申請新的內存空間。
8.When we call objective c is runtime language what does it mean?
咱們說的oc是動態運行時語言是什麼意思?
答案:多態。 主要是將數據類型的肯定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來講,運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。
多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;
那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。
也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。
所以也能夠說,運行時機制是多態的基礎?~~~
9.what is difference between NSNotification and protocol?
通知和協議的不一樣之處?
答案:協議有控制鏈(has-a)的關係,通知沒有。
首先我一開始也不太明白,什麼叫控制鏈(專業術語了~)。可是簡單分析下通知和代理的行爲模式,咱們大體能夠有本身的理解
簡單來講,通知的話,它能夠一對多,一條消息能夠發送給多個消息接受者。
代理按咱們的理解,到不是直接說不能一對多,好比咱們知道的明星經濟代理人,不少時候一個經濟人負責好幾個明星的事務。
只是對於不一樣明星間,代理的事物對象都是不同的,一一對應,不可能說明天要處理A明星要一個發佈會,代理人發出處理髮佈會的消息後,別稱B的
發佈會了。可是通知就不同,他只關心發出通知,而不關心多少接收到感興趣要處理。
所以控制鏈(has-a從英語單詞大體能夠看出,單一擁有和可控制的對應關係。
10.What is push notification?
什麼是推送消息?
答案:
推送通知更是一種技術。
簡單點就是客戶端獲取資源的一種手段。
普通狀況下,都是客戶端主動的pull。
推送則是服務器端主動push。 測試push的實現能夠查看該博文。
11.Polymorphism?
關於多態性
答案:多態,父類指針指向子類對象。
這個題目其實能夠出到一切面向對象語言中,
所以關於多態,繼承和封裝基本最好都有個自我意識的理解,也並不是必定要把書上資料上寫的能背出來。
最重要的是轉化成自我理解。
12.Singleton?
對於單例的理解
答案:11,12題目其實出的有點泛泛的感受了,可能說是編程語言須要或是必備的基礎。
基本能用熟悉的語言寫出一個單例,以及能夠運用到的場景或是你編程中碰到過運用的此種模式的框架類等。
進一步點,考慮下如何在多線程訪問單例時的安全性。
13.What is responder chain?
說說響應鏈
答案: 事件響應鏈。包括點擊事件,畫面刷新事件等。在視圖棧內從上至下,或者從下之上傳播。
能夠說點事件的分發,傳遞以及處理。具體能夠去看下touch事件這塊。由於問的太抽象化了
嚴重懷疑題目出到越後面就越籠統。
能夠從責任鏈模式,來說經過事件響應鏈處理,其擁有的擴展性
14.Difference between frame and bounds?
frame和bounds有什麼不一樣?
答案:frame指的是:該view在父view座標系統中的位置和大小。(參照點是父親的座標系統)
bounds指的是:該view在自己座標系統中 的位置和大小。(參照點是自己座標系統)
15.Difference between method and selector?
方法和選擇器有何不一樣?
答案:selector是一個方法的名字,method是一個組合體,包含了名字和實現.
詳情能夠看apple文檔。
16.Is there any garbage collection mechanism in Objective C.?
OC的垃圾回收機制?
答案: OC2.0有Garbage collection,可是iOS平臺不提供。
通常咱們瞭解的objective-c對於內存管理都是手動操做的,可是也有自動釋放池。
可是差了大部分資料,貌似不要和arc機制搞混就行了。
求更多~~
17.NSOperation queue?
答案:存放NSOperation的集合類。
操做和操做隊列,基本能夠當作java中的線程和線程池的概念。用於處理ios多線程開發的問題。
網上部分資料提到一點是,雖然是queue,可是卻並非帶有隊列的概念,放入的操做並不是是按照嚴格的先進現出。
這邊又有個疑點是,對於隊列來講,先進先出的概念是Afunc添加進隊列,Bfunc緊跟着也進入隊列,Afunc先執行這個是必然的,
可是Bfunc是等Afunc徹底操做完之後,B纔開始啓動而且執行,所以隊列的概念理論上有點違背了多線程處理這個概念。
可是轉念一想其實能夠參考銀行的取票和叫號系統。
所以對於A比B先排隊取票可是B率先執行完操做,咱們亦然能夠感性認爲這仍是一個隊列。
可是後來看到一票關於這操做隊列話題的文章,其中有一句提到
「由於兩個操做提交的時間間隔很近,線程池中的線程,誰先啓動是不定的。」
瞬間以爲這個queue名字有點忽悠人了,還不如pool~
綜合一點,咱們知道他能夠比較大的用處在於能夠幫助多線程編程就行了。
樓上區分了線程執行時的次序(Afunc和Bfunc誰先啓動)和線程執行完成(Afunc和Bfunc誰先執行完)時的次序不一樣,而多線程的重要概念是併發(同時執行多個任務),NSOperationQueue是管理併發線程的對象,能夠在其中放入NSOpertation對象(對象化的線程實體),經過設置maxConcurrentOperationCount的大小,控制併發數目,如樓上所說但願「Afunc添加進隊列,執行完後,Bfunc緊跟進入隊列,繼續執行」,那隻需將maxConcurrentOperationCount設爲1,變會依次執行,這時候實際是在單線程依次執行。因此這裏的NSOperationQueue就是對象化抽象的去管理多線程,這樣的好處,使用者經過繼承NSOperation對象,能夠方便的用對象來管理線程,而再也不用關心線程同步、信號量等細節,更多地關注於業務邏輯。
18.What is lazy loading?
答案:懶漢模式,只在用到的時候纔去初始化。
也能夠理解成延時加載。
我以爲最好也最簡單的一個列子就是tableView中圖片的加載顯示了。
一個延時載,避免內存太高,一個異步加載,避免線程堵塞。
19.Can we use two tableview controllers on one viewcontroller?
是否在一個視圖控制器中嵌入兩個tableview控制器?
答案:一個視圖控制只提供了一個View視圖,理論上一個tableViewController也不能放吧,
只能說能夠嵌入一個tableview視圖。固然,題目自己也有歧義,若是不是咱們定性思惟認爲的UIViewController,
而是宏觀的表示視圖控制者,那咱們卻是能夠把其當作一個視圖控制者,它能夠控制多個視圖控制器,好比TabbarController
那樣的感受。
20.Can we use one tableview with two different datasources? How you will achieve this?
一個tableView是否能夠關聯兩個不一樣的數據源?你會怎麼處理?
答案:首先咱們從代碼來看,數據源如何關聯上的,實際上是在數據源關聯的代理方法裏實現的。
所以咱們並不關心如何去關聯他,他怎麼關聯上,方法只是讓我返回根據本身的須要去設置如相關的數據源。
所以,我以爲能夠設置多個數據源啊,可是有個問題是,你這是想幹嗎呢?想讓列表如何顯示,不一樣的數據源分區塊顯示?
1. Object-c的類能夠多重繼承麼?能夠實現多個接口麼?Category是什麼?重寫一個類的方式用繼承好仍是分類好?爲何?
Object-c的類不能夠多重繼承;能夠實現多個接口,經過實現多個接口能夠完成C++的多重繼承;Category是類別,通常狀況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其餘類與原有類的關係。
2.#import 跟#include 又什麼區別,@class呢, #import<> 跟 #import」"又什麼區別?
#import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字,使用#import頭文件會自動只導入一次,不會重複導入,至關於#include和#pragma once;@class告訴編譯器某個類的聲明,當執行時,纔去查看類的實現文件,能夠解決頭文件的相互包含;#import<>用來包含系統的頭文件,#import」」用來包含用戶頭文件。
3. 屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什麼做用,在那種狀況下用?
readwrite 是可讀可寫特性;須要生成getter方法和setter方法時
readonly 是隻讀特性 只會生成getter方法 不會生成setter方法 ;不但願屬性在類外改變
assign 是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain 表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy 表示拷貝特性,setter方法將傳入對象複製一份;須要徹底一份新的變量時。
nonatomic 非原子操做,決定編譯器生成的setter getter是不是原子操做,atomic表示多線程安全,通常使用nonatomic
4.寫一個setter方法用於完成@property (nonatomic,retain)NSString *name,寫一個setter方法用於完成@property(nonatomic,copy)NSString *name
[cpp] view plaincopyprint?
5.對於語句NSString*obj = [[NSData alloc] init]; obj在編譯時和運行時分別時什麼類型的對象?
編譯時是NSString的類型;運行時是NSData類型的對象
6.常見的object-c的數據類型有那些, 和C的基本數據類型有什麼區別?如:NSInteger和int
object-c的數據類型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,這些都是class,建立後即是對象,而C語言的基本數據類型int,只是必定字節的內存空間,用於存放數值;NSInteger是基本數據類型,並非NSNumber的子類,固然也不是NSObject的子類。NSInteger是基本數據類型Int或者Long的別名(NSInteger的定義typedef long NSInteger),它的區別在於,NSInteger會根據系統是32位仍是64位來決定是自己是int仍是Long。
7.id 聲明的對象有什麼特性?
Id 聲明的對象具備運行時的特性,便可以指向任意類型的objcetive-c的對象;
8.Objective-C如何對內存管理的,說說你的見解和解決方法?
Objective-C的內存管理主要有三種方式ARC(自動內存計數)、手動內存計數、內存池。
9.內存管理的幾條原則時什麼?按照默認法則.那些關鍵字生成的對象
須要手動釋放?在和property結合的時候怎樣有效的避免內存泄露?
誰申請,誰釋放
遵循Cocoa Touch的使用原則;
內存管理主要要避免「過早釋放」和「內存泄漏」,對於「過早釋放」須要注意@property設置特性時,必定要用對特性關鍵字,對於「內存泄漏」,必定要申請了要負責釋放,要細心。
關鍵字alloc 或new 生成的對象須要手動釋放;
設置正確的property屬性,對於retain須要在合適的地方釋放,
10.如何對iOS設備進行性能測試?
Profile-> Instruments ->Time Profiler
11.看下面的程序,第一個NSLog會輸出什麼?這時str的retainCount是多少?第二個和第三個呢? 爲何?
[cpp] view plaincopyprint?
str的retainCount建立+1,retain+1,加入數組自動+1
3
retain+1,release-1,release-1
2
數組刪除全部對象,全部數組內的對象自動-1
1
12. Object C中建立線程的方法是什麼?若是在主線程中執行代碼,方法是什麼?若是想延時執行代碼、方法又是什麼?
線程建立有三種方法:使用NSThread建立、使用GCD的dispatch、使用子類化的NSOperation,而後將其加入NSOperationQueue;在主線程執行代碼,方法是performSelectorOnMainThread,若是想延時執行代碼能夠用performSelector:onThread:withObject: afterDelay: 或者使用GCD的函數:dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒後異步執行這裏的代碼...
});
13.描述一下iOS SDK中如何實現MVC的開發模式
MVC是模型、試圖、控制開發模式,對於iOS SDK,全部的View都是視圖層的,它應該獨立於模型層,由視圖控制層來控制。全部的用戶數據都是模型層,它應該獨立於視圖。全部的ViewController都是控制層,由它負責控制視圖,訪問模型數據。
來源:http://blog.csdn.net/enuola/article/details/8627283
推送通知,也被叫作遠程通知,是在iOS 3.0之後被引入的功能。是當程序沒有啓動或不在前臺運行時,告訴用戶有新消息的一種途徑,是從外部服務器發送到應用程序上的。通常說來,當要顯示消息或 下載數據的時候,通知是由遠程服務器(程序的提供者)發送,而後經過蘋果的推送通知服務(Apple Push Notification Service,簡稱apns)推送到設備的程序上。
推送的新消息多是一條信息、一項即將到期的日程或是一份遠程服務器上的新數據。在系統上展示的時候,能夠顯示警告信息或在程序icon上顯示數字,同 時,也能夠播放警告音。一旦用戶注意到程序有新的信息、時間或是數據,他們能夠運行程序並訪問新的內容。也能夠選擇忽略通知,這時程序將不會被激活。
iPhone, iPad和iPod touch上同一時刻只有一個app在前臺運行。大多數程序在後臺運行的時候,能夠對某些用戶感興趣的內容作出迴應(定時、或數據等)。推送通知能讓程序在這些事件發生的時候通知用戶。
做爲提供者爲程序開發和部署推送通知,必須經過iOS Developer Program Portal得到SSL證書。每一個證書限用於一個程序,使用程序的bundle ID做爲標識。證書有兩種用途的:一種是針對sandbox(用於開發和測試),另一種針對發佈產品。這兩種運行環境擁有爲各自指定的IP地址而且須要 不一樣的證書。還必須爲兩種不一樣的環境獲取各自的provisioning profiles。
APNS提供了兩項基本的服務:消息推送和反饋服務。
消息推送:使用流式TCP套接字將推送通知做爲二進制數據發送給APNs。消息推送有分別針對開發和測試用的sandbox、發佈產品的兩個接口,每一個都 有各自的地址和端口。無論用哪一個接口,都須要經過TLS或SSL,使用SSL證書來創建一個安全的信道。提供者編制通知信息,而後經過這個信道將其發送給 APNs。
注:sandbox: gateway.sandbox.push.apple.com:219
產品接口:gateway.push.apple.com:2195
反饋服務:能夠獲得針對某個程序的發送失敗記錄。提供者應該使用反饋服務週期性檢查哪些設備一直收不到通知,不須要重複發送通知到這些設備,下降推送服務器的負擔。
注:sandbox:feedback.push.apple.com:2196
產品接口:feedback.sandbox.push.apple.com:2196
下面是一個完整推送流程圖
從上圖,咱們能夠看到。
不管是iPhone客戶端跟APNS,仍是Provider和APNS都須要經過證書進行鏈接的:
圖中,
1. Provider是指某個iPhone軟件的Push服務器,是咱們將要開發的服務器。
2. APNS 是Apple Push Notification Service(Apple Push服務器)的縮寫,是蘋果的服務器。
上圖能夠分爲三個階段:
第一階段:推送服務器(provider)把要發送的消息、目的iPhone的標識打包,發給APNS;
第二階段:APNS在自身的已註冊Push服務的iPhone列表中,查找有相應標識的iPhone,並把消息發到iPhone;
第三階段:iPhone把發來的消息傳遞給相應的應用程序,而且按照設定彈出Push通知。
爲使應用能支持推送功能,咱們的項目配置時要注意:
在代碼方面,推送的註冊、監聽和處理都集中在AppDelegate類裏:
1.(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
在該方法體裏主要實現兩個功能:
一是完成推送功能的註冊請求,即在程序啓動時彈出是否使用推送功能;
二是實現的程序啓動是經過推送消息窗口觸發的,在這裏能夠處理推送內容;
2. 接收從蘋果服務器返回的惟一的設備token,該token是推送服務器發送推送消息的依據,因此須要發送回推送服務器保存
3.接收註冊推送通知功能時出現的錯誤,並作相關處理:
4. 接收到推送消息,解析處理
經過上面的代碼,基本推送功能的開發已經完成了。最後附件上面代碼中所需用到的DeviceSender的類文件,須要將其頭文件導入到AppDelegate中。
注意:有的App ID的Apple Push Notification service列是灰色的,而且不容許使用Configure按鈕,這是由於APNS不支持帶通配符的App ID。
到如今爲止,咱們已經生成了三個文件:
1、Push.certSigningRequest
2、Push.p12
3、aps_developer_identity.cer
在項目的AppDelegate中的didFinishLaunchingWithOptions方法中加入下面的代碼:
經過registerForRemoteNotificationTypes方法,告訴應用程序,能接受push來的通知。
在項目的AppDelegate中添加下面的方法來獲取deviceToken:
獲取到的deviceToken,咱們能夠提交給後臺應用程序,發送通知的後臺應用程序除了須要知道deviceToken以外,還須要一個與APNS鏈接的證書。
這個證書能夠經過咱們前面生成的兩個文件中獲得。
1、將aps_developer_identity.cer轉換成aps_developer_identity.pem格式
2、將p12格式的私鑰轉換成pem
3、建立p12文件
這樣咱們就獲得了在.net或java等後臺應用程序中使用的證書文件:aps_developer_identity.p12
若是後臺應用是php的話,那麼能夠按照 iOS消息推送機制中pem文件的生成這篇文章中的方法來生成php後臺應用程序中使用的證書文件:ck.pem
SQLite是嵌入式的和輕量級的sql數據庫。普遍用於包括瀏覽器、ios、android以及一些便攜需求的小型web應用系統。
SQLite是MySQL的精簡版,無需服務器就能進行;限制條件:必須手動建立數據庫,沒有面向對象的接口;
Demo作了個簡單的保存學生信息的例子,點擊保存按鈕能夠保存信息,點擊查詢能夠查詢信息,Demo下載地址:http://download.csdn.net/detail/weasleyqi/4706760 。
要想在工程中使用SQLite,須要將SQLite的庫添加到工程:
在本工程中的.h文件中引用這個庫:
[css] view plaincopy
建立數據庫:
接下來若是該數據庫不存在須要建立這個數據庫,建立的過程寫在viewDidLoad裏面:
[css] view plaincopy
由於SQLite數據庫是文件數據庫,是保存在文件系統中的,ios下:
咱們的數據庫文件是保存在Documents下的。
切記,由於用的是C語法,sqlite3_open傳入的是database的地址!
保存信息:
[css] view plaincopy
在往數據庫裏面插入數據的時候,咱們須要先打開數據庫,而後執行插入語句,結束的時候切記要關閉數據庫!
查詢操做:
[css] view plaincopy
查詢操做一樣也是須要先打開數據庫,再查詢,最後關閉數據庫,在這裏就指定了根據學號來查詢,其餘狀況未涉及。
在本例中還涉及一個觸摸屏幕來關閉鍵盤:
在viewcontroller.h中添加申明代碼:
[css] view plaincopy
經過觸摸屏幕來關閉鍵盤須要咱們的.xib文件的class爲UIControl,點擊viewController.xib文件,選中view,打開 Identity Inspector,在class中選擇UIConrol,再選擇Connector Inspector,找到Touch Down,把圓圈中的線映射到剛剛的IBAction;
在viewController.m文件中實現該方法:
[css] view plaincopy
這樣,基本上就完成了
1、離線緩存
在項目開發中,一般都須要對數據進行離線緩存的處理,如新聞數據的離線緩存等。
說明:離線緩存通常都是把數據保存到項目的沙盒中。有如下幾種方式
(1)歸檔:NSCodeing、NSKeyedArchiver
(2)偏好設置:NSUserDefaults
(3)Plist存儲:writeToFile
提示:上述三種方法都有一個致命的缺點,那就是都沒法存儲大批量的數據,有性能的問題。
舉例:使用歸檔
兩個問題:
(1)數據的存取都必須是完整的,要求寫入的時候要一次性寫入,讀取的時候要一次性所有讀取,這涉及到應用的性能問題。
(2)若是有1000條數據,此時要把第1001條數據存入,那麼須要把全部的數據取出來,把這條數據加上去以後,再存入。
說明:以上的三種技術不能處理大批量數據的存儲,大批量數據一般使用數據庫來進行存儲。
2、SQLite簡單介紹
1.ios中數據的存儲方式
(1)Plist(NSArray\NSDictionary)
(2)Preference(偏好設置\NSUserDefaults)
(3)NSCoding(NSKeyedArchiver\NSkeyedUnarchiver)
(4)SQLite3
(5)Core Data
說明:
3是版本號,是SQLite的第三個版本。
core Data是對SQLite的封裝,由於iOS中使用的SQLite是純C語言的。
2.SQLite
(1)什麼是SQLite?
答:SQLite是一款輕型的嵌入式數據庫,安卓和ios開發使用的都是SQLite數據庫
(2)特色(優勢)
答:1)它佔用資源很是的低,在嵌入式設備中,可能只須要幾百K的內存就夠了
2)它的處理速度比Mysql、PostgreSQL這兩款著名的數據庫都還快
(3)什麼是數據庫
答:數據庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫
(4)數據庫的分類
答:能夠分爲2大種類
關係型數據庫(主流)和對象型數據庫(直接把內存中的對象塞入到數據庫,對比關係型數據庫而言性能不能很好,效率不高)
(5)經常使用關係型數據庫有哪些?
答:PC端:Oracle、MySQL、SQL Server、Access、DB二、Sybase
嵌入式\移動客戶端:SQLite
(6)數據庫是如何存儲數據的?
答:數據庫的存儲結構和excel很像,以表(table)爲單位 。表由多個字段(列、屬性、column)組成,表裏面的每一行數據稱爲記錄
(7)數據庫存儲數據的步驟?
1)新建一張表(table)
2)添加多個字段(column,列,屬性)
3)添加多行記錄(row,record,每行存放多個字段對應的值)
iOS設備提供三種不一樣定位途徑,蜂窩式移動電話基站定位;WiFi定位,經過查詢一個WiFi路由器的地理位置信息,比較省電;GPS衛星定位,經過3~4顆衛星定位,最爲準確,可是耗電量大。iOS系統若是可以接收GPS信息,那麼設備優先採用GPS,其次是WiFi,最後是基站,開發人員不能選擇哪一種定位方式。
定位服務使用CoreLocation框架,主要使用CLLocationMananger、CLLocationManangerDelegate和CLLocation三個類,CLLocationMananger是定位服務管理類,獲取設備的位置信息,CLLocationManangerDelegate是代理協議,CLLocation封裝了位置信息。
這裏要注意,CLLocationManangerDelegate 的locationManager:didUpdateToLocation:fromLocation:方法獲得的座標是火星座標,這個緣由你懂得,因此須要轉換成真實的地理座標。我使用的是一個第三方的CSqlite類,有一個轉換座標的數據庫,你調用就能夠轉換爲正確座標了。
獲得經緯度後,要進行地理位置信息反編碼,使用CLGeocoder類實現,將地理座標轉換爲地理文字描述信息,這些文字描述信息被封裝在CLPlacemark類中。
固然給定地理信息的文字描述,也能夠進行地理信息編碼查詢,轉換爲地理座標,也是採用CLGeocoder類。
|
// 在範圍內返回1,不在返回0 -(int)mutableBoundConrtolAction:(NSMutableArray *)arrSome:(CLLocationCoordinate2D )myCoordinate4{ int n=arrSome.count; float vertx[n]; float verty[n]; for (int i=0; i<arrSome.count; i++) { //MyPoint類存儲的是經度和緯度 vertx[i]=((MyPoint *)(arrSome[i])).x; verty[i]=((MyPoint *)(arrSome[i])).y; } if (arrSome.count==0) {
return 1; } BOOL i=pnpoly(arrSome.count, vertx, verty, myCoordinate4.latitude, myCoordinate4.longitude);
if (i) { return 1; }else{ return 0; }
return 1; } //多邊形由邊界的座標點所構成的數組組成,參數格式 該數組的count, 多邊形邊界點x座標 的組成的數組,多邊形邊界點y座標 的組成的數組,須要判斷的點的x座標,須要判斷的點的y座標 BOOL pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) { int i, j; BOOL c=NO; for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ( (verty[i]>testy) != (verty[j]>testy) ) && (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ) c = !c; } return c; } |
地圖我目前用過系統、百度以及高德,開發人員使用都是差很少的,下面的代碼涉及的類都是高德地圖api提供的類。
我以前作項目,使用高德地圖,作到後期,項目會出現閃退,後來查出是地圖區域內存的問題,而後從新佈局了地圖區域,使得每個地圖區域可以及時銷燬,雖然閃退週期明顯延長,可是仍是存在,這裏不知道是何緣由,說來慚愧。
1 2 3 4 5 6 7 8 9 |
-(void)SetMapRegion:(CLLocationCoordinate2D)myCoordinate { MACoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } }; theRegion.center=myCoordinate; [self.m_map setScrollEnabled:YES]; theRegion.span.longitudeDelta = 0.01f; theRegion.span.latitudeDelta = 0.01f; [self.m_map setRegion:theRegion animated:YES]; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-(void)panMap:(NSString *)direction{ CLLocationCoordinate2D changeCoordinate=self.m_map.centerCoordinate; CGPoint changePoint=[self.m_map convertCoordinate:changeCoordinate toPointToView:self.m_map];
if ([direction isEqualToString:@"up"]) { changePoint.y=changePoint.y+50;
}else if ([direction isEqualToString:@"down"]) { changePoint.y=changePoint.y-50; }else if ([direction isEqualToString:@"left"]) { changePoint.x=changePoint.x-50; }else if ([direction isEqualToString:@"right"]) { changePoint.x=changePoint.x+50; } changeCoordinate=[self.m_map convertPoint:changePoint toCoordinateFromView:self.m_map]; [self.m_map setCenterCoordinate:changeCoordinate animated:YES]; } |
1 2 3 4 5 6 7 8 9 10 |
-(void)isAtCurrentRegion:(CLLocationCoordinate2D)coordiante{
CGPoint point=[self.m_map convertCoordinate:coordiante toPointToView:self.view]; if ((point.x<0)||(point.y<0)||(point.x>WScreen)||(point.y>HScreen)) { // 若是不在 設置該點爲地圖中心點 [self SetMapRegion:coordiante]; }
} |
系統地圖使用MapKit框架,核心是MKMapView類,顯示地圖只要添加MKMapView實例就能夠了。若是要實如今地圖上添加標註點,第以是觸發添加動做,第二實現MKMapViewDelegate的mapView:viewForAnnotation:完成添加標註。
高德地圖實現的原理也是同樣的,高德地圖使用的是MAMapKit框架。對於annotation,通常會自定義一個繼承NSobject而且實現了maannotation協議的類,而後使用mapview的addAnnotation:方法就能夠。MKReverseGeocoder類能夠實現coordinate的反編碼,這裏須要實現它的代理,把獲得的地理文字描述信息賦給annotation。這裏須要實現代理的mapView:viewForAnnotation:方法,一個標註其實就是一個MAAnnotationView,標註有點相似tableviewcell,這裏也有重用機制。實現代理的mapView:annotationView:calloutAccessoryControlTapped:方法能夠響應leftCalloutAccessoryView或者rightCalloutAccessoryView的點擊事件,不過這個accessory view必須繼承自UIControl。
MAPolyline類定義一個由多個點相連的多段線,點與點之間尾部想連但第一點與最後一個點不相連, 一般MAPolyline是MAPolylineView的model,它提供了兩個方法polylineWithPoints:count:、polylineWithCoordinates:count:用來添加線條,而後再經過map view的addOverlay:方法把Polyline實例添加進去,最後實現mapviewdelegate的mapView:viewForOverlay:方法就能夠了。注意若是一開始添加的不是coordinate,而是point,能夠經過map view的convertPoint:toCoordinateFromView:方法進行轉換。
MAPolygon類定義的就是一個不規則的由多個點組成的閉合多邊形,點與點之間按順序尾部相連, 第一個點與最後一個點相連, 一般MAPolygon是MAPolygonView的model,首先須要添加座標點的數組,能夠使用polygonWithCoordinates:count:方法或者polygonWithPoints:count:方法,而後把這個polygon經過addOverlay:方法添加到map view上就能夠了。而後能夠在mapviewdelegate裏面的mapView:viewForOverlay:方法裏面給MAPolygonView的屬性賦值,這樣一個完整的多邊形就出來了。
無論是高德地圖仍是百度地圖等第三方,都會有一個mapsearchkit,這是一個用於查詢的框架,有興趣的朋友能夠多加研究。
iOS中的MapKit集成了google地圖api的不少功能加上iOS的定位的功能,咱們就能夠實現將你運行的軌跡繪製到地圖上面。這個功能很是有用,好比快遞追蹤、汽車的gprs追蹤、人員追蹤等等。這篇文章咱們將使用Map Kit和iOS的定位功能,將你的運行軌跡繪製在地圖上面。
實現
在以前的一篇文章描述瞭如何在地圖上顯示本身的位置,若是咱們將這些位置先保存起來,而後串聯起來繪製到地圖上面,那就是咱們的運行軌跡了。
首先咱們看下如何在地圖上繪製曲線。在Map Kit中提供了一個叫MKPolyline的類,咱們能夠利用它來繪製曲線,先看個簡單的例子。
使用下面代碼從一個文件中讀取出經緯度,而後建立一個路徑:MKPolyline實例。
[plain] view plaincopy
[plain] view plaincopy
將這個路徑添加到地圖上
[plain] view plaincopy
[plain] view plaincopy
顯示在地圖上:
[plain] view plaincopy
[plain] view plaincopy
效果:
而後咱們在從文件中讀取位置的方法改爲從用gprs等方法獲取當前位置。
第一步:建立一個CLLocationManager實例
第二步:設置CLLocationManager實例委託和精度
第三步:設置距離篩選器distanceFilter
第四步:啓動請求
代碼以下:
[plain] view plaincopy
[plain] view plaincopy
上面的代碼我定義了一個數組,用於保存運行軌跡的經緯度。
每次通知更新當前位置的時候,咱們將當前位置的經緯度放到這個數組中,並從新繪製路徑,代碼以下:
[plain] view plaincopy
[plain] view plaincopy
咱們將前面從文件獲取經緯度建立軌跡的代碼修改爲從這個數組中取值就好了:
[plain] view plaincopy
[plain] view plaincopy
這樣咱們就將咱們運行得軌跡繪製google地圖上面了。
擴展:
若是你想使用其餘的地圖,好比百度地圖,其實也很方便。能夠將百度地圖放置到UIWebView中間,經過用js去繪製軌跡。