如何在 return 语句之前等待委托方法执行?
How to wait for delegate method execution before return statement?
我有一个模型对象,它有一个 class 方法来检查模型对象是否已经存在,如果存在,return 就创建它,如果不存在,就创建它然后 returns 它。 class 利用 VLC 框架生成有关视频文件的数据并生成缩略图。这就是我遇到麻烦的地方。
VLCThumbnailer return 在调用 fetchthumbnail
方法后通过委托方法生成缩略图。问题是在我的 class 创建方法到达它的 return 函数之前,委托方法不会得到 returned。这是一个代码示例。
-(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);
}
我知道锁定等待调用委托方法的主线程是不可行的,那么在这种情况下应该做什么?
I know it's a nono to lock the main thread waiting for the delegate
method to be called so what should be done in this instance?
正在 VLC 的视频处理线程上调用这些委托方法。它们不是主线程,因此,您不应该直接在 return 块中调用随机 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 的更新。
而且,正如您所说,您永远不应该阻止主要 queue/thread。
我能够通过创建一个单独的 class 作为代理来解决它,发出缩略图获取请求然后处理它们。
@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];
}
必须这样做似乎很愚蠢,但它似乎有效。
我有一个模型对象,它有一个 class 方法来检查模型对象是否已经存在,如果存在,return 就创建它,如果不存在,就创建它然后 returns 它。 class 利用 VLC 框架生成有关视频文件的数据并生成缩略图。这就是我遇到麻烦的地方。
VLCThumbnailer return 在调用 fetchthumbnail
方法后通过委托方法生成缩略图。问题是在我的 class 创建方法到达它的 return 函数之前,委托方法不会得到 returned。这是一个代码示例。
-(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);
}
我知道锁定等待调用委托方法的主线程是不可行的,那么在这种情况下应该做什么?
I know it's a nono to lock the main thread waiting for the delegate method to be called so what should be done in this instance?
正在 VLC 的视频处理线程上调用这些委托方法。它们不是主线程,因此,您不应该直接在 return 块中调用随机 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 的更新。
而且,正如您所说,您永远不应该阻止主要 queue/thread。
我能够通过创建一个单独的 class 作为代理来解决它,发出缩略图获取请求然后处理它们。
@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];
}
必须这样做似乎很愚蠢,但它似乎有效。