2013-12-20 2 views
1

Это похоже на такую ​​элементарную вещь, которую я хочу, я не могу поверить, что не могу понять, как это сделать. Чтобы сделать описание понятным, предположим, что я просто хочу нарисовать пучок случайных прямоугольников на экране. Эти случайные прямоугольники будут постоянно добавлять друг к другу несколько раз, пока что-то не остановит процесс. Как это сделать?Как просто добавить графический контент в текущий экран в iOS

Ближайшее объяснение, которое я видел, - это рисование приложений, в которых основная схема состоит в том, чтобы нарисовать изображение, сначала скопировав предыдущее изображение в новое изображение, а затем добавив новое содержимое. Копирование исходного изображения обязательно кажется пустой тратой усилий, и, похоже, должно быть возможно просто написать новый контент на месте над тем, что там есть. Мне что-то не хватает?

Обратите внимание, что drawRect заменяет весь кадр. Он хорошо работает для рисования небольшого набора объектов, но быстро становится неудобным, когда существует неопределенное количество истории, которое также нужно отображать.

Редактировать: Я прикрепляю некоторые образцовые изображения, которые являются отпечатками экрана из программы Mix C, которая делает то, что мне нужно. По существу, есть клеточные автоматы, которые перемещаются по экрану, оставляя след. Цвет следа зависит от логики в автомате, а также от цвета пикселя, в который только что проехал автомат. Автоматы должны иметь возможность перемещаться со скоростью сотен пикселей в секунду. Из-за логики, используемой автоматами, мне нужно иметь возможность не только быстро писать изображение, но также иметь возможность узнать, какой цвет пикселя (или зеркальные данные).

enter image description here

enter image description here

enter image description here

+0

Instantiate и добавить, чтобы просмотреть 'UIView' со случайным кадра (и цвета)? – nhgrif

+0

Это приведет к огромной утечке памяти, если вы также не добавили код для удаления скрытых просмотров. –

ответ

1

Обычно это можно сделать, либо создавая отдельные пути или слои для всех прямоугольников (если вы хотите, чтобы следить за ними), или рисуя неоднократно в a CGBitmapContextRef, а затем преобразует его в изображение и рисует его в drawRect:. Это в основном тот же подход, который вы описываете («где основная схема заключается в рисовании в виде изображения ...»), за исключением того, что нет необходимости копировать изображение. Вы просто продолжаете использовать один и тот же контекст и вынимаете из него новые изображения.

Другой инструмент, который вы можете использовать здесь, - CGLayer. Команда Core Graphics не рекомендует использовать ее из-за проблем с производительностью, но делает этот вид рисунка намного более удобным. Когда вы смотрите на документы, и они говорят: «Воспользуйтесь улучшенной производительностью», помните, что это было написано в 2006 году, и когда я спросил об этом команду Core Graphics, они сказали, что более быстрый ответ сегодня - CGBitmapContext. Но вы не можете победить CGLayer для удобства по этой проблеме.


Это должно быть хорошо, поддерживая CGBitmapContext, что вы постоянно писать в (и это позволяет также читать из него). Когда он изменится, вызовите setNeedsDisplayInRect:. В drawRect: создайте изображение и нарисуйте его с помощью CGContextDrawImage, пройдя прямоугольник, в котором вы прошли. (Вы можете передать весь прямоугольник.)

Может быть немного более гибким, чтобы сделать это на CALayer вместо UIView, но я сомневаюсь, что вы увидите большую разницу в производительности. Вид переходит к его слою.

Число раз в секунду это обновление не так уж и важно.drawRect: не будет вызываться чаще, чем частота кадров (макс. 60 кадров в секунду), независимо от того, как часто вы звоните setNeedsDisplayInRect:. Таким образом, вы не будете создавать изображения сотни или тысячи раз в секунду; просто в то время, когда вам нужно что-то нарисовать.

Вы видите конкретные проблемы с производительностью, или вы просто обеспокоены тем, что в будущем можете столкнуться с проблемами производительности? У вас есть образец кода, который показывает проблему? Я не говорю, что это не может быть медленным (возможно, если вы пытаетесь сделать этот полный экран с сетчаткой). Но вы хотите начать с простого решения, а затем оптимизировать. Apple делает много графических оптимизаций за кулисами. Не пытайтесь повторить их слишком много. Они генерируют и рисуют изображения очень хорошо.

+0

Хммм. Похоже, что рисование многократно в «CGBitmapContextRef» может быть тем, что мне нужно сделать, но все же кажется, что рисование всего представления - это пустая трата усилий. Я подозреваю, что будет проблема с производительностью, но, возможно, нет. Я полагаю, что другая альтернатива - использование OpenGL ES 2.0 и 'CAEAGLLayer'. Завтра я посмотрю ваше предложение. –

+0

Вам не нужно перерисовывать весь вид. Вы можете использовать 'setNeedsDisplayInRect:', а затем просто перерисовать прямоугольник, переданный вам в 'drawRect:'. Но это обычно больше проблем, чем того стоит. –

+0

Вы видели эту проблему? http://stackoverflow.com/questions/10484291/setneedsdisplayinrect-causes-the-whole-view-to-be-updated –

0

Я принял еще один ответ, но я включаю свой собственный ответ, чтобы показать альтернативу, которую я использовал для тестирования.

-(void)viewWillLayoutSubviews { 
     self.pixelCount = 0; 
     self.seconds = 0; 
     CGRect frame = self.testImageView.bounds; 
     UIGraphicsBeginImageContextWithOptions(frame.size, YES, 0.0); 
     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextSetLineWidth(context, 1.0); 
     CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 
     CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); 
     CGContextMoveToPoint(context, 0.0, 0.0); 
     CGContextAddRect(context, frame); 
     CGContextFillRect(context, frame); 
     CGContextStrokePath(context); 
     CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); 
     CGContextStrokePath(context); 

     UIImage *blank = UIGraphicsGetImageFromCurrentImageContext(); 
     self.context = context; 
     self.testImageView.image = blank; 

     // This timer has no delay, so it will draw squares as fast as possible. 
     [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(drawRandomRectangle) userInfo:nil repeats:NO]; 

     // This timer is used to control the frequency at which the imageViews image is updated. 
     [NSTimer scheduledTimerWithTimeInterval:1/20.f target:self selector:@selector(updateImage) userInfo:nil repeats:YES]; 

     // This timer just outputs the counter once per second so I can record statistics. 
     [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(displayCounter) userInfo:nil repeats:YES]; 
    } 
    -(void)updateImage 
    { 
     self.testImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    } 
    -(void)displayCounter 
    { 
     self.seconds++; 
     NSLog(@"%d",self.pixelCount/self.seconds); 
    } 
    -(void)drawRandomRectangle 
    { 
     int x1 = arc4random_uniform(self.view.bounds.size.width); 
     int y1 = arc4random_uniform(self.view.bounds.size.height); 
     int xdif = 20; 
     int ydif = 20; 
     x1 -= xdif/2; 
     y1 -= ydif/2; 
     CGFloat red = (arc4random() % 256)/255.0f; 
     CGFloat green = (arc4random() % 256)/255.0f; 
     CGFloat blue = (arc4random() % 256)/255.0f; 
     UIColor *randomColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f]; 
     CGRect frame = CGRectMake(x1*1.0f, y1*1.0f, xdif*1.0f, ydif*1.0f); 
     CGContextSetStrokeColorWithColor(self.context, [UIColor blackColor].CGColor); 
     CGContextSetFillColorWithColor(self.context, randomColor.CGColor); 
     CGContextSetLineWidth(self.context, 1.0); 
     CGContextAddRect(self.context, frame); 
     CGContextStrokePath(self.context); 
     CGContextFillRect(self.context, frame); 
     CGContextStrokePath(self.context); 
     if (self.pixelCount < 100000) { 
     [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(drawRandomRectangle) userInfo:nil repeats:NO]; 
     } 
     self.pixelCount ++; 
    } 

На графике показаны обновления изображения в секунду на оси х и число 20x20 квадратов обращается к контексту в секунду в оси у.

enter image description here

Смежные вопросы