精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

深受開(kāi)發(fā)者喜愛(ài)的10大Core Data工具和開(kāi)源庫(kù)

移動(dòng)開(kāi)發(fā)
在iOS和OSX應(yīng)用程序中存儲(chǔ)和查詢(xún)數(shù)據(jù),Core Data是一個(gè)很好的選擇。它不僅可以減少內(nèi)存使用、提高性能,而且它可以使你避免寫(xiě)很多不必要的樣板文件代碼。

QQ截圖20150831112227.png

在iOS和OSX應(yīng)用程序中存儲(chǔ)和查詢(xún)數(shù)據(jù),Core Data是一個(gè)很好的選擇。它不僅可以減少內(nèi)存使用、提高性能,而且它可以使你避免寫(xiě)很多不必要的樣板文件代碼。

此外,Core Data API非常靈活,可以用在各種應(yīng)用程序中,所有應(yīng)用程序有不同的數(shù)據(jù)存數(shù)需求。

然而,這種靈活性意味著有時(shí)Core Data用起來(lái)可能稍微有點(diǎn)困難。即便你是一個(gè)Core Data專(zhuān)家,仍然會(huì)需要處理一些平常的任務(wù),也會(huì)有很多犯錯(cuò)的可能性。

幸運(yùn)的是,有很多很好的工具可以幫你解決問(wèn)題,讓Core Data更易于使用。為此我們選出了10個(gè)你應(yīng)該知道和喜歡的工具和開(kāi)源庫(kù)。

注意:即便有這些優(yōu)秀的工具和庫(kù),你仍需要很好地理解Core Data。如果你需要獲得Core Data的更多經(jīng)驗(yàn),下載查閱我們的新手教程。

還要注意的是這篇文章以O(shè)bjective-C為主,因?yàn)榇蟛糠諧ore Data庫(kù)都是用Objective-C寫(xiě)的。如果你想學(xué)習(xí)怎樣用Swift來(lái)使用Core Data,可下載查閱我們已經(jīng)出版的書(shū)Core Data by Tutorials,這本書(shū)已經(jīng)完全為iOS 8和Swift更新了!

#10. RestKit

RestKit是為了和RESTful web服務(wù)交互的一個(gè)Objective-C框架。它提供了一個(gè)Core Data實(shí)體映射引擎,把序列化的響應(yīng)對(duì)象直接映射給托管的對(duì)象。

下面的代碼例子展示了如何設(shè)置RestKit來(lái)訪問(wèn) OpenWeatherMap API,同時(shí)把/weather端點(diǎn)的JSON響應(yīng)映射成為一個(gè)WFWeather 托管對(duì)象。

  1. - (void)loadForecastData { 
  2.   RKManagedObjectStore *store = self.managedObjectStore; 
  3.    
  4.   // 1 
  5.   RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"WFWeather" 
  6.                                                  inManagedObjectStore:store]; 
  7.   [mapping addAttributeMappingsFromArray:@[@"temp", @"pressure", @"humidity"]]; 
  8.    
  9.   // 2 
  10.   NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); 
  11.   RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor 
  12.                                               responseDescriptorWithMapping:mapping 
  13.                                               method:RKRequestMethodGET 
  14.                                               pathPattern:@"/data/2.5/weather" 
  15.                                               keyPath:@"main" 
  16.                                               statusCodes:statusCodeSet]; 
  17.    
  18.   // 3 
  19.   NSURL *url = [NSURL URLWithString: 
  20.                 [NSString stringWithFormat:@"http://api.openweathermap.org/data/2.5/weather?q=Orlando"]]; 
  21.   NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
  22.   RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc] 
  23.                                                 initWithRequest:request 
  24.                                                 responseDescriptors:@[responseDescriptor]]; 
  25.   operation.managedObjectCache = store.managedObjectCache; 
  26.   operation.managedObjectContext = store.mainQueueManagedObjectContext; 
  27.    
  28.   // 4 
  29.   [operation setCompletionBlockWithSuccess: 
  30.    ^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){ 
  31.      NSLog(@"%@",mappingResult.array); 
  32.      [self.tableView reloadData]; 
  33.    } failure:^(RKObjectRequestOperation *operation, NSError *error) { 
  34.      NSLog(@"ERROR: %@", [error localizedDescription]); 
  35.    }]; 
  36.    
  37.   [operation start]; 

代碼分解:

1、首先,創(chuàng)建一個(gè)RKEntityMapping對(duì)象來(lái)告訴RestKit如何把API的響應(yīng)映射給WFWeather屬性。

2、這里,RKResponseDescriptor 把上面從/data/2.5/weather到 RKEntityMapping 實(shí)例的響應(yīng)聯(lián)系在了一起。

3、RKManagedObjectRequestOperation 定義了要執(zhí)行的操作。這個(gè)例子中,你從OpenWeatherMap API請(qǐng)求了Orlando(奧蘭多)的天氣,然后把響應(yīng)指向上面提到的RKResponseDescriptor 實(shí)例。

4、***,用需要的成功和失敗的block(塊)執(zhí)行操作。當(dāng)RestKit看到和定義的RKResponseDescriptor 想匹配的應(yīng)答返回的時(shí)候,它將直接把數(shù)據(jù)映射到WFWeather 實(shí)例上。

以上代碼不需要手動(dòng)JSON解析、檢查[NSNull null]、手動(dòng)創(chuàng)建Core Data實(shí)體,或者連接一個(gè)API時(shí)任何其他必須做的事情。RestKit通過(guò)一個(gè)簡(jiǎn)單的映射字典把API響應(yīng)轉(zhuǎn)換成Core Data模型對(duì)象。沒(méi)有比這個(gè)更容易的了。

要學(xué)習(xí)如何安裝和使用RestKit,請(qǐng)下載查閱我們的 RestKit教程說(shuō)明

#9. MMRecord

MMRecord是一個(gè)基于block(塊)的集成庫(kù),它使用Core Data模型配置,自動(dòng)創(chuàng)建并填充來(lái)自API響應(yīng)的完整地對(duì)象圖。當(dāng)它在后臺(tái)為你創(chuàng)建、獲取、填充N(xiāo)SManagedObjects 實(shí)例時(shí),使從web服務(wù)請(qǐng)求來(lái)的生成的本地對(duì)象盡可能簡(jiǎn)單。

它使得從web服務(wù)請(qǐng)求生成本地對(duì)象,像它在后臺(tái)創(chuàng)建、獲取、填充N(xiāo)SManagedObjects 實(shí)例那樣簡(jiǎn)單。

下面的代碼塊,展示了怎樣使用MMRecord來(lái)進(jìn)行相同的Orlando天氣調(diào)用,以及你在上面的RestKit例子中做的數(shù)據(jù)映射:

  1. NSManagedObjectContext *context = [[MMDataManager sharedDataManager] managedObjectContext]; 
  2.    
  3. [WFWeather  
  4.   startPagedRequestWithURN:@"data/2.5/weather?q=Orlando" 
  5.                       data:nil 
  6.                    context:context 
  7.                     domain:self 
  8.   resultBlock:^(NSArray *weather, ADNPageManager *pageManager, BOOL *requestNextPage) { 
  9.     NSLog(@"Weather: %@", weather); 
  10.   } 
  11.   failureBlock:^(NSError *error) { 
  12.     NSLog(@"%@", [error localizedDescription]); 
  13. }]; 

無(wú)需編寫(xiě)任何復(fù)雜的網(wǎng)絡(luò)代碼,或者手動(dòng)解析JSON響應(yīng),你已經(jīng)調(diào)用一個(gè)API,并且已用幾行代碼的響應(yīng)數(shù)據(jù)填充了Core Data托管對(duì)象。

MMRecord 如何知道你在API響應(yīng)中定位你的對(duì)象?你的托管對(duì)象必須是MMRecord 的子類(lèi),然后像下面所示那樣重載keyPathForResponseObject :

  1. @interface WFWeather : MMRecord 
  2. @property (nonatomic) float temp; 
  3. @property (nonatomic) float pressure; 
  4. @property (nonatomic) float humidity; 
  5. @end 
  6.    
  7. @implementation WFWeather 
  8. @dynamic temp; 
  9. @dynamic pressure; 
  10. @dynamic humidity; 
  11.    
  12. + (NSString *)keyPathForResponseObject { 
  13.     return @"main"
  14.    
  15. @end 

keyPathForResponseObject 返回了一個(gè)關(guān)鍵路徑,指定了來(lái)自API的響應(yīng)對(duì)象的根相關(guān)的對(duì)象的位置。這個(gè)例子中,關(guān)鍵路徑是data/2.5/weather 調(diào)用的main。

神奇之處不止這一點(diǎn)-MMRecord要求你創(chuàng)建一個(gè)服務(wù)器類(lèi),這個(gè)類(lèi)知道如何請(qǐng)求你集成的API。謝天謝地,MMRecord附帶一個(gè)基于AFNetworking 的服務(wù)器類(lèi)的例子。

關(guān)于配置和使用MMRecord的信息,MMRecord Github repository 的說(shuō)明文件是***的開(kāi)始。

#8. Magical Record

靈感來(lái)源于Ruby on Rails' ActiveRecord 系統(tǒng),提供了一系列支持一行實(shí)體的獲取、嵌入和刪除操作的類(lèi)和類(lèi)別。

下圖是運(yùn)行的MagicalRecord視圖:

  1. // Fetching NSArray *people = [Person MR_findAll]; 
  2. // Creating Person *myPerson = [Person MR_createEntity]; 
  3. // Deleting [myPerson MR_deleteEntity]; 

MagicalRecord讓設(shè)置Core Data堆棧變得非常容易。而不是使用很多行的樣板代碼,你可以像下邊這樣只用AppDelegate文件里的一個(gè)方法調(diào)用來(lái)設(shè)置一個(gè)完整的Core Data堆棧。

  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
  2.   // 1 
  3.   [MagicalRecord setupCoreDataStackWithStoreNamed:@"ExampleDatabase.sqlite"]; 
  4.    
  5.   return YES; 
 

在application:didFinishLaunchingWithOptions: 里,用你SQLite文件的名調(diào)用setupCoreDataStackWithStoreNamed。 這就建立了NSPersistentStoreCoordinator、NSManagedObjectModel 和NSManagedObjectContext 的實(shí)例,這樣你就可以準(zhǔn)備使用Core Data工作了。

進(jìn)一步地了解如何安裝和使用MagicalRecord,請(qǐng)參看我們的MagicalRecord 教程

#7. GDCoreDataConcurrencyDebugging

并發(fā)問(wèn)題是在Core Data中調(diào)試最難的事情。performBlock API可以幫忙,但仍然很容易犯錯(cuò)。

你可以將開(kāi)源項(xiàng)目GDCoreDataConcurrencyDebugging添加到自己的項(xiàng)目中,當(dāng)在錯(cuò)誤線程或者調(diào)度隊(duì)列上訪問(wèn)NSManagedObjects時(shí),它通過(guò)控制臺(tái)消息提醒你。

以下是在錯(cuò)誤環(huán)境中訪問(wèn)NSManagedObject 實(shí)例的例子:

  1. __block NSManagedObject *objectInContext1 = nil; 
  2.    
  3. [context1 performBlockAndWait:^{ 
  4.    
  5.   objectInContext1 = [[NSManagedObject alloc] initWithEntity:entity  
  6.                               insertIntoManagedObjectContext:context1]; 
  7.   objectInContext1.name = @"test"
  8.    
  9.   NSError *saveError; 
  10.   if ([context1 save:&saveError] == NO) { 
  11.    
  12.     NSLog(@"Error: %@", [saveError localizedDescription]); 
  13.   } 
  14. }]; 
  15.    
  16.    
  17. // Invalid access 
  18. [context2 performBlockAndWait:^{ 
  19.  NSString *name = objectInContext1.name; 
  20. }]; 

在上面的代碼中,你正嘗試從一個(gè)對(duì)象中context2 讀取name, 這個(gè)對(duì)象最初在context1 被創(chuàng)建。

如果你使用GDCoreDataConcurrencyDebugging 運(yùn)行上面的例子,你會(huì)看到下面的控制臺(tái)消息,通知你有問(wèn)題發(fā)生:

2014-06-17 13:20:24.530 SampleApp[24222:60b] CoreData concurrency failure

注意:在你的應(yīng)用程序上傳到App Store上去時(shí),你得移除掉GDCoreDataConcurrencyDebugging ,它增加了少量的開(kāi)銷(xiāo),那些開(kāi)銷(xiāo)無(wú)需存在于在發(fā)布的應(yīng)用中。

在iOS 8和OS X Yosemite中,Core Data現(xiàn)在有檢測(cè)并發(fā)問(wèn)題的能力。想要啟用這個(gè)新功能,你可以在啟動(dòng)時(shí)通過(guò)Xcode?s Scheme Editor 把-com.apple.CoreData.ConcurrencyDebug 1 傳給你的應(yīng)用程序。

然而,直到你逐步淘汰對(duì)OS更早版本的支持,GDCoreDataConcurrencyDebugging 都會(huì)在開(kāi)發(fā)過(guò)程中一直通知你并發(fā)問(wèn)題。

GDCoreDataConcurrencyDebugging README on Github 是安裝和使用這個(gè)工具***的資源信息。

#6. CoreData-hs

CoreData-hs 生成類(lèi)別方法來(lái)執(zhí)行Core Data模型里所有實(shí)體和屬性的常見(jiàn)獲取請(qǐng)求。創(chuàng)建這些方法不難,但它耗時(shí)--編碼時(shí)節(jié)省每一點(diǎn)時(shí)間都是有價(jià)值的!

比如,你的天氣應(yīng)用程序里有一個(gè)查看天氣預(yù)報(bào)和使用帶有timeStamp,temp和 summary 屬性的WFForecast 實(shí)體來(lái)模仿每天的預(yù)報(bào)的視圖,CoreData-hs 將為你創(chuàng)建以下的類(lèi)別:

  1. #import #import @interface WFForecast (Fetcher) 
  2.    
  3. + (NSArray *)summaryIsEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  4.    
  5. + (NSArray *)summaryIsLessThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  6.    
  7. + (NSArray *)summaryIsGreaterThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  8.    
  9. + (NSArray *)summaryIsGreaterThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  10.    
  11. + (NSArray *)summaryIsLessThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  12.    
  13. + (NSArray *)summaryIsNotEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  14.    
  15. + (NSArray *)summaryIsBetwixt:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  16.    
  17. + (NSArray *)tempIsEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  18.    
  19. + (NSArray *)tempIsLessThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  20.    
  21. + (NSArray *)tempIsGreaterThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  22.    
  23. + (NSArray *)tempIsGreaterThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  24.    
  25. + (NSArray *)tempIsLessThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  26.    
  27. + (NSArray *)tempIsNotEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  28.    
  29. + (NSArray *)tempIsBetwixt:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  30.    
  31. + (NSArray *)timeStampIsEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  32.    
  33. + (NSArray *)timeStampIsLessThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  34.    
  35. + (NSArray *)timeStampIsGreaterThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  36.    
  37. + (NSArray *)timeStampIsGreaterThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  38.    
  39. + (NSArray *)timeStampIsLessThanOrEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  40.    
  41. + (NSArray *)timeStampIsNotEqualTo:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  42.    
  43. + (NSArray *)timeStampIsBetwixt:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  44.    
  45. + (NSArray *)summaryIsLike:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  46.    
  47. + (NSArray *)summaryContains:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  48.    
  49. + (NSArray *)summaryMatches:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  50.    
  51. + (NSArray *)summaryBeginsWith:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  52.    
  53. + (NSArray *)summaryEndsWith:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  54.    
  55. + (NSArray *)tempIsLike:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  56.    
  57. + (NSArray *)tempContains:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  58.    
  59. + (NSArray *)tempMatches:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  60.    
  61. + (NSArray *)tempBeginsWith:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  62.    
  63. + (NSArray *)tempEndsWith:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock; 
  64.    
  65. @end 

#p#

正如你看到的,生成了很多方法!以下是tempIsGreaterThan:inContext:sortDescriptors: error: 生成的實(shí)現(xiàn)方法:

  1. + (NSArray *)tempIsGreaterThan:(id)object inContext:(NSManagedObjectContext *)context sortDescriptors:(NSArray *)sort error:(void(^)(NSError *error))errorBlock { 
  2.   NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"WFForecast"]; 
  3.   [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"temp > %@", object]]; 
  4.   [fetchRequest setSortDescriptors:sort]; 
  5.   NSError *err = nil; 
  6.   NSArray *results = [context executeFetchRequest:fetchRequest error:&err]; 
  7.   if(!results && errorBlock) { 
  8.     errorBlock(err); 
  9.     return nil; 
  10.   } 
  11.   return results; 

方法一旦生成,你就可以用它們通過(guò)特定條件獲取請(qǐng)求。比如,需要獲取所有溫度超過(guò)70°的WFForecast對(duì)象,你可以調(diào)用tempIsGreaterThan:inContext:sortDescriptors:error:,然后簡(jiǎn)單地傳遞目標(biāo)溫度,如下所示:

  1. NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"temp" ascending:YES]; 
  2. NSArray *results = [WFForecast tempIsGreaterThan:@(70) 
  3.                                        inContext:self.managedObjectContext 
  4.                                  sortDescriptors:@[sortDescriptor] 
  5.                                            error:^(NSError *error) { 
  6.    
  7.   NSLog(@"Error: %@", [error localizedDescription]); 
  8. }]; 

你將返回一個(gè)匹配對(duì)象的數(shù)據(jù)。

CoreData-hs 是一個(gè)輕量級(jí)的工具,如果你傾向于手動(dòng)生成大量這種類(lèi)型的請(qǐng)求,它可以節(jié)省你的時(shí)間。關(guān)于安裝和使用說(shuō)明,請(qǐng)查閱README on Github

#5. Core Data Editor

你可以在Core Data Editor的GUI中查看和編輯APP基于Core Data的數(shù)據(jù)模型,它支持XML、二進(jìn)制和SQLite持久性存儲(chǔ)類(lèi)型。除了可以編輯基本屬性,你還可以編輯和形象化數(shù)據(jù)關(guān)系。你也可以在使用Core Data Editor的同時(shí)使用Mogenerator工具 (第#2項(xiàng)中討論)來(lái)創(chuàng)建模型代碼。

Core Data Editor熟悉蘋(píng)果的模式,展示不帶Z前綴的數(shù)據(jù),如果你曾看到Core Data生成的SQL文件,這個(gè)前綴你可能會(huì)熟悉。你可以在一個(gè)不錯(cuò)的表格格式里瀏覽應(yīng)用程序數(shù)據(jù)庫(kù)里的內(nèi)容。它也支持預(yù)覽二進(jìn)制數(shù)據(jù),比如圖片,以及用一個(gè)標(biāo)準(zhǔn)日期選擇器在線編輯數(shù)據(jù)。

166.png

如果你想創(chuàng)建一個(gè)種子文件或者只想導(dǎo)入數(shù)據(jù),Core Data Editor可以生成一個(gè)CSV文件,把它轉(zhuǎn)換成Core Data里持久化對(duì)象,如下所示:

177.png

安裝Core Data Editor,從Thermal Core website 下載免費(fèi)試用版。解壓下載的ZIP歸檔文件,把Core Data Editor.app 文件移動(dòng)到你的Applications 目錄里。這個(gè)應(yīng)用的作者最近也把它開(kāi)源了,如果你想了解它是如何工作的,以及提高自己,你可以去學(xué)習(xí)下。

***次啟動(dòng)應(yīng)用程序,它會(huì)引導(dǎo)你完成一個(gè)簡(jiǎn)短的設(shè)置過(guò)程。這個(gè)過(guò)程是可選的,但如果你至少指定iPhone模擬器目錄和Xcode歸檔數(shù)據(jù)的目錄,它將會(huì)加快速度。

注意:因?yàn)槟愕迷贕UI中選擇導(dǎo)出的數(shù)據(jù)和模擬器目錄,所以你可能在使用OS X Lion默認(rèn)設(shè)置時(shí)會(huì)遇到問(wèn)題,隱藏你的庫(kù)文件夾。

在Mavericks OS X里,你可以通過(guò)在Finder的主目錄里,選擇View / Show View Options ,檢查Show Library Folder來(lái)糾正這個(gè)問(wèn)題。在Lion和Mountain Lion OS X中,同樣的事情可以通過(guò)在終端輸入chflags nohidden ~/Library/ 來(lái)完成。

更多有關(guān)Core Data的詳情可以在這個(gè)網(wǎng)站Thermal Core's website上找到。

#4. SQLite3

有時(shí)當(dāng)調(diào)試一個(gè)棘手的數(shù)據(jù)問(wèn)題時(shí),在底層的Core Data SQLite數(shù)據(jù)庫(kù)中直接執(zhí)行SQL查詢(xún)是有幫助的。如果你沒(méi)有擴(kuò)展的數(shù)據(jù)庫(kù)經(jīng)驗(yàn),這個(gè)可能不適合你。

使用SQLite3,首先打開(kāi)Terminal終端,并導(dǎo)航到你應(yīng)用程序的Documents 目錄。根據(jù)你的安裝情況,Documents目錄類(lèi)似于 ~/Library/Application Support/iPhone Simulator/7.1-64/Applications/{your app's ID}/Documents.

更改上面命名中7.1-64 來(lái)匹配你使用的模擬器的版本。{your app's ID} 由Xcode自動(dòng)生成,并唯一地標(biāo)識(shí)應(yīng)用的安裝。沒(méi)有簡(jiǎn)單的辦法找出哪個(gè)ID是你的。你可以在創(chuàng)建Core Data堆棧的時(shí)候添加日志記錄,也可以尋找最近被多次修改的目錄--這將是你當(dāng)前工作的應(yīng)用程序。

文檔目錄將包含一個(gè)擴(kuò)展sqlite的文件,這個(gè)就是你應(yīng)用程序的數(shù)據(jù)庫(kù)文件。對(duì)于使用蘋(píng)果Core Data模板的應(yīng)用程序而言,文件名稱(chēng)要匹配你的應(yīng)用的名字。用如下所示的SQLite3程序打開(kāi)這個(gè)文件(這里的例子應(yīng)用叫AddressBook,你的文件名字會(huì)有所不同):

1
$ sqlite3 AddressBook.sqlite

你將在控制臺(tái)看到以下提示:

  1. SQLite version 3.7.13 2012-07-17 17:46:21 
  2. Enter ".help" for instructions 
  3. Enter SQL statements terminated with a ";" 
  4. sqlite> 

現(xiàn)在準(zhǔn)備好對(duì)數(shù)據(jù)庫(kù)執(zhí)行標(biāo)準(zhǔn)的SQL查詢(xún)。

比如,為了看到Core Data 使用的模式,可執(zhí)行以下的命令:

  1. sqlite> select * from sqlite_master; 
 

SQLite用模式里的一個(gè)文本列表清單來(lái)響應(yīng)你的查詢(xún),如下所示:

  1. table|ZMDMPERSON|ZMDMPERSON|3|CREATE TABLE ZMDMPERSON ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZISNEW INTEGER, ZFIRSTNAME VARCHAR ) 
  2. table|Z_PRIMARYKEY|Z_PRIMARYKEY|4|CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER) table|Z_METADATA|Z_METADATA|5|CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB) 
  3. sqlite> 

所有在列表欄里的Z前綴是Core Data底層使用SQLite的一部分。出于分析的目的,可以忽略它們。

注意:你不能直接寫(xiě)入SQLite Core Data數(shù)據(jù)庫(kù)。蘋(píng)果可以隨時(shí)修改底層結(jié)構(gòu)。

如果你真的有需要在生產(chǎn)應(yīng)用程序中直接操作SQLite數(shù)據(jù),你應(yīng)該放棄Core Data,用原始的SQL訪問(wèn)。有幾種流行的框架可以幫助你管理你應(yīng)用中的SQL實(shí)現(xiàn),包括FMDB和 FCModel

如果只是分析數(shù)據(jù),到處訪問(wèn)SQLite數(shù)據(jù)庫(kù)文件是沒(méi)什么關(guān)系的--只要不修改它的內(nèi)容。直接使用SQL分析數(shù)據(jù)的一個(gè)例子是不同屬性進(jìn)行分組和計(jì)算,以理解屬性的差異。

舉個(gè)例子,如果你有一個(gè)地址薄的應(yīng)用例子,想知道在每個(gè)城市里有多少聯(lián)系人生活,你可以用SQLite3提示執(zhí)行以下命令:

  1. SELECT t0.ZCITY, COUNT( t0.ZCITY ) FROM ZMDMPERSON t0 GROUP BY t0.ZCITY 

SQLite會(huì)用地址薄數(shù)據(jù)庫(kù)里每個(gè)不同城市的數(shù)據(jù)來(lái)作出響應(yīng),如下面的例子所示:

  1. San Diego|23 
  2. Orlando|34 
  3. Houston|21 

退出SQLite3終端程序,簡(jiǎn)單地執(zhí)行以下的命令:

  1. sqlite> .exit 

想要了解更多SQLite3的信息,可打開(kāi)終端查看man 頁(yè),并執(zhí)行man sqlite3命令。

#3. MDMCoreData

MDMCoreData(免責(zé)聲明--這個(gè)庫(kù)是我的寫(xiě)的!)是一個(gè)開(kāi)源類(lèi)的集合,讓使用Core Data變得更簡(jiǎn)單。它并不試圖隱藏或抽象Core Data,而是執(zhí)行***實(shí)踐,以及減少所要的模板代碼。這比Xcode Core Data模板是一個(gè)更好的選擇。

MDMCoreData由以下四個(gè)類(lèi)組成:

  • MDMPersistenceController,一個(gè)便利的控制器,支持創(chuàng)建多個(gè)child-managed object context 來(lái)建立一個(gè)高效的Core Data堆棧。它有一個(gè)內(nèi)置的私有 managed object context,異步保存到SQLite倉(cāng)庫(kù)。

  • MDMFetchedResultsTableDataSource,獲取ResultsController delegate和列表數(shù)據(jù)源。

  • MDMFetchedResultsCollectionDataSource,獲取ResultsController delegate和集合數(shù)據(jù)源。

  • NSManagedObject+MDMCoreDataAdditions,一個(gè)托管對(duì)象類(lèi)別,它提供輔助方法來(lái)消除模板代碼,比如實(shí)體名。

MDMCoreData一個(gè)***的特點(diǎn)是,它伴隨著一個(gè)支持表數(shù)據(jù)源的Core Data--所以你不必?fù)?dān)心要自己去實(shí)現(xiàn)。

#p#

你可以只設(shè)置MDMFetchedResultsTableDataSource實(shí)例的表數(shù)據(jù)源,而不是實(shí)現(xiàn)UITableViewDataSource 和NSFetchedResultsControllerDelegate 協(xié)議需要的所有方法。

當(dāng)實(shí)例化MDMFetchedResultsTableDataSource 對(duì)象,你只要簡(jiǎn)單地在表視圖里簡(jiǎn)單傳送,并獲取一個(gè)results controller:

  1. - (void)viewDidLoad { 
  2.   [super viewDidLoad]; 
  3.    
  4.   self.tableDataSource = [[MDMFetchedResultsTableDataSource alloc] initWithTableView:self.tableView 
  5.                                                         fetchedResultsController:[self fetchedResultsController]]; 
  6.   self.tableDataSource.delegate = self; 
  7.   self.tableDataSource.reuseIdentifier = @"WeatherForecastCell"
  8.   self.tableView.dataSource = self.tableDataSource; 

MDMFetchedResultsTableDataSource 有一個(gè)代理,有兩個(gè)必須實(shí)現(xiàn)的方法。一個(gè)方法為你的表格配置cell:

  1. - (void)dataSource:(MDMFetchedResultsTableDataSource *)dataSource      configureCell:(id)cell 
  2. withObject:(id)object { 
  3. OWMForecast *forecast = object; 
  4. UITableViewCell *tableCell = (UITableViewCell *)cell;   tableCell.textLabel.text = forecast.summary;   tableCell.detailTextLabel.text = forecast.date; 

第二個(gè)方法處理刪除操作:

  1. - (void)dataSource:(MDMFetchedResultsTableDataSource *)dataSource       deleteObject:(id)object 
  2. atIndexPath:(NSIndexPath *)indexPath { 
  3. [self.persistenceController.managedObjectContext deleteObject:object]; 

實(shí)現(xiàn)兩個(gè)所需的MDMFetchedResultsTableDataSource 方法,遠(yuǎn)比實(shí)現(xiàn)表數(shù)據(jù)源所有所需方法和獲取results controller protocols要簡(jiǎn)單的多。

你可以在MDMCoreData Github repository 找到更多關(guān)于MDMCoreData的信息。

#2. Mogenerator

因?yàn)镃ore Data完全支持鍵/值編碼(KVC)和鍵/值觀察(KVO),就沒(méi)必要實(shí)現(xiàn)自定義的NSManagedObject 類(lèi)。當(dāng)對(duì)你讀寫(xiě)實(shí)體時(shí),可以使用setValue:forKey: 和setValue:forKey: 。但這往往變得復(fù)雜和難于調(diào)試,因?yàn)樽址诰幾g的時(shí)候沒(méi)法檢查正確性。

比如,你有個(gè)person 的Core Data實(shí)體,你可以像這樣讀寫(xiě)屬性:

  1. NSString *personName = [person valueForKey:@"firstName"]; 
  2. [person setValue:@"Ned" forKey:@"firstName"]; 

上面的person 對(duì)象是一個(gè)屬性名為firstName 的NSManagedObject 實(shí)例。想要讀取firstName,你得用firstName 作為valueForKey:關(guān)鍵字。類(lèi)似地,你可以使用setValue:forKey: 設(shè)置一個(gè)person 對(duì)象的first name。

更好的方法就是使用標(biāo)準(zhǔn)的訪問(wèn)方法或者點(diǎn)語(yǔ)法。然而,要這么做的話你必須為你的實(shí)體實(shí)現(xiàn)NSManagedObject一個(gè)自定義子類(lèi)。你可以添加邏輯模型,比如獲取請(qǐng)求和驗(yàn)證。

你可能使用Xcode的Create NSManagedObjectSubclass功能快速創(chuàng)建單個(gè)實(shí)體的子類(lèi)。雖然是個(gè)捷徑,但如果你的數(shù)據(jù)模型比較大,它會(huì)增加額外的開(kāi)銷(xiāo),會(huì)在更改模型時(shí)帶來(lái)許多問(wèn)題。

重新創(chuàng)建子類(lèi)意味著清除你所有的自定義模型邏輯--這就意味著你應(yīng)該在自定義模型以外創(chuàng)建邏輯。它適合于創(chuàng)建帶有托管對(duì)象屬性和自定義模型邏輯類(lèi)別的自定義子類(lèi)的常規(guī)模式。

命令行工具M(jìn)ogenerator 會(huì)自動(dòng)化這些精確的任務(wù)。每個(gè)Core Data實(shí)體會(huì)生成兩個(gè)類(lèi)。***個(gè)類(lèi)是為機(jī)器消耗生成的,當(dāng)模型改變的時(shí)候不斷地被覆蓋。第二個(gè)類(lèi)是為你所有的自定義邏輯生成的,從來(lái)不被覆蓋。

Mogenerator 有一系列其他好處,包括以下幾點(diǎn):

  • 讀/寫(xiě)數(shù)值型屬性時(shí)無(wú)需使用NSNumber 對(duì)象。

  • 處理設(shè)置的輔助方法

  • 創(chuàng)建新實(shí)體的輔助方法

  • 一個(gè)實(shí)體識(shí)別的方法

Mogenerator可以從Mogenerator website 上可用的DMG文件來(lái)安裝,或者通過(guò)Homebrew安裝Mogenerator,打開(kāi)終端,執(zhí)行下面的命令:

  1. brew install mogenerator 

一旦安裝,用cd 命令來(lái)改變你應(yīng)用程序的目錄,然后從終端運(yùn)行Mogenerator,像這樣:

  1. $ mogenerator -m MySampleApp/ExampleModel.xcdatamodeld -O MySampleApp/Model --template-var arc=true 

在上面的命令中,你可以用-m 選項(xiàng)調(diào)用Mogenerator,緊隨其后的是模型的位置。你也可以用-O 選項(xiàng)指定生成類(lèi)的位置。當(dāng)使用ARC時(shí),你需要傳遞--template-var arc=true 選項(xiàng)。

你可以讓Xcode通過(guò)創(chuàng)建Run Script Build Phase來(lái)運(yùn)行Mogenerator。Build Phases是編譯期間Xcode必須執(zhí)行的任務(wù)的描述。

要添加一個(gè)Build Phase,首先選擇target,選擇Build Phases標(biāo)簽,然后選擇菜單里的Editor / Add Build Phase / Add Run Script Build Phase 。

在新Run Script下的Shell腳本文本區(qū)域里添加以下代碼,確保修改mogenerator 的參數(shù),來(lái)適配你的工程:

  1. if [ "${CONFIGURATION}" == "Debug" ]; then 
  2. echo "Running Mogenerator" 
  3. mogenerator -m MySampleApp/ExampleModel.xcdatamodeld -O MySampleApp/Model --template-var arc=true 
  4. echo "Finished Mogenerator" 
  5. else echo "Skipping Mogenerator" 
  6. fi 
以上的運(yùn)行腳本,會(huì)在你每次運(yùn)行一個(gè)調(diào)試編譯命令時(shí)讓Xcode運(yùn)行Mogenerator。如果模型沒(méi)什么改動(dòng)的話,Mogenerator將什么都不做,然后退出。

為了快速生成子類(lèi),現(xiàn)在你已經(jīng)把Mogenerator合并到你的工作流中,你應(yīng)該好好利用它的其它特性。

比如,不用每次打開(kāi)原始值,你只要給它們添加Value后綴, 如以下的代碼片段所示:

  1. // Without Mogenerator 
  2. if ([person.isFriend boolValue]) { 
  3.   // Do some work 
  4.    
  5. // With Mogenerator 
  6. if (person.isFriendValue) { 
  7.   // Do some work 

因?yàn)樵贑ore Data里bool 類(lèi)型是以NSNumber 類(lèi)型存儲(chǔ)的,在檢查值是否為真之前你必須調(diào)用person 對(duì)象的boolValue 。通過(guò)Mogenerator,就不需要額外的步驟了,因?yàn)槟阒灰?jiǎn)單地調(diào)用 isFriendValue即可。

如果Mogenerator對(duì)你的工具箱來(lái)說(shuō)看起來(lái)像個(gè)有用的補(bǔ)充,你可以在Github repository 找到更多有關(guān)Mogenerator的信息。

#1. Instruments

Instruments 是OS X 和 iOS里為研究幾乎所有性能和內(nèi)存問(wèn)題的重要工具--包括Core Data 問(wèn)題。清單里的其它工具提供了許多自動(dòng)化和便捷性,但I(xiàn)nstruments通常會(huì)是研究任何問(wèn)題或者性能調(diào)整的***站。

下圖是Time Profiler 和Core Data 模板,對(duì)Core Data配置來(lái)說(shuō)是最有用的。

121.png

默認(rèn)的Core Data 模板,添加了可選的Faults Instrument功能,通過(guò)提供以下功能來(lái)幫你調(diào)整和監(jiān)控應(yīng)用程序的性能:

  • Core Data Fetches Instrument,捕捉獲取次數(shù)和獲取操作的持續(xù)時(shí)間。

  • Core Data Cache Misses Instrument,捕捉導(dǎo)致緩存遺漏的故障事件。

  • Core Data Saves Instrument,捕捉托管對(duì)象上下文環(huán)境保存事件的信息。

  • Core Data Faults Instrument,捕捉NSManagedObjects 或相關(guān)關(guān)系的延遲初始化過(guò)程發(fā)生的故障事件的信息。

這個(gè)是Core Data應(yīng)用程序中典型的instruments profile。你可以看到獲取請(qǐng)求何時(shí)發(fā)生,以及請(qǐng)求所花時(shí)間,保存操作何時(shí)以及如何發(fā)生,以及何時(shí)出現(xiàn)故障燈。

122.png

要獲取更多有關(guān)Instruments的信息,請(qǐng)下載我們的教程:How to Use Instruments in Xcode

下一步

Core Data是個(gè)很強(qiáng)大的框架,但它會(huì)有很多開(kāi)發(fā)消耗,不過(guò)這篇文章中的工具和庫(kù)提供了一些方法來(lái)高效、有效地幫你解決消耗問(wèn)題。

責(zé)任編輯:倪明 來(lái)源: Raywenderlich
相關(guān)推薦

2015-10-19 11:06:42

CoreDate開(kāi)源庫(kù)

2013-09-12 15:02:54

iOS開(kāi)發(fā)者

2022-01-09 23:05:16

Java開(kāi)發(fā)工具

2014-12-10 10:01:31

PHP

2014-03-06 16:04:44

iOS開(kāi)源庫(kù)匯總

2020-08-05 14:30:08

開(kāi)源IDEJava開(kāi)發(fā)

2018-01-03 09:48:51

Python開(kāi)源庫(kù)工具

2018-01-04 22:17:05

Python開(kāi)源工具

2016-08-04 10:29:59

開(kāi)源工具VimLinux文本編輯器

2020-08-05 16:10:11

Java開(kāi)發(fā)代碼

2014-03-28 16:03:03

移動(dòng)開(kāi)發(fā)跨平臺(tái)工具

2017-01-20 08:57:00

開(kāi)發(fā)Web網(wǎng)關(guān)物聯(lián)網(wǎng)

2019-03-19 14:03:34

PHPPython編程語(yǔ)言

2010-07-08 15:48:34

開(kāi)源

2011-01-11 11:35:17

jQueryAndroidgoogle

2011-10-11 10:07:37

2011-11-28 09:35:21

云計(jì)算云電視

2011-05-30 14:07:42

2011-11-29 10:00:34

云計(jì)算

2011-07-15 10:02:01

JavaScript
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

日本大片在线播放| 懂色av蜜臀av粉嫩av分享吧最新章节| 中文字幕日韩亚洲| 亚洲大片免费看| 日本不卡二区高清三区| 国产情侣激情自拍| 亚洲一区欧美激情| 另类专区欧美制服同性| 日韩精品卡通动漫网站| 国产一区二区三区国产精品| 精品国产精品三级精品av网址| 日韩三级在线播放| 亚洲成人av综合| 日日摸夜夜添夜夜添精品视频 | 久久性爱视频网站| 国产精品无码久久久久| 精品久久久精品| av动漫免费观看| 国产爆初菊在线观看免费视频网站| 国产成人午夜精品5599| 国产有码一区二区| 一级黄色av片| 一本色道久久综合| 欧美成人午夜剧场免费观看| 69精品无码成人久久久久久| 久久99精品久久久久久欧洲站| 欧美性高清videossexo| 久久久999视频| 日本在线视频中文有码| 亚洲天堂福利av| 亚洲国产一区在线| 免费在线黄色电影| 99精品在线免费| 高清国产在线一区| 国产成人三级一区二区在线观看一| 免费欧美在线视频| 日本成熟性欧美| 日韩美女黄色片| 欧美视频久久| 九九久久精品一区| 黄色a级片在线观看| 久久亚洲精品中文字幕蜜潮电影| 亚洲视频axxx| 手机av免费看| 蜜桃a∨噜噜一区二区三区| 亚洲精品国精品久久99热一| 欧美熟妇精品一区二区蜜桃视频 | 久久99欧美| 蜜桃久久一区二区三区| 国产成人精品午夜视频免费| 亚洲在线www| 国产欧美一区二区三区视频在线观看| 老司机一区二区| 国产裸体写真av一区二区| 日本熟妇一区二区三区| 日韩av网站在线观看| 国产精品久久久久久久av大片| 伊人中文字幕在线观看| 视频一区二区中文字幕| 国产精品久久久久福利| 怡红院男人天堂| 精品伊人久久久久7777人| 成人午夜高潮视频| 亚洲精品视频91| 99精品欧美一区二区三区综合在线| 国产99在线播放| 视频午夜在线| 国产欧美日韩在线视频| 在线看无码的免费网站| 曰本三级在线| 午夜成人在线视频| 网站一区二区三区| www999久久| 欧美成人性战久久| 久久一区二区电影| 成人3d动漫在线观看| 久久精品国产v日韩v亚洲| 青青青在线免费观看| 亚洲巨乳在线| 国产精品视频免费在线| 精品女同一区二区三区| 99久久精品国产一区| 日韩免费毛片| 色yeye免费人成网站在线观看| 香蕉av福利精品导航| www.色就是色| 香蕉大人久久国产成人av| 亚洲精品www久久久| 免费看黄色三级| 午夜日韩电影| 日本视频久久久| 国产欧美一区二区三区视频在线观看| 成人av在线看| 亚洲欧美久久久久一区二区三区| 国产三线在线| 欧美日韩精品系列| 国产不卡一二三| 国产高清一区二区| 91国在线精品国内播放| 国产精品高潮呻吟av| 99久久免费国产| 精品少妇人妻av一区二区| 日韩脚交footjobhd| 69堂国产成人免费视频| 亚洲一区二区三区蜜桃| 午夜精品久久久久99热蜜桃导演| 国产成人精品一区二区| 免费看日韩av| 综合久久一区二区三区| 蜜臀久久99精品久久久酒店新书| 欧州一区二区三区| 国产一区二区三区四区福利| 国产五月天婷婷| 国产资源在线一区| 日韩欧美精品在线不卡| yellow字幕网在线| 日韩欧美不卡在线观看视频| 91视频免费看片| 久久福利一区| 国产一区二区中文字幕免费看| 看黄网站在线| 欧美日免费三级在线| 在线观看av中文字幕| 在线日韩欧美| 波多野结衣久草一区| 看黄网站在线| 欧美日韩精品二区第二页| 美女洗澡无遮挡| 先锋影音久久久| 精品卡一卡二| 国产精品13p| 欧美精品一区二区三区高清aⅴ| 亚洲一级生活片| 久久99蜜桃精品| 中文字幕日韩一区二区三区| 91精品国产经典在线观看| 国产精品成人免费电影| 亚洲精品一区二区精华| 91精品人妻一区二区三区蜜桃欧美| 国精品一区二区| 亚洲精品日韩激情在线电影| 欧美成人高清在线| 欧美猛男gaygay网站| 中文字幕第69页| 久久国内精品自在自线400部| 免费国产一区二区| 中文字幕这里只有精品| 亚洲精品自拍第一页| 欧美一区二区三区四| 91在线一区二区| 18禁免费无码无遮挡不卡网站| 欧美久久精品| 欧美在线性爱视频| 可以在线观看的黄色| 在线观看日产精品| 国产aaaaaaaaa| 国产在线精品国自产拍免费| 日韩视频一二三| 亚洲一级大片| 欧美性资源免费| 国产色a在线| 9191成人精品久久| 三上悠亚在线观看视频| 国产成人精品免费在线| 免费看国产一级片| 精品久久精品| 91久久久久久| av中文字幕在线观看第一页| 亚洲精品一区中文字幕乱码| 中文字幕人成人乱码亚洲电影| 最新国产成人在线观看| 91精品国产高清91久久久久久| 亚洲人人精品| 亚洲v日韩v欧美v综合| www.久久热| 国内精品一区二区三区| 第九色区av在线| 欧美一级久久久| 国产69精品久久久久久久久久| 久久久亚洲午夜电影| www.桃色.com| 一本色道久久精品| 亚洲一区二区三区四区中文| 99久久香蕉| 国产成人鲁鲁免费视频a| 黄色网页在线播放| 日韩精品免费在线视频| 亚洲中文一区二区三区| 亚洲成a人片在线不卡一二三区| 91视频在线网站| 国产麻豆9l精品三级站| av免费在线播放网站| 欧美日韩三级电影在线| 欧美日韩在线精品一区二区三区| 粉嫩av国产一区二区三区| 性欧美视频videos6一9| 午夜伦理在线| 日韩成人在线观看| 99热这里只有精品9| 色88888久久久久久影院按摩| 免费无遮挡无码永久在线观看视频 | 久久精品一区蜜桃臀影院| 亚洲热在线视频| 日韩精品免费专区| 国产a级片网站| 亚洲成人一区| 亚洲午夜精品久久久中文影院av | 日韩国产精品亚洲а∨天堂免| 中文字幕日日夜夜| 欧美性69xxxx肥| 国产在线一区视频| 亚洲免费av高清| 日本一卡二卡在线播放| 91视视频在线观看入口直接观看www | 久久亚洲中文字幕无码| 牛牛国产精品| 亚洲欧洲免费无码| 女优一区二区三区| 久久er99热精品一区二区三区| 欧美视频二区欧美影视| 成人国产精品日本在线| 国产精品亚洲成在人线| 国产精品成人av性教育| 免费电影日韩网站| 欧美一级片免费在线| 99热99re6国产在线播放| 久99久在线视频| 97caopron在线视频| 久久精品国产亚洲一区二区| 91精品国产91久久久久游泳池 | 亚洲免费精品| youjizz.com在线观看| 午夜精品网站| 国产一区二区三区在线免费| 欧美日本一区| 国产玉足脚交久久欧美| 韩国av一区| 黄色一级片在线看| 亚洲精品孕妇| 日韩在线视频在线观看| 国产亚洲精品v| 无码人妻h动漫| 日韩精品乱码av一区二区| 日本激情视频在线| 蜜臀国产一区二区三区在线播放| 污片在线免费看| 久久成人久久爱| 亚洲精品免费一区亚洲精品免费精品一区 | 欧美色图激情小说| 亚洲国产一区二区精品视频 | 国产乱人乱偷精品视频a人人澡| 欧美蜜桃一区二区三区| 国产乱码一区二区| 精品久久免费看| 偷拍精品一区二区三区| 亚洲精品天天看| 国产午夜在线观看| 精品国产欧美一区二区五十路| 黄色成人在线| 久久久久久久一区二区| 免费高潮视频95在线观看网站| 欧美综合第一页| 成人自拍视频网| 亚洲伊人久久大香线蕉av| 91精品国产乱码久久久竹菊| 精品一区久久久| 成人精品影院| 国产日韩欧美大片| 国产精品婷婷| 国产成人黄色网址| 成人污污视频在线观看| 亚洲影院久久精品| 国产精品丝袜视频| 国产精品4hu.www| 亚洲综合第一页| 欧美电影在线观看免费| 欧洲精品一区色| 久久综合99| 欧美午夜小视频| 日本特黄久久久高潮| aaaaaaaa毛片| 久久综合久久综合亚洲| 中文字幕观看av| 黑人巨大精品欧美一区二区| 中文字幕一区二区人妻痴汉电车| 日韩亚洲国产中文字幕欧美| 深夜福利在线看| 色诱女教师一区二区三区| 丰满大乳少妇在线观看网站| 国产精品7m视频| 天堂精品久久久久| 日本一区二区三区免费观看| 午夜精品久久| 国产九九热视频| av资源站一区| 免费在线观看a级片| 精品久久久国产| 99国产精品欲| 亚洲偷欧美偷国内偷| 免费不卡av| 成人欧美一区二区三区在线| 亚洲区小说区图片区qvod按摩| 爱爱爱视频网站| 日日夜夜免费精品| a级一a一级在线观看| 亚洲三级电影全部在线观看高清| 久久久久久少妇| 精品国产伦一区二区三区免费| 中文字幕在线视频区| 欧美在线一级视频| www.神马久久| 女女百合国产免费网站| 奇米777欧美一区二区| 久久国产精品无码一级毛片| 亚洲在线中文字幕| 99产精品成人啪免费网站| 一区二区亚洲欧洲国产日韩| 色吧亚洲日本| 国产一区二区免费电影| 国产精品分类| 男人女人拔萝卜视频| 亚洲男同性恋视频| 91福利在线观看视频| 国产一区二区三区精品久久久 | 偷拍精品福利视频导航| 免费在线黄网站| 国产福利91精品一区二区三区| 二区三区四区视频| 欧美日韩一区二区三区视频| 精品影院一区| 日韩免费观看av| 亚洲精品蜜桃乱晃| 国产一区二区三区精彩视频| 99在线热播精品免费| 黄色小说在线观看视频| 欧美成人性福生活免费看| 性爱视频在线播放| 99re在线| 伊人影院久久| 国产精品无码电影| 精品国产1区2区| 日本福利在线观看| 国产精品1234| 欧美一二区在线观看| 欧美大尺度做爰床戏| 国产精品每日更新在线播放网址| 中文字幕免费在线看| 久久精品中文字幕| 99久久香蕉| www.亚洲天堂网| 中文字幕av一区二区三区免费看| 亚洲一区二区视频在线播放| 久久精品久久久久电影| 免费看一区二区三区| 97久久国产亚洲精品超碰热| 成人精品免费看| 国产成人一级片| 一级做a爰片久久毛片美女图片| 青青热久免费精品视频在线18| 亚洲国产一区在线| 国产精品一二三四五| 日韩免费一级片| 亚洲视频欧洲视频| 四虎国产精品免费久久5151| 五月天激情图片| 99精品视频中文字幕| 中文字幕永久在线观看| 久久亚洲精品一区二区| av综合网站| 中文字幕第80页| 亚洲精品成a人| 亚洲av片一区二区三区| 国产精品九九久久久久久久| 亚洲澳门在线| 亚洲熟女乱综合一区二区三区| 在线一区二区三区四区五区| 国产在线1区| 蜜桃欧美视频| 国产一区二区三区黄视频 | 一区二区欧美在线| 精品视频在线播放一区二区三区 | 亚洲一区二区三区色| 成人免费精品视频| 成人一二三四区| 欧美精品videos| 日韩视频在线观看| 久久久午夜精品福利内容| 欧美丝袜第三区| a级片免费在线观看| 亚洲欧美日韩精品综合在线观看| 丁香一区二区三区| 亚洲av无码乱码国产精品fc2| 欧美另类在线播放| re久久精品视频| 一本加勒比波多野结衣| 91麻豆精品国产91久久久使用方法 | 国产精品自拍视频在线| 午夜一区二区三区视频| 免费黄色在线观看| 欧美影视一区二区|