如何在return语句之前等待委托方法执行?

时间:2016-03-08 16:53:36

标签: ios objective-c multithreading delegates vlc

我有一个模型对象,它有一个类方法,用于检查模型对象是否已经存在,如果有,则返回它,如果没有,则创建它然后返回它。该类利用VLC框架生成有关视频文件的数据并生成缩略图。这是我遇到麻烦的地方。

一旦调用了fetchthumbnail方法,VLCThumbnailer就会通过委托方法返回缩略图。问题是,在我的类创建方法到达它的返回函数之后,才会返回委托方法。这是一个代码示例。

-(AnimuProfile*)createnewProfileforFilename:(NSString*)filename{

        NSURL *fileURL = [NSURL fileURLWithPath:filename];
    VLCMedia *media = [VLCMedia mediaWithURL:fileURL];
    FilenameParser *parser = [[FilenameParser alloc]init];
    NSArray *parsedFilename = [parser parseFilename:[filename lastPathComponent]];

    NSArray *mediaArray = [media tracksInformation];
    if (mediaArray.count != 0) {
        NSDictionary *videoTrackinfo = [mediaArray objectAtIndex:0];
        _fansubGroup = parsedFilename[0];
        _seriesTitle = parsedFilename[1];
        _episodeNumber = parsedFilename[2];
        _filename = [filename lastPathComponent];
        _filepathURL = fileURL;
        _filepathString = filename;
        _watched = NO;
        _progress = [VLCTime timeWithInt:0];
        _length = [[media length]stringValue];

        NSNumber *resolution = [videoTrackinfo valueForKey:@"height"];
        _resolution = [NSString stringWithFormat:@"%@p",resolution];

        VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media andDelegate:self];

        [thumbnailer fetchThumbnail];



    NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    NSString *profileName = [[_filename lastPathComponent] stringByAppendingPathExtension:@"prf"];
    NSString *pathandProfileName = [libPath stringByAppendingPathComponent:profileName];
    [NSKeyedArchiver archiveRootObject:self toFile:pathandProfileName];

      return self;
}

然后是委托方法:

#pragma mark VLC Thumbnailer delegate methods
- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailerP{
    NSLog(@"Thumbnailer timed out on file %@",_filename);
    UIImage *filmstrip = [UIImage imageNamed:@"filmstrip"];
    _thumbnail = UIImagePNGRepresentation(filmstrip);
}
- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
    UIImage *image = [UIImage imageWithCGImage:thumbnail];
    _thumbnail = UIImagePNGRepresentation(image);

}

我知道锁定主线程等待委托方法被调用是一个nono,所以应该在这个实例中做些什么?

2 个答案:

答案 0 :(得分:1)

  

我知道它是一个nono来锁定等待委托的主线程   要调用的方法,以便在这个实例中应该做什么?

在VLC的视频处理线程上调用这些委托方法。它们不是主线程,因此,您不应该直接在返回块中调用随机UIKit API。

您需要在结果可用时进行处理。如果VLC是使用现代模式实现的,那么它将使用完成块。但它不是,所以......

 - (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
  {
      dispatch_async(dispatch_get_main_queue(), ^{ ... process thumbnail and update UI accordingly here ...});
  }

也就是说,您的createnewProfileforFilename:方法应开始处理,但不要指望它会在以后某个时间完成。然后,当稍后发生时,您将触发使用在后台处理的数据更新UI。

而且,正如您所说,您永远不应该阻止主队列/线程。

答案 1 :(得分:0)

我能够通过创建一个单独的类作为delgate来解决它,制作缩略图获取请求然后处理它们。

@property NSMutableArray *queue;
@end

@implementation ThumbnailWaiter

+(id)sharedThumbnailWaiter{
    static ThumbnailWaiter *singletonInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singletonInstance = [[self alloc] init];
    });
    return singletonInstance;
}


-(id)init{
    self = [super init];
    if (self) {


        NSMutableArray *queue = [NSMutableArray array];
        _queue = queue;


    }


    return self;
}


-(void)requestThumbnailForProfile:(AnimuProfile*)profile{


    VLCMedia *media = [VLCMedia mediaWithURL:profile.filepathURL];
    VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media andDelegate:self];
    [_queue addObject:profile];
    [thumbnailer fetchThumbnail];

}




#pragma mark VLC Thumbnailer delegate methods
- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailerP{


}

- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail{
    UIImage *image = [UIImage imageWithCGImage:thumbnail];
    AnimuProfile *profile = _queue.firstObject;
    profile.thumbnail = UIImagePNGRepresentation(image);
    [profile saveProfile];
    [_queue removeObjectAtIndex:0];

   }

看起来几乎是愚蠢的必须这样做,但它似乎工作。