2016-03-08 41 views
1

我有一个模型对象有一个类方法,用于检查模型对象是否已经存在,如果它返回,或者它没有创建它并返回它。该类使用VLC框架生成有关视频文件的数据并生成缩略图。这是我遇到麻烦的地方。如何在返回语句之前等待委托方法执行?

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

-(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); 

} 

我知道这是锁定的主线程等待委托方法被调用,所以我应该在这种情况下做一个诺诺?

+1

听起来像你想[完成块](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html)[传入你的方法]( http://stackoverflow.com/questions/7180552/implementing-a-method-taking-a-block-to-use-as-callback)。 – Hamish

回答

0

我能够解决它通过创建一个单独的类作为越狱,使缩略图抓取请求,然后处理它们。

@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]; 

    } 

似乎很难做到这一点,但它似乎工作。

+0

我最终通过NSOperations&Blocks来做到这一点。你也应该看看这种方法。 – atulkhatri

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。

而且,正如你所说的,你不应该阻塞主队列/线程。

+0

谢谢。看来你对VLC的工作原理有点了解。问题是我没有从视图控制器调用这些方法,而是从模型对象本身中调用这些方法。这是一个棘手的问题。 –

+0

@JosephToronto只有我读过的那个课程的来源。 :)仍然不是太棘手;你的模型将派发到主线程,主线程更新方法将(很有可能)告诉控制器层有新的数据可用,然后控制器层可以照顾到UI层。或者,你可以发出通知,但这似乎是矫枉过正,无论如何都很难调试(“现在,通知来自哪里?!”)。 – bbum

相关问题