Maybe it is silly question, but I have an curious problem. My app fails every time I try to refresh my data in database using core data when I re-enter the view controller. If I enter the view controller and refresh data from internet it works. However, when I start the program, enter the view controller, then pop it and re-enter and try refresh data, it fails and nothing is logged in view controller. I do not know why it happens. So I tried to debug it but the problem disappeared. After I tried again without debug mode it failed once more. I do not know why. Could it be problem of allocation, or something not released? Here's my implementation of -viewDidLoad:
- (void)viewDidLoad {
pool = [[NSAutoreleasePool alloc] init];
if (managedObjectContext_ == nil)
{
managedObjectContext_ = [[(NavTestAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext] autorelease];
}
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(insertNewObject)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];
prikazDatabaseArray = [[[NSMutableArray alloc] init]retain];
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd.MM.yyyy"];
datumOd = [[dateFormatter stringFromDate:now] retain];
[dateFormatter release];
VObrat = YES;
}
I also use
NSAutoreleasePool *pool;
NSURLConnection *theConnection;
NSMutableURLRequest *theRequest;
NSData *xmlData;
NSData *xmlFile;
NSXMLParser *addressParser;
in my code. If you could, at least help me find where I have the problem, because without debug and console I feel like a blind man.
Thanks a lot
remove the autorelease from the line managedObjectContext_ = [[(NavTestAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext] autorelease];
You didn't retain, so you should not (auto)release it.
Edit: I see, there's more.
remove the retain in prikazDatabaseArray = [[[NSMutableArray alloc] init]retain];. Alloc retains your object already. No need to do it twice.
And get rid of the autoreleasepool or drain it at the end of the method.
You should consider to read the Memory Management Programming Guide again.
if you are creating your own pool then you need to release the pool in the same context or method or loop.
you should use [pool drain] for that.
if you are not able to see your crash log you run with performance tool it will give you the location where u are doing wrong.
Related
Following a tutorial for a photo slideshow for code ivI'e run into what I think is some deprecated code. I have an ARC error at autorelease and a warning with the setDelegate:self
NSXMLParser *photoParser = [[[NSXMLParser alloc]
initWithContentsOfURL:[NSURL URLWithString:
#"http://localhost/photos/index.xml"]] autorelease];
[photoParser setDelegate:self];
Remove the autorelease so that the code looks like the following:
ARC does not allow explicit autorelease calls. If you want an object to be deallocated you don't have to do anything (ARC will handle it). In some case you may want to set an object to nil (such as photoParser = nil;)
NSXMLParser *photoParser = [[NSXMLParser alloc]
initWithContentsOfURL:[NSURL URLWithString:
#"http://localhost/photos/index.xml"]];
[photoParser setDelegate:self];
I have spent many hours looking into this and I still can't find a solution. Here's a chart on what the user goes through:
The user takes a picture or takes one from their camera roll
As soon as they take (or select) one, the captionView closes
As soon as the captionView closes, startUploads from a different view starts
If the user decides to open the view that startUploads is in, they can see what has been uploaded
Now that you know a little bit about the process, I have a few issues. When uploads finish I want them to fade out. I know how to do that, but for some reason when I call to, the self.theTableView returns null. I have a #property (nonatomic, retain)... in my .h and I have a #sythesize theTableView; in my .m.
In a different question, I found out that when doing the startUploads, my NSMutableArray needed to be initiated in here (so I thought that it would do the same with my UItableView). Here's what I have:
- (id)initWithNibNamed:(NSString *)nibName bundle:(NSBundle *)bundle {
self = [super initWithNibNamed:nibName bundle:bundle];
if (self) {
processList = [[NSMutableArray alloc] init];
self.theTableView = [[UITableView alloc] init];
NSLog(#"thetableview: %#", theTableView);
}
return self;
}
Just in case you want to see how startUploads is called, here's the code:
processViewController *testtest = [[processViewController alloc] initWithNibName:#"processView.xib" bundle:nil];
//testtest.processList = [[NSMutableArray alloc] initWithNig];
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest startUploads];
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest release];
However it still shows (null) in the console.
Please help!Coulton
EDIT 1:
Here's where it's being nil:
- (void)deleteOneRow: (NSString *)theString {
int theInt = [processList indexOfObject:theString];
[processList removeObjectAtIndex:theInt];
NSArray *deleteIndexPaths = [[NSArray alloc] initWithObjects: [NSIndexPath indexPathForRow:theInt inSection:0], nil];
NSLog(#"theTableView: %#", self.theTableView);
[self.theTableView beginUpdates];
[self.theTableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.theTableView endUpdates];
}
The designated initializer for UITableView is -initWithFrame:style: and you're leaking. Try this in -viewDidLoad instead.
self.theTableView = [[[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain] autorelease];
I am creating an app for the Iphone/Itouch, but I keep on running into a couple of major leaks that just crash the app. In my game, right when I press play (from the home screen)It goes to another page that has the game on it. But, right after it appears, ind the console I get a Warning: Memory level=1. What could be happening? Here is my ViewDidLoad Method:
-(void)viewDidLoad {
[super viewDidLoad];
array = [[NSMutableArray alloc] initWithCapacity:100];
bulletArray = [[NSMutableArray alloc] initWithCapacity:100];
pos = CGPointMake(0.0,-5.0);
NSString *path = [[NSBundle mainBundle] pathForResource:#"GloriousMorning" ofType:#"mp3"];
AVAudioPlayer *theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
//float effects_Volume = [[NSUserDefaults standardUserDefaults] floatForKey:#"effectsVolume"];
//theAudio.volume = effects_Volume;
[theAudio play];
}
And also, a second question, since my game is a shooting game, the user presses a button titled "Fire". But, every time I test my app on a device, It crashes when I press the fire button. Here is my code for the fire button.
-(IBAction)Fire {
NSString *path = [[NSBundle mainBundle] pathForResource:#"gunShot" ofType:#"mp3"];
AVAudioPlayer *theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
//float effects_Volume = [[NSUserDefaults standardUserDefaults] floatForKey:#"effectsVolume"];
//theAudio.volume = effects_Volume;
[theAudio play];
//IBOutlet UIImageView *newBullet = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Bullet.png"]];
UIImageView *newBullet = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Bullet.png"]];
newBullet.frame = CGRectMake(0, 0, 10.0, 10.0);
newBullet.center = CGPointMake(239.0, 236.0);
[bulletArray addObject:newBullet];
[self.view addSubview:newBullet];
}
First, I create a sound. Then, I place a bullet right where the gun is currently located, and add it to an array so that every .01 of a second, in another bit of code, I can run through the array and check every bullet to detect collision.
Please tell me what I am doing wrong. Thanks!!!
The error when I click the Fire Button that makes the app crash is this:
GDB: Data Formatters temporarily unavailable, will retry after a 'continue'(unknown error loading shared library "
And Also I think I am making a huge leak when I try to play the audio, at least that's what someone told me. (If that is the case, please tell me how to fix it)
You alloc'd theAudio so you need to release it when you are done. Might be better to make that a ivar so you don't have to set up and tear down the audio every time they press the fire button.
I have an app which uses a UISearchBar to dynamically search from an external API based on user input.
The app is searching the external API fine and displaying results correctly, but when I select any row from the search results, the screen freezes and I am getting this error;
Tried to obtain the web lock from a thread other than the main thread or the web thread
UIKit should not be called from a secondary thread
I have absolutely no idea how I can fix this.
Here is the code;
- (void) run: (id) param {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL: [self URL]];
[parser setDelegate: self];
[parser parse];
[parser release];
[delegate parseDidComplete];
[pool release];
}
- (void) parseXMLFile: (NSURL *) url
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self setURL: url];
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:#selector(run
object: nil];
[myThread start];
[pool release];
}
"Tried to obtain the web lock from a
thread other than the main thread or
the web thread UIKit should not be
called from a secondary thread"
The fix is conceptually simple; don't update the UI from your thread.
Assuming the parseDidComplete is where the message is sourced, then something like this will "work":
[delegate performSelectorOnMainThread: #selector(parseDidComplete) withObject: nil waitUntilDone: YES];
"Work" because threading is hard and this answer completely ignores any synchronization issues you might have.
Note that you'd be better off using NSOperation and NSOperationQueue. They are well documented and there are a bunch of examples.
I would suspect the line:
[delegate parseDidComplete];
If the delegate class is interacting with UIKit components, then the background thread that is retrieved the XML contents is then calling the front-end objects which must all be in the main thread.
You may want to look at using an NSOperation and NSOperationQueue to do the asynchronous operations. I believe that provides a more threadsafe way to handle this type of use case.
This is a general question about memory management and best practices when using Cocoa arrays.
Which of the following is "better":
NSArray *pageControllers = [[NSArray alloc] initWithObjects:
[[Page1 alloc] initWithNibName:#"Page1" bundle:nil],
[[Page2 alloc] initWithNibName:#"Page2" bundle:nil],
[[Page3 alloc] initWithNibName:#"Page3" bundle:nil],
nil];
...then release NSArray later when not needed anymore...
Or
NSMutableArray *pageControllers = [[NSMutableArray alloc] init];
UIViewController *page1 = [[Page1 alloc] initWithNibName:#"Page1" bundle:nil];
[pageControllers addObject:page1];
[page1 release];
UIViewController *page2 = [[Page2 alloc] initWithNibName:#"Page2" bundle:nil];
[pageControllers addObject:page2];
[page2 release];
UIViewController *page3 = [[Page3 alloc] initWithNibName:#"Page3" bundle:nil];
[pageControllers addObject:page3];
[page3 release];
...then release NSMutableArray later when not needed anymore...
Or is there something else that's even better?
Either way works fine, but keep in mind that you'll be leaking all your page objects in the first example.