Ios 仅在准备就绪时返回方法?
我有一个方法,在这个方法中我运行了几个其他的方法。这些都有完成块,我只想在得到每个子方法的结果后,在主方法的末尾返回一个值。例如:Ios 仅在准备就绪时返回方法?,ios,objective-c,methods,block,Ios,Objective C,Methods,Block,我有一个方法,在这个方法中我运行了几个其他的方法。这些都有完成块,我只想在得到每个子方法的结果后,在主方法的末尾返回一个值。例如: -(NSMutableDictionary *)mainMethod { [self subMethod1Complete:^(NSMutableArray *results) { } [self subMethod2Complete:^(NSMutableArray *results) { } //r
-(NSMutableDictionary *)mainMethod
{
[self subMethod1Complete:^(NSMutableArray *results)
{
}
[self subMethod2Complete:^(NSMutableArray *results)
{
}
//return...
}
我只想在两个子方法完成后在末尾返回字典。我该怎么做
我确实有为每个方法存储BOOL的想法,所以我知道,没有不完整和是完整。所以,当两者都是肯定的时候,我就把我的口述还给他们。但我怎么能按时而不过早地把它叫来呢
更新
我已经调整了我的代码以使用一个完成块,所以当我最终从其他方法接收到来自另外两个完成块的数据时,我会使用编译后的结果运行最后一个完成块。下面你可以看到我的方法。您可以在下面看到我的方法,到目前为止还没有成功,最终的完成块仍然被过早地调用
对我来说很重要getTitles
和getThumbnails
方法。在这些的完成部分,我得到了我需要的数据。只有当我拥有这两个方法时,我才想调用这个主方法的最终完成块。因此,一旦收到标题和缩略图,它将传递它们
-(void)getFeedForUserID:(NSString*)channelID委托:(id)委托完成:(void(^)(NSMutableDictionary*结果))完成块属性:(NSString*)元素。。。
{
va_列表参数;
va_开始(参数、元素);
NSMUTABLEARRY*数组=[NSMUTABLEARRY new];
对于(NSString*arg=element;arg!=nil;arg=va_arg(args,NSString*))[array addObject:arg];
va_端(args);
NSMutableDictionary*resultsDict=[NSMutableDictionary new];
调度队列=调度获取全局队列(0,0);
dispatch_group_t group=dispatch_group_create();
for(NSString*数组中的字符串)
{
if([string IseQualtString:kFeedElementTitle])
{
调度组异步(组、队列、^{
[self-getTitlesArrayForChannel:channelID completionHandler:^(NSMutableArray*结果){
dispatch\u group\u async(组,dispatch\u get\u main\u queue()^{
[resultsDict setObject:results-forKey:kFeedElementTitle];
});
}];
});
}
if([string IseQualtString:kFeedElementTitle])
{
调度组异步(组、队列、^{
[self-getThumbnailsArrayForChannel:channelID completionHandler:^(NSMutableArray*结果){
dispatch\u group\u async(组,dispatch\u get\u main\u queue()^{
[resultsDict setObject:results-forKey:kFeedElement缩略图];
});
}];
});
}
}
调度组通知(组,调度获取主队列()^{
完成块(resultsDict);
});
}
您可以使用GCD和调度组功能。下面有一篇文章对此进行了解释:
例如,在您的例子中,您的代码可能看起来像这样(不知羞耻地从文章中复制并稍作修改)
这需要对类的工作方式进行一些修改,因为上面的方法是异步的(这是一件好事——在所有这些工作完成时,它不会阻止应用程序)。你所需要的只是某种类型的处理程序来调用并通知你的应用程序你的数据已经准备好了,你可以更新你的用户界面或进行任何必要的额外处理。你正在寻找GCD的
dispatch_group
API。以下是苹果公司的一些示例代码:
对更新代码的评论: 你确定你的错误不是因为你的第二个
if
语句第二次检查kFeedElementTitle
而不是我认为可能是你想要的kFeedElementThumbnail
更新了工作示例:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *kFeedElementTitle = @"some";
NSString *kFeedElementThumbnail = @"strings";
NSArray *array = @[@"some", @"test", @"strings"];
NSMutableDictionary *resultsDict = [NSMutableDictionary new];
NSLog(@"App launched");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
for (NSString *string in array)
{
if ([string isEqualToString:kFeedElementTitle])
{
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:5]; // simulate network call
dispatch_group_async(group, dispatch_get_main_queue(), ^{
[resultsDict setObject:@"title result" forKey:kFeedElementTitle];
NSLog(@"Received title result");
});
});
}
if ([string isEqualToString:kFeedElementThumbnail]) // Note: this was changed to kFeedElementThumbnail from kFeedElementTitle
{
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:10]; // simulate network call
dispatch_group_async(group, dispatch_get_main_queue(), ^{
[resultsDict setObject:@"thumbnail result" forKey:kFeedElementThumbnail];
NSLog(@"Received thumbnail result");
});
});
}
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"final dictionary: %@", resultsDict);
});
return YES;
}
输出:
2013-07-16 21:02:46.468 d[947:a0b] App launched
2013-07-16 21:02:51.471 d[947:a0b] Received title result
2013-07-16 21:02:56.471 d[947:a0b] Received thumbnail result
2013-07-16 21:02:56.472 d[947:a0b] final dictionary: {
some = "title result";
strings = "thumbnail result";
}
您不知道块何时返回,因此您不知道当时是否有数据,如果我可以建议您在这些块中调用一个方法,该方法将检查是否设置了两个字典,然后继续处理,否则不要继续
- (void)mainMethod
{
[self subMethod1Complete:^(NSMutableArray *results)
{
self.result1 = results;
[self method3];
}
[self subMethod2Complete:^(NSMutableArray *results)
{
self.results2 = results;
[self method3];
}
}
- (void)method3 {
if ( self.results1 != nil && self.results2 != nil ) {
[self startProcedure];
} else {
// do nothing
}
}
尽管总的来说,我建议您修改代码,以实现不同的功能,只是因为您不能保证其中一个块在返回时完成,更不用说两个块了
你也可以这样做
-(NSMutableDictionary *)mainMethod
{
[self subMethod1Complete:^(NSMutableArray *results)
{
}
[self subMethod2Complete:^(NSMutableArray *results)
{
}
while(result == nil)
sleep(1);
//return...
}
这真的很糟糕。。。。最好重新编写代码,使这两个方法异步运行?在假设这两个块都已完成的情况下,您不能从该方法返回。我的方法使用完成块更有意义,但仍然有问题。不确定原因。正如另一位评论员所写,您也可以使用dispatch_group_wait()等待组完成。然后你可以把这个方法变成同步的。呼叫调度组等待(组、调度时间永远);然后发送_发布(组);谢谢,虽然你的建议不太好,但是在这些方法完成之前,最终的完成块仍然被过早地调用。检查我的原始问题以获取更新。我使用他在问题中陈述的代码回答问题,我的目的是给出一个他可以利用的答案,这样他就不必重新编写太多,我知道这是错误的,这就是我建议重新编写代码的原因。。。。。尽管这不是最好的答案,也有更好的答案,但考虑到这两种选择都能解决问题,我觉得这不值得投票。这也是为什么我在收到反对票时没有删除答案的原因。
dispatch\u group\u wait
overdispatch\u group\u notify
在另一个答案中建议了什么好处?另外,到目前为止GCD解决方案还没有成功,请检查我的原始问题。它们基本上是等效的,但将getFeedForUserID
的行为分别更改为同步或异步
2013-07-16 21:02:46.468 d[947:a0b] App launched
2013-07-16 21:02:51.471 d[947:a0b] Received title result
2013-07-16 21:02:56.471 d[947:a0b] Received thumbnail result
2013-07-16 21:02:56.472 d[947:a0b] final dictionary: {
some = "title result";
strings = "thumbnail result";
}
- (void)mainMethod
{
[self subMethod1Complete:^(NSMutableArray *results)
{
self.result1 = results;
[self method3];
}
[self subMethod2Complete:^(NSMutableArray *results)
{
self.results2 = results;
[self method3];
}
}
- (void)method3 {
if ( self.results1 != nil && self.results2 != nil ) {
[self startProcedure];
} else {
// do nothing
}
}
-(NSMutableDictionary *)mainMethod
{
[self subMethod1Complete:^(NSMutableArray *results)
{
}
[self subMethod2Complete:^(NSMutableArray *results)
{
}
while(result == nil)
sleep(1);
//return...
}