- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我必须进行一个单独的api调用,该API会为每个我想获取有关信息的电影返回一些JSON数据。我试图遍历电影ID的数组,并在viewDidLoad方法中的每个ID上调用populateAssetObject。
如果进入调试模式并逐步执行for循环,它将正确填充所有5个标题的电影,但如果正常运行,则电影数组只是前两个对象。我认为这可能是某些多线程引起的?我并不是那个领域的专家,有人知道我的问题吗?
viewDidLoad:
_movies = [[NSMutableArray alloc] init];
for (NSString *curr in assetIDs) {
[self populateAssetObject:curr];
}
-(void)populateAssetObject:(NSString *)videoID {
NSString *urlString = [NSString stringWithFormat:@"[api url]", videoID];
NSURL *url = [NSURL URLWithString:restURLString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
NSError *error = nil;
NSDictionary *contents = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
OVDAsset *newAsset = [[OVDAsset alloc] init];
[newAsset setTitle:[contents valueForKey:@"title"]];
[newAsset setDescription:[contents valueForKey:@"longDescription"]];
[self.movies addObject:newAsset];
}
最佳答案
您的方法有一个重要问题:
您的方法populateAssetObject:
是一个同步方法,它将访问远程资源。此方法将在主线程上执行,因此将阻止UI。
循环调用它只会使情况变得更糟。
您真正需要的是一个异步方法,该方法在后台线程中执行所有操作,而完成块则在整个操作完成后通知调用站点:
typedef void (^completion_t)();
- (void) populateAssetsWithURLs:(NSArray*) urls completion:(completion_t)completionHandler;
viewDidLoad
中执行以下操作:
- (void) viewDidLoad {
[super viewDidLoad];
[self populateAssetsWithURLs:urls ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
}
populateAssetsWithURLs:completion:
方法。
- (void) populateAssetsWithURLs:(NSArray*) urls
completion:(completion_t)completionHandler
{
NSUInteger count = [urls count];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (NSUInteger i = 0; i < count; ++i) {
[self synchronousPopulateAssetObject:urls[i]];
}
if (completionHandler) {
completionHandler();
}
});
}
- (void) synchronousPopulateAssetObject:(NSString*)url {
...
}
asynchronousPopulateAssetObject
),每个任务都需要异步启动,并且最终结果也只能异步获得。具有
for loop
非常不适合使循环异步。
NSArray
的Category:
typedef void (^completion_t)(id result);
-(void) forEachPerformTask:(task_t)task completion:(completion_t)completionHandler;
task
是
task_t
类型的异步块,具有自己的完成处理程序作为参数:
typedef void (^task_t)(id input, completion_t);
NSOperationQueue
的方法:
NSOperationQueue
具有不可估量的优势,可以通过
取消来消除正在运行和待处理的异步任务。实际上,执行无法取消的操作列表的异步解决方案是不完整的解决方案,在大多数情况下可能根本不适用。
NSOperationQueue
可以同时执行其任务。可以使用
maxConcurrentOperationCount
属性设置发生任务的数量。
NSOperationQueue
时会有一些变化,最简单的基本思想是:
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 2;
for (NSString* url in urls) {
[queue addOperationWithBlock:^{
[self synchronousPopulateAssetObject:url];
}];
}
addOperationWithBlock:
创建一个操作,该方法从一个块动态创建一个
NSOperation
对象。
waitUntilAllOperationsAreFinished
方法的“阻止”解决方案。由于此方法
阻止了调用线程,并且由于我们需要异步方法
populateAssetsWithURLs:completion:
,因此需要将同步方法包装为异步方法,如下所示:
- (void) populateAssetsWithURLs:(NSArray*) urls
queue:(NSOperationQueue*)queue
completion:(completion_t)completionHandler
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (NSString* url in urls) {
[queue addOperationWithBlock:^{
[self synchronousPopulateAssetObject:url];
}];
}
[queue waitUntilAllOperationsAreFinished];
if (completionHandler) {
completionHandler();
}
});
}
cancelAllOperations
发送到队列,以停止执行挂起的和正在运行的任务。
addOperationWithBlock:
时,我们没有机会为异步任务指定完成处理程序。
addOperationWithBlock:
时的另一个缺点是,我们没有获得设置其他
NSOperation
对象的依赖关系所需的
NSOperation
(请参阅NSOperation的官方文档中的
Operation Dependencies)。
NSOperations
和
NSOperationQueue
的功能,我们将不得不更加详细。例如,有一个完成处理程序可以在操作队列处理完所有任务后通知 call 站点,但这是可行的-但这需要建立依赖关系,这需要在我们需要子类的
NSOperation
对象上,并且需要执行该代码以前是简单的异步任务。
关于ios - viewDidLoad多线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19914106/
我正在学习 objective-c 教程,并注意到 viewDidLoad 中的代码放在 super viewDidLoad 下,而不是第一次调用 viewDidLoad。 代码放在viewDidLo
在Apple的scrollView示例中,他们没有这样称呼。我一直认为这是必须的。我为什么要这样调用它? 最佳答案 如果您要重写该方法,您仍然应该在 super 中调用该方法。即使父类(super c
这个问题已经有答案了: Why/when do we have to call super.ViewDidLoad? (6 个回答) 已关闭 4 年前。 override func viewDidLo
大家好,我有一个双 View Controller 。 我的 firstviewcontroller 有一个按钮,这个按钮发送 NSNotification,secontviewController
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Do I always have to call [super viewDidLoad] in the -v
我有一个关于子类化的问题。 我从我的第一个 View 开始:在我的 .h 文件中: @interface viewAController : UIViewController 在我的 .m 文件中:
我读到一篇文章说,当创建 UIViewController 类时,属性需要为零,然后 Storyboard 或在调用 viewDidLoad 时将其添加到值中。 它表示在构造对象时也无法初始化属性。
这是我当前的代码。我什至没有通过 viewDidLoad 方法覆盖,因为在它说 super viewdidload 的那一行它抛出错误 @interface for uitableview 为选择器
import UIKit class SecondViewController: UIViewController { @IBOutlet weak var labelA: UILabel!
我需要设置和存储一些可用于 View 的 NSUserDefaults 数据。这不适用于 viewDidLoad。 这可以做到吗? 在 viewDidLoad 之前我可以使用什么方法? 你会推荐什么?
当我向主视图 Controller 中的 viewDidLoad 添加方法时,我的 iPhone 应用程序崩溃了: #import "dbQuestionGetterViewController.h"
当用户切换到另一个程序然后再次返回时,原始程序的 View 将被另一个程序的新 View 替换。那么当用户切换回原来的程序时,viewDidLoad会被第二次调用吗? 我问这个是因为如果是这种情况,那
全部, 我正在从我的 applicationDidFinishLaunching 方法创建一个 windowController ... (void)applicationDidFinishLaunc
这个问题已经有答案了: Looking to understand the iOS UIViewController lifecycle (11 个回答) iPhone SDK: what is th
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 5年前关闭。 Improve this
我知道viewDidLoad在 UIViewController 期间可能会多次调用方法的生命周期。但这怎么可能?如何让它多次调用而不是直接调用它?我试过这样做: UIView *view = [
我在使用 iOS 时遇到了一点问题。我使用协议(protocol)在两个 View Controller 之间来回传递数据并手动切换 View 。我的问题是,当我关闭顶 View 时,不再调用底 Vi
我正在开发一款新应用程序,该应用程序主要用于组织网络内容中的信息。它将是一款用于监控道琼斯指数股息 yield 的金融应用程序。为此,需要执行几个步骤,但我现在正在执行第一步。我想选取道琼斯指数中的
我需要采用 viewDidLoad 方法中填充的变量来显示在连接到自定义单元格的标签上。我想做的是: 查找数据库中存储的用户盒子中的 SKU 使用SKU查找数据库中存储的产品详细信息 将产品详细信息存
我正在 viewDidLoad 中使用异步任务函数,根据返回的响应,我正在更改 View (颜色、文本...),但我有“错误”: 有时,当我更改 View 并返回 View 时,我的 View 背景没
我是一名优秀的程序员,十分优秀!