I'm struggling with the following scenario and could use some different perspectives to shed some light on me:
I have a self.backstack which is an array of sections to go "back" to when you hit the back button. I'm getting an EXC_BAD_ACCESS when the back button is hit in a particular situation, but I'm not sure which object the code is mad about because everything seems there.
If you look on the bottom left of the image you'll see that self, backStack, and userInfo are all there. Not only that but their respective prints on are logged in the bottom right.
Any thoughts on what the problem might be? Thanks.
I suspect you have an observer of the notification which has been deallocated before it unregistered for the notifications.
Notifications are synchronous, which means that on the line you are crashing on, it is trying to run all of the observer callbacks. Check everywhere you are registering for these, and make sure the objects are either retained elsewhere, or are being properly unregistered (removeObserver iirc) when they are released.
Related
First of all I'd like to say sorry in case my question is dummy, I'm really new to iOS and what to understand how thing are going on. Imagine such a situation - user taps on home button and the app starts to collapse, but immediately after taping on home button user taped on some UI element. So, I'm wondering how the iOS will handle this? I tried to do some tests using breakpoints, but since it just test I can't be 100% sure. It seems that if the UI interaction event will happen before the system will call willResignActive then the event will be fully processed and if the system will call willResignActive first, then the even will be discarded and won't be handled at all. Is this correct, or I missed something? Thanks
First, why do you want to use this in your app? If a user presses a button exactly in this time, it's okay that the action is not handled.
The only thing you have to keep track of is that whenever the button gets pressed and let's say you store a file without a completion handler it could be that you present an alert which is saying that everything went well but you actually not saved the file because the user left the app in this time.
But since you're never doing critical actions without completion handlers, in my opinion, there's no need to make sure that this doesn't happen.
If I got you wrong, just comment!
I was searching crash logs of my app, and I've seen this (which occured quiet a few times, not just once or twice):
As seen above, notification center posted a memory warning notification, and it was somehow forwarded to a CALayer. I've also seen instances of didReceiveMemoryWarning: messages sent to other deallocated objects such as UIImageViews or even private _UINavigationBarBackground objects, when zombies were enabled on my debugger, too, crashing my app. Why would this happen?
NSNotificationCenter only keeps weak references to observers.
What's probably happening is that you have one ore more objects somewhere that register for UIApplicationDidReceiveMemoryWarningNotification, but which never unregister (thats a bug). Since NSNotificationCenter only keeps weak references to those objects it doesn't notice when they are dealloc'd and their memory is reused for other objects such as CALayer etc, which do not implement a method named didReceiveMemoryWarning.
This seems like a memory management issue. Typically, the memory warning would be sent to a currently-existing UIViewController, which lives at some hypothetical location X in memory.
But at runtime, instead of finding your UIViewController at location X as expected, it found some other object, like a random CALayer or UIImageView, which does not know how to respond to didReceiveMemoryWarning:. This results in the crash you're seeing.
Does your project use ARC? Enable it if its not already, that should reduce the frequency of these errors. If you're using manual retain/release, it is likely there is some error in your implementation.
If you have any code that does funny things with memory, or any code that does hacky things with view controller transitions, those are possible culprits, I'd post that code.
Also, try manually sending a memory warning to your app as soon as it is done starting up, to see if the issue manifests immediately, or if the app needs to run for a while before it occurs.
Boy, this is frustrating.
I sent in my app to Apple after months and months of development. It was quickly rejected due to the fact that they said it was unresponsive at the home screen. Here is the screenshot they sent me:
Now, when I build the exact archive of the app that I sent them, I have no such issues:
The buttons were created in the storyboard file and were IBOutlets, but the highscore label that you see was created programmatically. Is it possible that the storyboard file didn't upload properly? I have already messaged them in the resolution center about it and tried to submit it again to see if it would work next time, but I was wondering if anyone knew anything about this issue.
From above screenshot, I've understand something that issue related with network error. See, they were tested with flight mode. According to apple guidelines, it should be go on in home screen without much more delay. At least show an alert for this issue. Just test with this scenario, you will get this.
When they said it was unresponsive, it may be due to the fact that its stuck for certain reasons, check if you make any API call at the viewLoad method, also, if the UI may turn unresponsive incase you are performing some heavy operation on the main thread, try using a background thread of these operations
It's been an extremely long time, but I thought I'd say what was wrong in case anyone comes across this in the future. Basically, I had created the buttons in Interface Builder but was re-instantiating them in viewDidLoad of my view controller. Since IBOutlets are weak properties, they were thus being released. Why that wasn't happening when I ran it on my computer, I have no idea. Still puzzles me to this day.
I'm slowly working on my first simple timer app, which is starting to slowly come to life. At the moment I've done no saving of data for when my app enters the background, for the moment whilst writing my app it is always staying loaded during my testing, even if its in the background for a small time. All this is being done on the simulator.
My problem is that I have a Table View Controller with an NSInteger index property
#property NSInteger index;
that I use to manage the slow iteration step by step over an NSArray over time, by calling a doWork method.
Initial setup of my TVC and this property is performed as the view is prepared for segue from another view. More work is done on this property and other properties whenever my app receives local notifications or upon observing UIApplicationWillEnterForegroundNotifications.
All accessing of this property I've added debug logging around and I'm just confused with what I'm seeing
PrepareForSegue
# 19:38:29:058 - calls a method doWork which increments my property from -1 to 0, and sets a local notification. Logs show self=0x10bb661f0
I press the home button to put my app in the background for ~10 secs
The local notification fires and I tap the banner to bring my app back to the focus
My TVC's awakeFromNib function sets up a notification observer
as follows
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note) {
[self doWork];
}];
This notification fires twice! (for some reason?) each time causing my doWork method to be called
# 19:38:45:832 - doWork immediately shows my property is now back to -1 not the 0 it was set to before being backgrounded, it is incremented again to 0. Also it shows self as different at self=0x10974bbd0, a value it remains at now whilst the app is foregrounded.
# 19:38:45:836 - doWork is called again from this 2nd notification call, my property is correctly now still 0 from the last call, it is incremented again to 1.
after that my app delegate also gets it's didReceiveLocalNotification method called, which will also end up calling the same doWork method via another block in a Notification Center observer setup the same as the one detailed above.
# 19:38:45:857 - doWork is called and again the property has gone from the 1 that was set, back to 0... and is again incremented back to 1.
I just can't understand what's going on. Most of the properties in my TVC are still presumably fine as the rest of my logic showing the TVC contents continues to work fine. Why is my NSInteger getting mangled so?
I thought perhaps there could be some issues with threading and the local notification handling occurring perhaps simultaneously, I hoped that adding the mainQueue would help with this, I'd previously got this set to nil. Sadly it didn't make any difference.
I wonder why self changes after being backgrounded for only a short amount of time. Naively I presumed that as everything seemed to be working on coming back to the foreground (the view still displayed, with all its data seemingly intact aside from this NSInteger property) that the self ptr and object would be the same. It's not too much to imagine that perhaps its been relocated by the OS somehow, but still this shouldn't have caused the property to change.
I'm using cocoa lumberjack for logging, and I've turned off ASYNC logging as follows
#define LOG_ASYNC_ENABLED NO
Which should at least mean that log calls block till they've logged. I could appreciate that if i did have some threading issues perhaps the logging order would be slightly in doubt. But for the initial corruption of the property described above after the app enters the background there is ~10 seconds from when I write 0 to the property, and later read -1 back out of it. This is clearly not a threading timing issue at that point.
Why am I notified about entering the foreground twice? If my properties were left where I set them it wouldn't matter much, but still strikes me as a little odd.
Is there a problem with my using self within this block, I've seen that sometimes you may want to use a weak self pointers for these blocks, but I've seen examples where self is used directly as well.
Any help on understanding and hopefully fixing this would be really appreciated. I'm a little stuck and can't see what I've done wrong!
Cheers
So the answer to my problem as figured out by Woofbeans and Phillip Mills is that my awakeFromNib was being called each time i entered this TVC, and also I was failing to removeObserver on these notifications causing the stale undisplayed TVCs to stay around indefinitely. I'd not realised this key part of my repro of the problem.
Go into the TVC, come out, go back in and then you would have a duplicate of alerts in the app being caused by the fact that the original TVC was still around, being held onto by the strong reference to self within my own blocks.
I'm going to refactor this doWork functionality into my model so that it can persist and be handled better, independently of whatever view happens to be being displayed.
I also changed my block code to use a weakself pointer within the block, to hopefully stop that block from causing any object to persist purely because of the block being left behind.
Cheers everyone!
I have an app where on start it checks the user's position and then get the weather for that spot. Mainly wind direction and speed.
It does the normal check to see it it has Intenet connection, but I found that if there is connection, but very slow the app freezes on launch screen (doing the check on startup).
I have a class that does this, which is called at startup after which a home screen is loaded.looking around, GCD seems the right way to go, but can I get the answer to be displayed in a label in the home screen when it is finished with getting the data? Main tread would have left, or rather bypassed that class and have arrived at the main screen.
Would I need to maybe use something like Notification Centre to help the label updating and re-load?
Thanks for any thoughts or code snippets.
Jorgen
PS. I am trying to keep the app iOS 5.1 to keep old iPads happy.
GCD seems the right way to go, but can I get the answer to be displayed in a label in the home screen when it is finished with getting the data? Main tread would have left, or rather bypassed that class and have arrived at the main screen. Would I need to maybe use something like Notification Centre to help the label updating and re-load?
Yes, I think you're on a very good track here. Let's keep the two issues separate, though:
After doing your background work, still in GCD, you're going to come back onto the main thread because you now want to update the interface. That's easy and straightforward.
If you have a communication problem, a notification can be an excellent solution. You can broadcast the need to update that label, and if the correct view controller exists and is listening, it will get that information.
Having said that, though, you should think about your architecture, since there may be a better way than a notification. Once you are back on the main thread, why are you not in a place where you have a way to know whether the correct view controller exist and to talk to it directly. I'm not saying the notification is bad/wrong! I've used this solution myself, and a notification is quite a standard way to come back from, say, an NSOperation. I'm just saying, give it a little thought.