ИСПРАВЛЕНО: Я пока не уверен, почему.Код был обновлен ниже, а примечания внизу
У меня очень странная ошибка, которая не отображается на симуляторе (даже при работе с инструментами), если я не включаю всех зомбии параметры отладки.Тем не менее, это будет сбой телефона после минуты обновлений (1 обновление в секунду).У меня есть 2D-массив, который я беру подмножество, применяю цветовую карту и превращаю в изображение (этот массив постоянно меняется).Затем я передаю это изображение в модель, и viewcontroller извлекает его из модели, как только получает уведомление об обновлении.Я размечу 3 класса: Спектрограмма, Модель, ViewController:
Вот важные биты каждого (есть больше, но не уместно):
Spectrogram.h (Извините, яздесь невозможно сделать правильный отступ)
@interface: Spectrogram : NSObject
{
NSMutableData *arrayData;
}
//renamed so Xcode allows the object with +1 reference count to be returned
- (CGImageRef)newSpectrogramImage;
Spectrogram.m
@implementation Spectrogram
- (CGImageRef)newSpectrogramImage
{
//slightly reordered
NSMutableData *imageData = [[NSMutableData alloc] init];
...code to go through arrayData and colormap it (get RGB transform) and store in imageData...
CGImageRef arrayImage = nil;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//specifically tell CGImage there is no alpha channel
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
//Use the toll-free bridge between NSData and CFData
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)imageData);
arrayImage = CGImageCreate((slices-startSlice), bins, 8, 24, 3*(slices-startSlice), colorSpace, bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault); //image is rotated now, so width and height are switched
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(provider);
CGImageRelease(arrayImage);
[imageData release];
//Pass the CGImageRef with a reference count of 1
return arrayImage;
}
Model.h
@interface: Model : NSManagedObject
{
Spectrogram *spectrogram;
}
//Function the viewController can call to get the update
- (CGImageRef)newSpectrogramImage;
Model.m
@implementation Model
... there is a function that adds new data to the array and notifies all listeners...
- (CGImageRef)newSpectrogramImage {
return [spectrogram newSpectrogramImage];
}
ViewController.h
@interface: ViewController : UIViewController
{
}
//the root controller actually alloc's the record, and sets this property when creating this view
@property (nonatomic, retain) Record *currentRecord;
ViewController.m
@implementation ViewController
@synthesize spectrogramView;
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter ... listen for model updates...
}
//now, the real meat
- (void)recordUpdated:(NSNotification*)notification
{
CALayer *myLayer = self.view.layer;
CGImageRef spectrogramImage = nil;
spectrogramImage = [currentRecord newSpectrogramImage];
myLayer.contents = (id)spectrogramImage;
CGImageRelease(spectrogramImage);
}
Я так много раз менял за последний день, пытаясь найти где и почемувыходит из строя.Вместо этого я попытался передать CGImageRef (но поскольку это не объект, я беспокоюсь о том, чтобы сделать копии того, что может быть огромным образом), и он все равно не работает.И это прекрасно работает в симуляторе (будет работать в течение десятков минут).Но происходит сбой в течение минуты на iphone, или если я включаю параметры отладки для симулятора (он потерпит неудачу, как только загрузится viewcontroller).
На заметку, которая может быть полезна,Этот view-контроллер загружается как модальный вид, когда телефон повернут вбок (прекрасно работает).Тем не менее, у меня есть много NSLogs там, и я вижу, что dealloc этого viewcontroller вызывается еще до того, как mainviewcontroller даже добирается до viewwilldisappear - но он все еще работает.А затем снова вызывается dealloc этого контроллера, когда телефон возвращается и представление исчезает.
Примечание Версия, которая хорошо работала в симуляторе, прошла CGImageRefs вплоть до viewController, вместо этогоUIImages.Я попробовал по крайней мере 50 различных комбинаций того, где создать UIImage из CGImage, и то, что опубликовано выше, является лишь одним из них (все они в конечном итоге терпят неудачу или сразу).Следует отметить, что с помощью приведенного выше кода, если я добавлю это в viewController modelUpdated:
CGSize size = currentModel.spectrogramImage.size;
NSLog(@"width: %f", size.width);
и закомментирую, назначив его для spectrogramView, ширина сообщается правильно, поэтому UIImage передается,он просто не сохраняется (так я понимаю ошибку EXE_BAD_ACCESS).
Кроме того, недавно я получил dan EXE_BAD_ACCESS в строке
self.spectrogramImage = [spectrogram getSpectrogramImage];
.Итак, я думаю, что ошибка может быть внутри класса Spectrogram.Хотя код CGImage и UIImage был взят из примеров Apple.
Исправлены заметки Я читал, что установка содержимого CALayer была гораздо более быстрым способом передачи CGImageRef в представление - инет UIImage посредника.К сожалению, я фиксирую только рабочие изменения, поэтому я не вижу каждую итерацию, которую я прошел.Тем не менее, я знаю, что у меня было что-то очень похожее на это несколько раз, которое продолжало падать.Проблема всегда заключалась в том, что, как написано в данный момент, программа зависала с EXE_BAD_ACCESS.И если бы я увеличил счетчик ссылок (или не выпустил его), то он работал бы отлично, но объект протекал.Я до сих пор не понимаю, как это возможно.Чтобы иметь разницу между утечкой и плохим доступом, используйте счетчик ссылок 1 (а не 2 или более).