我在这里处理一个问题。我使用此 View 查看应用程序中文档的缩略图。由于加载缩略图减慢了主线程的速度,我寻找了解决方法并最终为缩略图创建任务执行了 NSOperation。

我正在显示一个带有空缩略图框和相应事件指示器的 View ,以告诉用户“坚持住,他们在路上”。但这需要很长时间,以至于我想放一些电梯音乐来让等待更愉快 x_X。

我将这个 NSOperationQueue 设置为 10 个最大并发操作。设置对加载部分有一点帮助,但只是一点点。加载一个拇指仍然需要 6 秒,而且奇怪的是加载 10 需要相同的时间。
以下代码是操作本身

@class ThumbnailView;

@protocol LoadThumbnailOperationDelegate;
@interface LoadThumbnailOperation : NSOperation {
    NSString *key;
    id<LoadThumbnailOperationDelegate> delegate;
    @private
    CGSize _size;
    CGPDFDocumentRef _docRef;
    UIImage * _image;
    NSInteger _page;


}
@property (nonatomic,retain) NSString * key;
@property (nonatomic,assign) id<LoadThumbnailOperationDelegate>delegate;
-(id)initWithPage:(NSInteger)page  operationKey:(NSString *)opKey fromDocRef:(CGPDFDocumentRef)docRef size:(CGSize)size delegate:(id<LoadThumbnailOperationDelegate>)aDelegate;
-(NSInteger)getPage ;
@protocol LoadThumbnailOperationDelegate <NSObject>

-(void)operation:(LoadThumbnailOperation*)operation finishedLoadingThumbnail:(UIImage*)image;
@end


@interface LoadThumbnailOperation (private)
-(UIImage*)makeThumbnailForPage:(NSInteger)page;

@end

@implementation LoadThumbnailOperation
@synthesize key;
@synthesize delegate;

-(id)initWithPage:(NSInteger)page  operationKey:(NSString *)opKey fromDocRef:(CGPDFDocumentRef)docRef size:(CGSize)size delegate:(id<LoadThumbnailOperationDelegate>)aDelegate{

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

        self.key = opKey;
        _docRef = docRef;
        CGPDFDocumentRetain(_docRef);
        _size = size;
        _page = page;
        self.delegate = delegate;

    }
    return self;
}

-(void)main {
#if DEBUG
    NSLog( @"LoadThumbnailOperaiton.m -> main key:%@",key);
#endif
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
    if (![self isCancelled]) {
        _image = [self makeThumbnailForPage:_page];
        [_image retain];
    }
    if(![self isCancelled]){
        if ([delegate respondsToSelector:@selector(operation:finishedLoadingThumbnail:)]) {
            [delegate operation:self finishedLoadingThumbnail:_image];
        }
    }

    [pool release];
}


-(void)dealloc {


    [key release];
    CGPDFDocumentRelease(_docRef);
    [_image release];
    [super dealloc];

}
#pragma mark -
#pragma mark graphics


-(UIImage*) makeThumbnailForPage :(NSInteger) page  {
#if DEBUG
    NSLog( @"LoadThumbnailOperaiton.m -> makeThumbnailForPage:%d",page);
#endif
    CGPDFPageRef pdfPage = CGPDFDocumentGetPage(_docRef, page);
    if (pdfPage !=NULL){
        CGPDFPageRetain(pdfPage);

    }else {
        NSAssert (pdfPage==NULL,@"pdf page NULL");
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 _size.width,
                                                 _size.height,
                                                 8,                      /* bits per component*/
                                                 _size.width * 4,   /* bytes per row */
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextClipToRect(context, CGRectMake(0, 0, _size.width,_size.height));


    CGRect pdfPageRect = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
    CGRect contextRect = CGContextGetClipBoundingBox(context);
    CGAffineTransform transform =aspectFit(pdfPageRect, contextRect);

    CGContextConcatCTM(context, transform);
    CGContextDrawPDFPage(context, pdfPage);

    /*
     create bitmap context
     */
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    UIImage *uiImage = [[UIImage alloc]initWithCGImage:image];

    // clean up
    [uiImage autorelease];
    CGImageRelease(image);
    CGPDFPageRelease(pdfPage);
    return uiImage;
}

-(NSInteger)getPage {

    return _page;
}
@end

这是 View Controller 上的委托(delegate)方法,用于添加已加载的图像

注意:此应用程序仅适用于 iPad

预先感谢您的帮助

最佳答案

出色地,
我找到了解决此问题的方法。我通过检查委托(delegate)调用是否在主线程上完成来解决它。显然,操作完成得相当快,但委托(delegate)调用不是因为它不是在主线程上完成的。因此,请确保使用 -[NSObject performSelectorOnMainThread:] 方法对该线程进行委托(delegate)调用。

对于某些客户来说,这可能仍然不快。我最终使用 automator 生成了 pdf 缩略图,并将它们添加到应用程序包中,然后从磁盘加载它们。比在 ipad 上生成它们要快得多。

关于objective-c - 使用 NSOperation 非常慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4864770/

10-14 22:23
查看更多