When I save a single datum to the iCloud, it works fine and when I need to save number of data to iCloud, I put the same code steps to save inside the for loop.
When I tried saving number of data to iCloud, the following signal is received and the app is hanging infinitely. The signal received area is in the below image.
and the crash area points at
How I can debug this crash? Can someone help me with explantion ASAP
The documentation for that method says, "Important: Do not call this method from your app’s main thread." The warning goes on to say that doing so may cause a deadlock. It sounds as if that's the condition you have.
Related
I'm using HealthKit on my app to read user's health data and show them the data in the appropriate place on my app. For some production users(Major impact is on an iPhone X user), It's getting crashed while retrieving the health data using HealthKit(on Main Thread). But I'm not able to reproduce it.
Here is my code where I start taking the user permissions and read the health data.
Here is the crash information from fabric.
As per the crash info, it crashed while reading the DOB from HealthKit and I believe that there is no issue in getting DOB and I think the crash is happening because I'm reading health data on Main Thread and it might encounter with some multithreading issues. Tried with multiple devices, and I'm not able to reproduce the issue.
1) Any points on why reading the data from HealthKit on Main Thread is causing the crash?
2) Is the completion block I'm running on Main Thread expired/deallocated and might cause the crash?
Thanks.
HKObserverQuery has the following method that supports receiving updates in the background:
- initWithSampleType:predicate:updateHandler:
The updateHandler has a completionHandler which has the following documentation:
This block is passed to the update handler. You must call this block
as soon as you are done processing the incoming data. Calling this
block tells HealthKit that you have successfully received the
background data. If you do not call this block, HealthKit continues to
attempt to launch your app using a backoff algorithm. If your app
fails to respond three times, HealthKit assumes that your app cannot
receive data, and stops sending you background updates.
From looking at other posts it seems like there's a lot of confusion revolving around this handler. Below are some questions that I have about it:
When should the handler be called? If called too late, then HK might think that the app never received the query update causing you to hit the background update 3-strikes back-off algorithm. The documentation states that it should be called after handling other queries. Depending on how long it would take to run those queries, it sounds like you could get dangerously close to hitting the background update strikes.
Why is this needed? Shouldn't the system know that the app has been launched and has received the background update? When using CoreBluetooth in the background it just wakes your app up in the background for 10 seconds. No need to call any handler or deal with the background update 3-strikes.
If you hit the background update 3-strikes and HK stops sending updates is that permanent? Does HK ever start sending the background updates again? What if there's a bug that prevented the handler to be called and now you've fixed it. Is the app stuck never receiving the updates? Or will it reset when the app is re-launched or updated?
Does HK keep your app running in the background until the handler is called? Is that part of its purpose or just a side effect? If it's part of its purpose how long can we run before needing to stop (and hit the first background update strike)?
When should the handler be called?
Call it after you are done your job. Your code should not do complex operations. The app is in the background and the user does not see what's changed. You can just set a "flag" that data is updated and do complex operations after the user launched the app. If your decision about either notifies the user or not based on complex operations, then try to refactor code so that all necessary data is pre-calculated (e.g. in UserDefaults) and extra data is simply fetched with that data. So, 1-2 seconds is enough for your calculation.
Why is this needed?
All such handlers have completion closures. They are needed for iOS to know if your app works fine. If your app will eat too much CPU time, then iOS could become slow. Hence, Apple wants to be sure that iOS works fine despite bad apps.
If you hit the background update 3-strikes and HK stops sending updates is that permanent?
No.
Does HK ever start sending the background updates again?
Yes. But it depends on many factors. It may try to call your app again in 1-2 days. If nothing changes it will call it rarely.
Does HK keep your app running in the background until the handler is called?
This is unknown. It depends on many factors. Probably if iPhone is charging it will allow running your app longer just to estimate if the completion handle is called or not. If your iPhone is not charging and closed to 0% battery, then more likely iOS will kill your app. So, you should not do any job after you called the completion handler. And try to keep it simple.
Recommendations
You should process new data as quickly as possible. If you need to fetch a lot of data, then try to optimize this and pre-calculate it when the app is in foreground, then save somewhere (UserDefault), and use new data with cached data to make a decision (e.g. notify user about something; I believe you need background updates exactly for that).
1-2 seconds or less is a good time for background updates.
I have a rather strange behaviour in an app that is monitoring some CLCircularRegion objects.
What the app is expected to do
Whenever a region is entered or left, an entry in a quite simple UIManagedDocument (not located in the iCloud) will be updated or created. Furthermore, a NSLocalNotification will be fired telling me which region has been affected and how long the user stayd within the region.
What really happens
The Notifications are fired as expected, so the delegate methods are fired. Even the duration is calculated correctly. BUT, whenever the app was in background for a longer time - what means about an hour or more - there are no objects updated or created in the UIManagedDocument.
This behaviour is hard to debug, because I cannot reproduce it with the debugger attached or in Simulator, just on my iPhone 5S running iOS 8.1.3.
What I already tried out
Even if the UIManagedDocument handles context saving by itself, I tried to call the context saving directly from the location managers delegate method. Without any success.
Turning on the location update background capability lead the app to be rejected from the app store, because there is no need to do background location updates when working with region monitoring.
Question
Does anyone out there face similar problems or knows how to do the trick?
thank you in advance,
Peter
Are you aware that the iOS app gets awoken just for a couple of seconds after entering a region in background ? After that it stops execution and gets suspended.
Maybe you should try putting your UIManagedDocument operation in a backgroundTask. Please read Executing Finite-Length Tasks in:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Likewise that have functions in Objective-C to know when the screen will Appear, or When the User exit the app, or receive memory warning, I believe there is a way to know when the device will give crash.
If this function exists, I could create an alert will notify the user that the application has an error and the logs would be sent to my email, I wonder if this Possibility exists?.
Grateful.
like every POSIX process, iOS apps receive signals when they're crashing. thats how test flight works.
a) for exceptions use the function NSSetUncaughtExceptionHandler
b) for a signal handler (other crashes then exception) use signal
I won't write all the code here but for further info Ill refer to:
http://www.cocoawithlove.com/2010/05/handling-unhandled-exceptions-and.html
BUT
I would just try to avoid crashing because a handler often isn't really useful and it can very well be tricky to implement a signal handler because everything CAN be in a corrupt state. For example it may well corrupt your CoreData database or user defaults.
Don't ship it I'd say :)
I added a managedObjectContext save to my applicationDidReceiveMemoryWarning method in the app delegate. The app seems to crash on some devices when I receive a memory warning now.
It seems that the save pushes the app over the memory limit, as it is already low.
The reason I have this save in that method is to catch anything that may not have been saved during normal app operation.
Can someone tell me if this is bad practice?
Thanks.