在 Objective-c 中使用调度队列
Posted
技术标签:
【中文标题】在 Objective-c 中使用调度队列【英文标题】:Working with dispatch queues in Objective-c 【发布时间】:2012-10-23 20:38:47 【问题描述】:我对 ios 很陌生,我正在从网络服务获取数据。我将这些数据存储到核心数据中。目前,我正在第一个视图控制器(tableview)中加载我的所有数据。但这需要大约 10 分钟才能填满 tableview 并将所有数据存储在核心数据库中。所以我想知道最佳实践是什么。所以我想使用调度队列。但是最好的使用方法是什么?
第一种方法
-
首先从第一个视图存储数据
用这些数据填充表格视图
将其余数据存储在 db 中。
但是,如果您转到下一个视图并且没有加载所有数据怎么办?
第二种方法
-
从第一个视图存储数据
用这些数据填充 tableview?
当用户进入第二个视图时,存储第二个视图的数据
使用此数据加载第二个视图。
您始终可以正确存储数据,但用户仍然需要等待才能使用该应用程序。 (因为没有为该视图加载数据。)
目前我使用的是第一种方法。并使用调度队列。我就是这样用的。
- (void)fetch1:(UIManagedDocument *)document
dispatch_queue_t fetchQ = dispatch_queue_create("NewsFetch", NULL);
dispatch_async(dispatch_get_main_queue(), ^
//store data in core database for firstViewController and save document.
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
[self loadFirstTableView];
[self fetch2];
);
dispatch_release(fetchQ);
- (void)fetch2:(UIManagedDocument *)document
dispatch_queue_t fetchAlbum = dispatch_queue_create("Album fetcher", NULL);
dispatch_async(fetchAlbum, ^
//store data for secondViewController
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
dispatch_release(fetchAlbum);
谁能帮帮我?
亲切的问候
编辑
我如何从 web 服务获取我的数据是通过以下方式。
NSArray *news = [GenkData getNews]; //gets all the data from webservice as JSON
for (NSDictionary *genkInfo in news)
[News newsWithGenkInfo:genkInfo inManagedObjectContext:document.managedObjectContext];
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
这就是我设置表格视图的方式。
- (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"News"];
request.sortDescriptors = [NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES],nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.genkDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
【问题讨论】:
“所以我想知道最佳实践是什么。所以我想使用调度队列。”你好掉头。您应该更好地描述您的问题并让人们提出解决方案,而不是跳到 GCD 上。 我不知道您的性能问题。使用 Instruments 来确定您的瓶颈,然后在确定瓶颈位置后询问。此外,您对UIManagedDocument
的使用是完全错误的。这些调用是异步的。这就是他们有完成块的原因。
【参考方案1】:
当您遇到性能问题时,您的第一反应应该不是引入多线程。这增加了额外的复杂性,不应掉以轻心,并且需要非常小心地关注架构。
相反,我强烈建议您查看 Ray Wenderlich 的优秀教程,了解如何将 NSFetchedResultsController
连接到 UITableView
。
NSFetchedResultsController
允许您仅加载您需要的数据,并会在用户请求时自动获取批量内容。它会节省你的记忆;这将花费更少的时间;它会让您的用户满意。
在此处查看教程:http://www.raywenderlich.com/999/core-data-tutorial-how-to-use-nsfetchedresultscontroller
编辑
因此,根据您的修改,我将按照以下方式设计您的要求。
您应该使用异步 HTTP 请求从 Web 服务中获取数据。使用NSURLRequest
和AFNetworking
之类的库使这变得更容易。
既然您是从 Web 服务获取数据,那么您真的需要将该数据插入到 Core Data 中吗?更简单的方法是简单地缓存 HTTP 响应,然后直接从中加载表视图。
现在您已经有了 HTTP 响应,请告诉 UITableView
重新加载。当它重新加载时,您使用委托方法向它提供表数据。如果您不使用 Core Data,则无需再与NSFetchedResultsController
混淆。
如果您的 Web 服务返回大量数据,您可能应该编写一些分页机制来批量获取结果。它会这样工作:当用户到达表格视图的末尾时,您将发送另一个请求以获取接下来的 25 个项目。一般的经验法则:在需要之前不要获取数据。
最后,通过所有这些获取,您将想要告诉您的用户发生了什么。请查看SVProgressHUD
。
希望对您有所帮助。
【讨论】:
我正在使用这个 NSFetchedResultsController 来设置我的表格视图。但是还是很慢。 然后发布该代码。我已经在几分之一秒内加载了半百万行的核心数据表。您在获取请求中做错了什么。 如果我理解正确,您说“在需要时将数据加载到核心数据库中”。正确吗? 不,您应该只在需要时将数据从 Core Data 加载到内存中。您说“我正在加载我的所有数据”,这是不推荐的。NSFetchedResultsController
允许您批量加载数据。有关详细信息,请参阅文档。
他指的是 NSFetchRequest 的 setBatchSize 方法,它可以让你在你的 fetch 结果上拥有多条记录。以上是关于在 Objective-c 中使用调度队列的主要内容,如果未能解决你的问题,请参考以下文章
Objective-c中如何基于uiswitch ON/OFF案例实现删除和重新调度本地通知