I have a rather large app which works in the simulator but creates in an over-released object scenario on the iPhone device. NSzombies would seem to be the route to go except that the object is not over-released on the simulator and NSZombies does not function on the device. Through hours of logging I seem to be able to pin it down to someplace between when I run -
[locManager startUpdatingLocation] and the start of -
(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
That explains why it works on the simulator, I detect no location ability and do not run that location code.
When I NSLog in-line just before and after [locManager startUpdatingLocation] my NSString object is allocated and present. But when the app executes and it hits locationManager: NSLog shows the NSString is deallocated, gone. THis string object has absolutely nothing to do with location handling or functionality. Unrelated NSString. I have commented out all other potential activity, and commented out all explicit release code and can't find the moment it happens.
I'm further frustrated that lldb seems not to support watchpoints and gdb supports them but this version seems that they don't work ! gdb will set a hardware watchpoint and then Xcode says its running but 30 minutes later there is still no visual activity or break.
I'm on Lion, Xcode 4.1.1, and too much coffee.
What approach should I take to find this released NSString object in such a narrow spectrum of activity and limited tools ?
Once upon a time I had a complex case for locating over released object, so I just inherited from this object to MyObject and overriden a retain and release in a following way:
Here is the DebugString.h file:
#import <Foundation/Foundation.h>
#interface DebugString : NSString
#end
And here is the DebugString.m file:
#import "DebugString.h"
#implementation DebugString
- (id) retain {
NSLog(#"%i", [self retainCount]);
return [super retain];
}
- (void) release {
NSLog(#"%i", [self retainCount]);
[super release];
}
#end
I put a break points inside of this methods and turned them on at the phase when I expected a crash. Afterward I just started to go through this calls one by one and found an issue. It is complex, but it may help sometime and I never saw such approach described in forums. Maybe it will help you also.
Call the location "didUpdate" manually when running in the simulator - at least two calls, timed out about five seconds, after you start up the location manager. That should trigger the same bug as on the phone, then you can use NSZombies.
Also, the simulator SHOULD be able to run location code, I thought that was broken in 4.2 but OK in 4.1.
Related
Xcode 4.2 debugging on a viewDidLoad or viewDidDisappear will end on a EXC_BAD_ACCESS
It breaks on that breakpoint but when continuing ("Continue program execution") it returns a: EXC_BAD_ACCESS (code=1, address=0x....) on Thread 1 (0 start). That did not happen in earlier versions.
Someone getting the same error? Somebody knows how to deal with it?
Code for the example would be a simple:
- (void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(#"View did dissapear");
}
When debugging on breakpoint (line with NSLog) it and then hitting on continue it will end on that EXC_BAD_ACCESS. If no breakpoint then everything works fine.
I am working with Xcode 4.2 Build 4D199 (OS X Lion 10.7.2). Using LLDB debugger.
UPDATE: put a break in all exceptions and it always ends on a Thread 8: EXC_BAD_ACCESS - 0x1f43: movl (%ebx), %eax - line 0: start....
UPDATE 2: played around with Xcode and I really don´t know why but know it works. No code changed... hmmm... strange...
You must always call through to super at some point in all of the viewWill... or viewDid... methods that you override. For example,
- (void) viewDidDisappear:(BOOL)animated {
NSLog(#"View did disapear");
[super viewDidDisappear:animated];
}
If you override this method, you must call super at some point in your implementation.
It's from the doc, I don't know if it's the problem that cause your BAD ACCES, but it's at least something you have to fix.
You are not helping much with that code you provided.
set an malloc_error_break and enable zombies and see if that leads to something
I was recieving the same error on viewDidDisappear:animated - it turned out that I had a typo calling [self viewDidDisappear:animated]; instead of [super viewDidDisappear:animated];
Simple fix but not very noticeable at first. I was surprised it didn't give me a warning.
I see slightly different issue here. In my case(SnowLeopard 10.6.8, XCode 4.2, LLVM 3.0) it stops at the brake point, but XCode doesnt display any debugging info. I can see my stackrace in GDB fine, but local values are messed up. Interestingly i tried to use performSelectorOnMainThread: it can restore XCode debugging functions, but something corrupts active frame values.
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self performSelectorOnMainThread:#selector(_destroyMarketBrowser) withObject:nil waitUntilDone:YES];
}
Btw: Everything works fine in simulator, the problem only occurs on real devices (5.0.1 or 5.1 Beta2)
I am using iphone simulator 4.2 and try to display or NSLog Heading and other Location services attributes e.g. Latitude, Longitude, altitude, horizontalAccuracy, VerticalAccuracy, speed. but its not showing the correct parameters and Incase of Heading its actually not firing the event.
as its execute CLLocation code
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self.delegate locationUpdate:newLocation];
}
and not executing CLHeading code
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
[self.delegate headingUpdate:newHeading];
}
and when I put breakpoint on these both codes it never touch CLHeading code. I am updating location and heading in init.
- (id) init{
if (self!=nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
}
return self;
}
The problem is that I do not know that is due to simulator or there is any problem in code?
please help.
CLLocationManager needs additional hardware and hence wont work on simulator. However you can test that using the method described in this other SO question.
From the documentation:
Some location services require the presence of specific hardware on the given device. For example, heading information is available only for devices that contain a hardware compass. This class defines several methods that you can use to determine which services are currently available.
This answer can be updated for anyone using Xcode 4.2. It is still in beta status, but if you are a paid developer you will have access to it. Also, if you are a paid developer, there are some good videos from WWDC 2011 that explain how to use the simulator for location simulation.
WWDC 2011
See What's New in Core Location and Testing Your Location-Aware App Without Leaving Your Chair
**Note: Please note again that only paid developers have access to these videos
It looks like the behaviour is by default
It fires Location but not heading.
I have not tested my application in actual hard ware to confirm my though...
Anthony Desa
Encountering an issue with SKProductsRequest that is specific to iOS 4.0. The problematic code:
- (void)requestProductData
{
NSSet *productIdentifiers = [NSSet setWithObjects:kLimitedDaysUpgradeProductId, kUnlimitedUpgradeProductId, nil];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self;
[self.productsRequest start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSLog(#"didReceiveResponse");
}
When [SKProductsRequest start] is invoked, the productsRequest:didReceiveResponse: delegate method is never invoked; further, the entire app hangs and is completely unresponsive to input. Obviously, this is a huge issue for our iOS 4.0 users as it not only breaks payments but makes the app completely unusable.
Some other things to note: this only happens on iOS 4.0; iOS 4.2, 3.x are fine. Also: if the delegate is not set on the SKProductsRequest (i.e. comment out the line "self.productsRequest.delegate = self;"), the app doesn't hang (but of course in that case we have no way of getting the product info). Also, the problem still reproduces with everything stripped out of the productsRequest:didReceiveResponse: callback (that method never actually gets called). Finally, if the productIdentifiers NSSet object is initialized to an empty set, the hang doesn't occur.
Has anybody else experienced this? Any ideas/thoughts on what could be going on here, and how we might be able to work around this?
have you tried implementing –request:didFailWithError: in your delegate, and seeing if that's getting called?
I had a similar problem to this today. No response to any of the delegate methods after I made a SKProductRequest.
Everything was working fine, I didn't make any changes to the IAP code yet it broke.
Finally found the problem. If you self reject the app, then the product ID's you made become invalid. We resolved it by resubmitting the app and creating new ID's. Everything started to work again after that.
I'm trying to implement the Paparazzi 2 assignment from the Stanford CS193 course and I'm running into a problem. My one call to save the database is when the app exits (I'm borrowing heavily from Mike Postel's version to check my code):
- (void)applicationWillTerminate:(UIApplication *)application {
if (flickrContext != nil) {
if ([flickrContext hasChanges] == YES) {
NSError *error = nil;
BOOL isSaved = [flickrContext save:&error];
NSLog(#"isSaved? %#", (isSaved ? #"YES" :#"NO") );
// Replace this implementation with code to handle the error appropriately.
if(isSaved == NO){
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
}
Unfortunately, this doesn't seem to be doing the job. I'm getting the occasional EXEC_BAD_ACCESS call that might be related to this, but the database never saves. I've inserted the save into other pieces and it works fine there, just not in this routine. I'm not releasing any of the managed objects in my views, just the managed object context (flickrContext, or whatever I'm calling it in a view).
Any ideas?
Are you sure that applicationWillTerminate: is even being called?
With iOS4 and background process support, the usual application lifecycle is now:
running -> background -> background suspended -> exit
You get an applicationDidEnterBackground: call when transitioning into the background state, but no further notification when the background process suspends or exits.
So, you really need to save state in applicationDidEnterBackground: for iOS4, as well as in applicationWillTerminate: for older versions
flickrContext is your managedObjectContext? I'm betting it is nil or otherwise hosed when you hit this method. You say you are releasing it in a view - surely you should be creating just one, having it owned by the application delegate, and release it only in app delegate's dealloc?
(And when you need to use it -
NSManagedObjectContext* moc = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
)
Regarding your EXEC_BAD_ACCESS - what happens with NSZombieEnabled = YES? What does the static analyzer say?
Good call. I actually solved this one the old fashioned (brute force) way. It turns out that applicationWillTerminate wasn't being called, but it wasn't obvious. The routine to create the database that I had borrowed from the web was explicitly releasing an NSArray that I'm pretty sure was autoreleased. It essentially turned the program into a time bomb. Although I still haven't figured out why it lasted as long as it did and just didn't manifest until I tried to exit.
I'm still learning XCode and CocoaTouch. I know about NSZombieEnabled but I haven't figured out how to use it correctly yet. I'm still in the ham-fisted monkey stage. Thanks for the tips, though. They were helpful.
I'm not getting any location callbacks on either sim or device. I've got this code being called:
- (void)startLocationCallbacks: (NSObject*) ignore
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = MINIMUM_METERS;
[locationManager startUpdatingLocation];
NSLog(#"[DEBUG] [locationManager startUpdatingLocation] (%#, %#)", locationManager, locationManager.delegate);
}
and log statements at the top of both
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
and
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
but neither log statement ever gets called. Location Notifications are enabled for my app (as shown in Settings, plus I said "allow.")
What are some possible reasons that I'm not getting location updates?
Config/other info:
I have allocated locationManager, and saved it in a retain property.
I have called startUpdatingLocation
I'm using 4.1 SDK
Problem is on both Sim & iPod-touch (2nd Gen) & iPhone-3, all running 4.1
Location notifications are allowed in my app (both as indicated in Settings and because I clicked "allow" in the alert.)
I've used CLLocationManager successfully before (in many shipping apps!) This is a real hair-puller for me.
Thanks!
Whew! Ok, I found it.
It turns out that one of the ways to make a CLLocationManager not fire off location callbacks is to do all the set-up in not-the-main-thread. When I moved my setup routine to a performSelectorOnMainThread, all worked exactly as expected.
What a nightmare!
Hope this answer helps others...
Edit/clarification:
Originally, I had something like this:
- (BOOL) appDidFinishLaunchingWithOptions: (NSDictionary*) options
{
// ...[app setup, snip]
[NSThread detachNewThreadSelector: #selector(postLaunchSetupThread) toTarget: self withObject: nil];
}
- (void)postLaunchSetupThread
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
// ...[other setup, snip]
[self setupLocationManager];
[pool release];
}
- (void)setupLocationManager
{
self.myLocationManager = [[[CLLocationManager alloc] init] autorelease];
[myLocationManager startLocationUpdates];
}
But calling setupLocationManager in a thread prevented the callbacks. So my fix was to move the line
[self setupLocationManager];
out of the thread and back into appDidFinishLaunchingWithOptions
Actually you can run it from another thread as well.
From Apple documentation:
Configuration of your location manager object must always occur on a
thread with an active run loop, such as your application’s main
thread.
Just make sure your run loop is running on that thread, and the CLLocationManager events are dispatched.
More about run loop:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html
For iOS 8
1) I placed these lines right after I init'd the location manager.
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
2) I added NSLocationAlwaysUsageDescription to the plist and set it to a string and added a message.
3) In my target, I clicked on Capabilities tab, and then turned on Background Modes and checked "Location Updates" and "Uses Bluetooth LE accessories"
This worked for me
// check out this
//...CLLocationManager does n't call delegate method properly
//...after lot of R&D I'm using a watchdog method it calls "
https://stackoverflow.com/questions/7156920/didupdatetolocation-doesnt-gets-called-immediately/14605889#14605889
In my case it was because of my device was unable to determine location - while staying indoors GPS signal was unavailable and wi-fi was also disconnected so location manager just wasn't able to receive any location data and delegate was never called.
Once I've connected wi-fi it worked (I guess moving outdoors should also do the trick in that case, but sometimes it is not very convenient way :) )