Я недавно столкнулся с этой проблемой при разработке игры для iPhone. Я использовал UIButtons для хранения игровых плит, затем стилизовал их с прозрачными изображениями, цветами фона и текстом.
Все это хорошо работало для небольшого количества плиток. Однако, когда мы добрались до 50, производительность значительно снизилась. После очистки Google я обнаружил, что другие испытывали ту же проблему. Кажется, iPhone борется с множеством прозрачных кнопок на экране сразу. Не уверен, что это ошибка в коде UIButton или просто ограничение графического оборудования на устройстве, но в любом случае это не под вашим контролем в качестве программиста.
Моим решением было нарисовать доску вручную, используя Core Graphics. Сначала это казалось сложным, но на самом деле это было довольно легко. Я просто разместил один большой UIImageView на моем ViewController в Interface Builder, сделав его IBOutlet, чтобы я мог изменить его с Objective-C, а затем построил образ с помощью Core Graphics.
Поскольку UIImageView не обрабатывает краны, я использовал метод touchhesBegan моего UIViewController, а затем triangulated координаты x/y касания к точной черепице на моей игровой плате.
Совет теперь составляет менее одной десятой секунды. Бинго!
Если вам нужен образец кода, просто дайте мне знать.
ОБНОВЛЕНИЕ: Вот упрощенная версия кода, который я использую. Должно быть достаточно для вас, чтобы получить суть.
// CoreGraphicsTestViewController.h
// CoreGraphicsTest
#import <UIKit/UIKit.h>
@interface CoreGraphicsTestViewController : UIViewController {
UIImageView *testImageView;
}
@property (retain, nonatomic) IBOutlet UIImageView *testImageView;
-(void) drawTile: (CGContextRef) ctx row: (int) rowNum col: (int) colNum isPressed: (BOOL) tilePressed;
@end
... и файл .m ...
// CoreGraphicsTestViewController.m
// CoreGraphicsTest
#import "CoreGraphicsTestViewController.h"
#import <QuartzCore/QuartzCore.h>
#import <CoreGraphics/CoreGraphics.h>
@implementation CoreGraphicsTestViewController
@synthesize testImageView;
int iTileSize;
int iBoardSize;
- (void)viewDidLoad {
int iRow;
int iCol;
iTileSize = 75;
iBoardSize = 3;
[testImageView setBounds: CGRectMake(0, 0, iBoardSize * iTileSize, iBoardSize * iTileSize)];
CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
for (iRow = 0; iRow < iBoardSize; iRow++) {
for (iCol = 0; iCol < iBoardSize; iCol++) {
[self drawTile: context row: iRow col: iCol color: isPressed: NO];
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[testImageView setImage: image];
UIGraphicsEndImageContext();
[super viewDidLoad];
}
- (void)dealloc {
[testImageView release];
[super dealloc];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: testImageView];
if ((location.x >= 0) && (location.y >= 0) && (location.x <= testImageView.bounds.size.width) && (location.y <= testImageView.bounds.size.height)) {
UIImage *theIMG = testImageView.image;
CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[theIMG drawInRect: rect];
iRow = location.y/iTileSize;
iCol = location.x/iTileSize;
[self drawTile: context row: iRow col: iCol color: isPressed: YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[testImageView setImage: image];
UIGraphicsEndImageContext();
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIImage *theIMG = testImageView.image;
CGRect rect = CGRectMake(0.0f, 0.0f, testImageView.bounds.size.width, testImageView.bounds.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[theIMG drawInRect: rect];
[self drawTile: context row: iRow col: iCol isPressed: NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[testImageView setImage: image];
UIGraphicsEndImageContext();
}
-(void) drawTile: (CGContextRef) ctx row: (int) rowNum col: (int) colNum isPressed: (BOOL) tilePressed {
CGRect rrect = CGRectMake((colNum * iTileSize), (rowNum * iTileSize), iTileSize, iTileSize);
CGContextClearRect(ctx, rrect);
if (tilePressed) {
CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);
} else {
CGContextSetFillColorWithColor(ctx, [[UIColor greenColor] CGColor]);
}
UIImage *theImage = [UIImage imageNamed:@"tile.png"];
[theImage drawInRect: rrect];
}
Хммм, это заставило меня проверить одно, что зафиксировало это - хорошо, «странные вещи происходят». Который купил другой вопрос, если бы вы могли ответить. Раньше я подклассифицировал UIView, чтобы нарисовать некоторые строки и прочее, а затем в подклассе, который я создал, и добавил UIButtons к себе. Хотя он работал, он делал некоторые странные вещи и не отображался должным образом при нормальной нагрузке. Я вытащил код кнопки из подкласса и создал кнопки и добавил его в представление в моем основном классе, и он сработал. Что происходит? Я делаю большой нет нет, добавляя элементы в подкласс UIView в UIView? – Rudiger
Нет ничего плохого, если вы вообще не добавляете subviews в -initWithBlah. Странные вещи могут произойти, если вы добавите их в -drawRect: (я думаю, что -layoutSubviews безопасен, но я не совсем уверен). –
Хотя это не ответ на вопрос, который я искал, он исправил большинство моих проблем. Я рассмотрю ответы других людей, которые помогут решить мою проблему с производительностью. – Rudiger