0

Я пытаюсь создать моментальный снимок UICollectionViewCell, создав CGBitMapContext. Я не совсем ясно, о том, как это сделать, или как использовать связанные классы, но после того, как немного исследований, я написал следующий метод, который вызывается из внутри моего UICollectionViewCell подкласса:Создайте CGImage из CGBitmapContext и добавьте в UIImageView

- (void)snapShotOfCell 
{ 
    float scaleFactor = [[UIScreen mainScreen] scale]; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(NULL, self.frame.size.width * scaleFactor, self.frame.size.height * scaleFactor, 8, self.frame.size.width * scaleFactor * 4, colorSpace, kCGImageAlphaPremultipliedFirst); 

    CGImageRef image = CGBitmapContextCreateImage(context); 
    UIImage *snapShot = [[UIImage alloc]initWithCGImage:image]; 

    UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.frame]; 
    imageView.image = snapShot; 
    imageView.opaque = YES; 
    [self addSubview:imageView]; 

    CGImageRelease(image); 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 
} 

Результат является что изображение не появляется. После отладки я могу определить, что у меня есть действительный (не нулевой) контекст, CGImage, UIImage и UIImageView, но ничего не отображается на экране. Может ли кто-нибудь сказать мне, что мне не хватает?

ответ

0

Вы можете добавить это в качестве категории в UIView и он будет доступен для любого представления

- (UIImage*) snapshot 
{ 
    UIGraphicsBeginImageContextWithOptions(self.frame.size, YES /*opaque*/, 0 /*auto scale*/); 
    [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return image; 
} 

Тогда вам просто нужно сделать [self addSubview:[[UIImageView alloc] initWithImage:self.snapshot]] от вас объекта клетки.

[EDIT]

Обеспечение потребности в асинхронном рендеринга (вполне понятно), это может быть достигнуто с помощью очереди отправки. Я думаю, что это будет работать:

typedef void(^ImageOutBlock)(UIImage* image); 

- (void) snapshotAsync:(ImageOutBlock)block 
{ 
    CGFloat scale = [[UIScreen mainScreen] scale]; 
    CALayer* layer = self.layer; 
    CGRect frame = self.frame; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() { 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGContextRef context = CGBitmapContextCreate(NULL, frame.size.width * scaleFactor, frame.size.height * scaleFactor, 8, frame.size.width * scaleFactor * 4, colorSpace, kCGImageAlphaPremultipliedFirst); 
     UIGraphicsBeginImageContextWithOptions(frame.size, YES /*opaque*/, scale); 
     [layer renderInContext:UIGraphicsGetCurrentContext()]; 
     UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 
     CGContextRelease(context); 
     CGColorSpaceRelease(colorSpace); 
     dispatch_async(dispatch_get_main_queue(), ^() { 
      block(image); 
     }); 
    }); 
} 

[EDIT]

- (void) execute 
{ 
    __weak typeof(self) weakSelf = self; 
    [self snapshotAsync:^(UIImage* image) { 
     [weakSelf addSubview:[[UIImageView alloc] initWithImage:image]] 
    }]; 
} 
+0

Мой ответ предполагает ARC на – NSProgrammer

+0

Спасибо, у меня был этот код работает, но проблема была, что она занимает слишком много времени, чтобы выполнить и в то время как выполнение вызывало зависание прокрутки просмотра коллекции. Было предложено вместо этого «перерисовать каждую ячейку в свой собственный растровый контекст на фоновом потоке». Поэтому я пытаюсь понять, как начать это делать. – jac300

+0

Обновлен мой ответ. В конечном счете, что бы вы ни делали, мне нужно визуализировать контекст, прежде чем принимать изображение из контекста, это ключ. – NSProgrammer