固定:我不确定原因。代码已在下面更新,并在底部注释
我有一个非常奇怪的错误,它没有显示在模拟器上(即使在运行Instruments时),除非我打开所有的Zombie和Debug选项。但是,一分钟的更新(每秒更新1次)后它会崩溃。我有一个2D数组,我采用了一个子集,应用颜色图,然后变成一个图像(这个数组不断变化)。然后我将该图像传递给模型,一旦收到更新通知,viewcontroller就会从模型中获取它。我将布置3个类--Spectrogram,Model,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,它就会失败)。
另一方面,这可能有些用处。当手机侧向转动时,此视图控制器将作为模态视图加载(效果很好)。但是,我有很多NSLogs,我看到这个viewcontroller的dealloc在mainviewcontroller甚至到viewwilldisappear之前被调用 - 但它仍然运行。然后,当手机转回并且视图消失时,再次调用此控制器的dealloc。
注意 在模拟器中运行良好的版本将CGImageRefs一直传递给viewController,而不是UIImages。我已经尝试了至少50种不同的组合,从CGImage创建UIImage的位置,上面发布的只是其中之一(所有这些都最终失败,或立即失败)。值得注意的是,使用上面的代码,如果我将它添加到viewController modelUpdated:
CGSize size = currentModel.spectrogramImage.size;
NSLog(@"width: %f", size.width);
并注释掉将其分配给spectrogramView,正确报告宽度,因此UIImage正在传递,它只是没有被保留(这就是我理解EXE_BAD_ACCESS错误的方式)。
另外,最近我在
上收到了dan EXE_BAD_ACCESSself.spectrogramImage = [spectrogram getSpectrogramImage];
线。所以,我认为错误可能在Spectrogram类中。尽管CGImage和UIImage代码来自Apple的例子。
修正笔记 我读到设置CALayer的内容是一种更快捷的方式将CGImageRef传递给视图 - 而且没有UIImage中介。不幸的是,我只提交了工作变更,因此我无法看到我经历的每一次迭代。但是,我知道我有几次非常相似的事情一直在崩溃。问题始终是因为它当前已编写,程序将因EXE_BAD_ACCESS而崩溃。如果我提高了引用计数(或者没有释放它),那么它将完美地工作,但是对象会泄漏。我仍然不明白这是怎么可能的。泄漏和BAD ACCESS之间的区别是引用计数为1(而不是2或更多)。
答案 0 :(得分:1)
我无法回答您的具体问题,但这可能会帮助您了解更好的情况。我有一个函数“logMemUsage”,它输出你的内存使用量,并显示自上次以来它有多少变化。如果你每隔一秒钟调用一次,你就可以更好地理解应用程序中内存的使用方式。如果它继续增长,显然会有泄漏,如果它像你期望的那样上下波动,那就好了,如果你认为它不应该下降,你会看到它。它位于Utilities.h / .m
中的github here中答案 1 :(得分:1)
很难从您发布的内容中找出这一点,但为什么不在所有已分配的数据上使用带保留的属性?例如,你从getSpectrogramImage返回一个自动释放的UIImage,并通过调用self.spectrogramImage = [spectrogram getSpectrogramImage];将它存储到Model中,但是在我能看到的任何地方都没有spectrogramImage的属性,即使你'重新利用自我。机制。只是你没有费心发帖吗?它写的方式可能是自动释放,然后当你尝试使用它时......