I have the following methods in my SQLiteManager.m implementation. Warning: old legacy code alert
- (void)dealloc {
[super dealloc];
if (db != nil) {
[self closeDatabase];
}
[databaseName release];
}
- (NSError *) closeDatabase
{
NSError *error = nil;
if (db != nil) {
// Set and log error somewhere, not relevant here
}
db = nil;
}
return error;
}
When I run my app in debug mode on iOS 10 iPad, it runs fine. When I run my app in release mode on iOS 10 iPad (with development certificate and provisioning profile), the app crashes on the line [self closeDatabase];, returning a EXC_BAD_ACCESS. I see in my console that self still is an SQLiteManager object. How is it possible that a reference to a method in your own class can give rise to a bad access error, and only in release mode?
PS: When I run with NSZombieEnabled = YES, the app runs fine.
I found my answer. I had to place the call [super dealloc]; to the end of the overridden dealloc method.
- (void)dealloc
{
if (db != nil) {
[self closeDatabase];
}
[databaseName release];
[super dealloc];
}
Related
I get an error (ARC forbids explicit message send of 'dealloc'), if I write:
- (void)dealloc {
self.slider = nil;
self.tabBar = nil;
[super dealloc];
}
Hope anyone can help me.
Thanks a lot for answering.
Remove [super dealloc], it's automatic under ARC.
Should be just:
- (void)dealloc
{
self.slider = nil;
self.tabBar = nil;
}
I am using AFNetworking with AFDownloadRequestOperation to do downloads in my iPhone app.
I get an error when building:
Compile AFUrlConnectionOperation.m
The current deployment target does not support automated __weak references
In my code in the file AFUrlConnectionOperation.m this is where i can see the error:
- (void)setCompletionBlock:(void (^)(void))block {
[self.lock lock];
if (!block) {
[super setCompletionBlock:nil];
} else {
__weak __typeof(&*self)weakSelf = self;
[super setCompletionBlock:^ {
__strong __typeof(&*weakSelf)strongSelf = weakSelf;
block();
[strongSelf setCompletionBlock:nil];
}];
}
[self.lock unlock];
}
How can I resolve it and could you please explain me the logic behind this?
Thanks
So here's my problem: I've created a custom AVCaptureSession that takes pictures. I'm not sure why, but the third time you call startRunning, it crashes. I implemented didReceiveMemoryWarning, and it wasn't called before it crashed. I also ran instruments on it and there were no memory leaks associated with the AVCaptureSession. There were also no logs via console in XCode.
So my question is... is it a memory problem even though the didReceiveMemoryWarning wasn't called? Here's some of my code.
viewWillDisappear (ViewController)
- (void)viewWillDisappear:(BOOL)animated {
if (cameraFlashButton) { [cameraFlashButton release]; }
if (switchCamera) { [switchCamera release]; }
if (cameraBadgeBack) { [cameraBadgeBack release]; }
if (cameraBadgeNumber) { [cameraBadgeNumber release]; }
if (cameraUseButton) { [cameraUseButton release]; }
if (cameraOverlayView) { [cameraOverlayView release]; }
if (blackOverlay) { [blackOverlay release]; }
if (loadingIndicator) { [loadingIndicator release]; }
if (cameraPickButton) { [cameraPickButton release]; }
if (whiteOverlay) { [whiteOverlay release]; }
if (imageOverlay) { [imageOverlay release]; }
if (captureManager) { [captureManager release], captureManager = nil; }
if (theCaptureSession) { [theCaptureSession release], theCaptureSession = nil; }
[super viewWillDisappear:YES];
}
dealloc (CaptureSessionManager)
- (void)dealloc {
if ([self captureSession]) { [[self captureSession] stopRunning]; }
if (previewLayer) { [previewLayer release], previewLayer = nil; }
if (captureSession) { [captureSession release], captureSession = nil; }
if (stillImageOutput) { [stillImageOutput release], stillImageOutput = nil; }
if (stillImage) { [stillImage release], stillImage = nil; }
[super dealloc];
}
Ideas? If you need to see anything else, just ask! Thanks in advance.
If didReceiveMemoryWarning was properly implemented and it was never called, your problem is likely not due to running out of memory. There are many other ways you can get a crash when you start your capture session running. You'd need to post more of your implementation along with details of the crash to help debug this.
However, the code you posted has a number of inefficiencies and style problems. Note in Objective-C messages to nil are perfectly fine. So in your viewWillDisappear and dealloc methods you can and should remove every if test readability. For example, instead of:
if (cameraFlashButton) { [cameraFlashButton release]; }
just use:
[cameraFlashButton release];
If you are using properly synthesized accessors it is also much better to replace lines like
if (previewLayer) { [previewLayer release], previewLayer = nil; }
with simply
self.previewLayer = nil;
I just upgraded to xcode 4.0.2, my iPhone is 4.3.5 and the MFMessageComposeViewController doesn't do anything. It doesn't say "Can't send an SMS", it doesn't crash or abort, but it doesn't open the dialog to send the message either. It simply does nothing.
-(void)sendSMS:(NSString *)message recipientList:(NSArray *)recipients
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *controller =
[[[MFMessageComposeViewController alloc] init] autorelease];
if (controller != nil) {
controller.messageComposeDelegate = self;
controller.body = message;
controller.recipients = recipients;
[self presentModalViewController:controller animated:YES];
// [controller release]; // If I really did this it would crash.
}
}
}
OK I finally answered my own question. Now I want no one else to have to go through this.
I was calling this method from just an NSObject. It was a delegate to MFMessageComposeViewControllerDelegate but that made no difference. I had to move this method to my MainViewController, then it worked.
When my custom initializer fails, I am supposed to return nil. What is the convention for cleaning up any memory I've allocated in my initializer, that I was expecting would be cleaned up in dealloc?
Here is a contrived example:
- (id)init
{
if ((self = [super init])) {
instanceVar1 = [[NSString alloc] initWithString:#"blah"];
if (bad_thing_oh_noes) {
return nil;
}
}
return self;
}
- (void)dealloc
{
[instanceVar1 release];
[super dealloc];
}
A more realistic circumstance where I can't efficiently check every error condition before I do allocations would be deserializing a complex object containing arrays and the like.
Anyway, do I clean up the allocated memory before returning nil, do I send a dealloc message to self before returning nil, or is all of this managed for me magically?
If an error occurs during an initializer, you should call release on self and return nil.
if (bad_thing_oh_noes) {
[self release];
return nil;
}
Also, you must make sure that it is safe to call dealloc on a partially initialized object.
You should call release only at the point of failure. If you get nil back from the superclass’s initializer, you should not call release.
Normally, you should not throw an exception upon initialization failure.
An example from Handling Initialization Failure:
- (id)initWithURL:(NSURL *)aURL error:(NSError **)errorPtr {
self = [super init];
if (self) {
NSData *data = [[NSData alloc] initWithContentsOfURL:aURL
options:NSUncachedRead error:errorPtr];
if (data == nil) {
// In this case the error object is created in the NSData initializer
[self release];
return nil;
}
// implementation continues...