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;
Related
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];
}
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
I am new to Objective-C and I am confused about this retain-release thing. Are parameters retained automatically? Do I need to release them?
Here is my code. Did I do the retain-release thing (and everything else) correctly?
#import "ACStringTokenizer.h"
#implementation ACStringTokenizer
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (id)initWithStr:(NSString *)theString
{
self = [super init];
if (self) {
string = [theString retain];
delimiters = #" ";
doesReturnDelims = NO;
}
return self;
}
- (id)initWithStr:(NSString *)theString andDelims:(NSString *)theDelimiters
{
self = [super init];
if (self) {
string = [theString retain];
delimiters = [theDelimiters retain];
doesReturnDelims = NO;
}
return self;
}
- (id)initWithStr:(NSString *)theString andDelims:(NSString *)theDelimiters andDoesReturnDelims:(BOOL)returnDelims
{
self = [super init];
if (self) {
string = [theString retain];
delimiters = [theDelimiters retain];
doesReturnDelims = returnDelims;
}
return self;
}
- (int)countTokens
{
return numberOfTokens;
}
- (BOOL)hasMoreTokens
{
return ![queue isEmpty];
}
- (NSString *)nextToken
{
return [queue remove];
}
- (void)dealloc
{
[string release];
[delimiters release];
[queue release];
[super dealloc];
}
#end
Thanks in advance.
P.S. How do I make init with no parameters invalid?
This might be better suited to http://codereview.stackexchange.com?
Anyway, a few points:
You should read up on the concept of Designated Initializer. In your case you'd probably make initWithStr:andDelims:andDoesReturnDelims: the designated initializer. Only this initializer may call [super init]. All other initializers call [self initWithStr:andDelims:andDoesReturnDelims:] instead of [super init].
There are some more elaborate ways to make init invalid, but if you want to disable it I'd simply make it return nil. However, I don't really see a reason why you'd want to do this in this particular case.
The retains in your init methods and the dealloc method seem to be alright. Method parameters are valid until the end of the method, if you want to keep them beyond that, e.g. in instance variables, you need to retain them (which you seem to have done correctly).
However, there's a whole lot of code omitted in your example so obviously I'm only commenting on what you've posted.
A parameter variable is not retained automatically, you only get the object by reference. To keep them you have to retain them, as you did. For me it looks perfectly fine what you did there.
I am getting leak at [pool release];
My code here is:
#pragma mark UISearchBarDelegate delegate methods
- (void)performSearch:(UISearchBar *)aSearchBar
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
artistName= [aSearchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([artistName length] > 0)
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
LyricsAppDelegate* appDelegate = (LyricsAppDelegate*) [ [UIApplication sharedApplication] delegate];
artistsList=[appDelegate doSearch:artistName ];
[theTableView reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[aSearchBar resignFirstResponder];
}
else
{
[aSearchBar resignFirstResponder];
}
[NSThread exit];
[pool release];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)aSearchBar
{
#try {
[NSThread detachNewThreadSelector:#selector(performSearch:) toTarget:self withObject:aSearchBar];
[aSearchBar resignFirstResponder];
}
#catch (NSException * e) {
NSLog(#"\n caught an exception");
}
#finally {
}
}
Here I am getting leak at [pool release]; in performSearch method.
How can I solve this.
Anyone's help will be much appreciated.
Thank you,
Monish.
Try to release pool before you exit current thread?
...
[pool release];
[NSThread exit];
Edit: From NSThread -exit reference:
Invoking this method should be avoided
as it does not give your thread a
chance to clean up any resources it
allocated during its execution.
Do you really need to call this function BTW?
In addition to Vladimir's answer pointing out the autorelease pool leak, both artistName & artistList are missing a release message before you set them to a new value (otherwise the old object is leaked), and a retain message afterwards (so the new object sticks around when the autorelease pool is drained).
[artistsList release];
artistsList = [[appDelegate doSearch:artistName] retain];