我有一个模型对象,它有一个类方法,用于检查模型对象是否已经存在,如果有,则返回它,如果没有,则创建它然后返回它。该类利用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,所以应该在这个实例中做些什么?
答案 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];
}
看起来几乎是愚蠢的必须这样做,但它似乎工作。