Crash when calling completion handler for `UNUserNotificationCenter` - ios

I'm working on an app that, when receiving a silent push notification; will make two networking calls to get some data, and then use that data to create a local push notification.
This mostly works great in the foreground and the background; with the exception of some occasional crashes that I'm having a difficult time diagnosing.
This is my full implementation for the delegate method that gets called when the silent push notification arrives:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("Notification received!")
UNUserNotificationCenter.current().delegate = self
let id = updateNotificationID()
let payload = userInfo
guard let ship: String = payload["ship"] as? String else {
return
}
guard let node: String = payload["node"] as? String else {
return
}
guard let graph: String = payload["graph"] as? String else {
return
}
var groupName: String = ""
networkStore.scryForGroupInfo(ship: ship, graph: graph) { groupTitle in
if groupTitle == "" {
//one on one
} else {
//groupchat
groupName = groupTitle
}
networkStore.scryOnNotificationReceipt(ship: ship, node: node, graph: graph) { [self] messageString, author in
let content = UNMutableNotificationContent()
if groupName == "" {
//group chat
content.title = "New Message from \(author)"
let chatShipDict:[String: String] = ["ChatShip": author]
content.userInfo = chatShipDict
} else {
content.title = "\(author) posted in \(groupName)"
let chatShipDict:[String: String] = ["ChatShip": groupName]
content.userInfo = chatShipDict
}
//Don't show a notification for a chat that we're currently in
if airlockStore.selectedChannel != nil {
let author = "~"+author
if airlockStore.selectedChannel.channelShip == author || airlockStore.selectedChannel.channelName == groupName {
completionHandler(.noData)
return
}
} else {
//One on one chat
if groupName == "" {
let author = "~"+author
for channel in airlockStore.unPinnedChannelDataObjects {
if channel.channelShip == author {
notificationChannel = channel
}
}
} else {
//Group chat
for channel in airlockStore.unPinnedChannelDataObjects {
if channel.channelName == groupName {
notificationChannel = channel
}
}
}
}
content.body = messageString
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false)
let request = UNNotificationRequest(identifier: "notification.id.\(id)", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { Error in
print("Showing Notification")
completionHandler(.newData)
}
}
}
}
The crashes seem to occur at the completionHandler(.newData) line.
Here's my stack trace:
Thread 10 name:
Thread 10 Crashed:
0 libdispatch.dylib 0x00000001a0b147b8 dispatch_group_leave.cold.1 + 36 (semaphore.c:303)
1 libdispatch.dylib 0x00000001a0ae0668 dispatch_group_leave + 140 (semaphore.c:0)
2 Pocket 0x000000010464333c partial apply for closure #1 in closure #1 in closure #1 in AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:) + 136 (AppDelegate.swift:137)
3 Pocket 0x00000001046419ac thunk for #escaping #callee_guaranteed (#guaranteed Error?) -> () + 44 (<compiler-generated>:0)
4 libdispatch.dylib 0x00000001a0adda84 _dispatch_call_block_and_release + 32 (init.c:1466)
5 libdispatch.dylib 0x00000001a0adf81c _dispatch_client_callout + 20 (object.m:559)
6 libdispatch.dylib 0x00000001a0ae7004 _dispatch_lane_serial_drain + 620 (inline_internal.h:2557)
7 libdispatch.dylib 0x00000001a0ae7c34 _dispatch_lane_invoke + 456 (queue.c:3862)
8 libdispatch.dylib 0x00000001a0af24bc _dispatch_workloop_worker_thread + 764 (queue.c:6589)
9 libsystem_pthread.dylib 0x00000001ecc7e7a4 _pthread_wqthread + 276 (pthread.c:2437)
10 libsystem_pthread.dylib 0x00000001ecc8574c start_wqthread + 8

You say you are making two different network calls.
Are you sure you are not calling the completion handler twice sometimes? Make sure it is only called once.

Related

Firebase fetching causes crash for some users

When I try to fetch user data from Firebase a crash occurs for some users, I can't reproduce this crash myself but I do have the following crash log:
0 Ski Tracker 0x77bf0 closure #1 in HistoryPresenter.downloadHistory(completionHandler:) + 4340857840 (HistoryPresenter.swift:4340857840)
1 Ski Tracker 0x86c8 closure #1 in FetchFromDatabase.fetchUserHistoryFromDatabase(uid:completionHandler:) + 4340401864 (<compiler-generated>:4340401864)
2 Ski Tracker 0x8604 thunk for #escaping #callee_guaranteed (#guaranteed FIRDataSnapshot) -> () + 4340401668 (<compiler-generated>:4340401668)
3 FirebaseDatabase 0x1df28 __92-[FIRDatabaseQuery observeSingleEventOfType:andPreviousSiblingKeyWithBlock:withCancelBlock:]_block_invoke + 120
4 FirebaseDatabase 0xbf94 __43-[FChildEventRegistration fireEvent:queue:]_block_invoke.11 + 80
5 libdispatch.dylib 0x24b4 _dispatch_call_block_and_release + 32
6 libdispatch.dylib 0x3fdc _dispatch_client_callout + 20
7 libdispatch.dylib 0x127f4 _dispatch_main_queue_drain + 928
8 libdispatch.dylib 0x12444 _dispatch_main_queue_callback_4CF + 44
9 CoreFoundation 0x9a6f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
10 CoreFoundation 0x7c058 __CFRunLoopRun + 2036
11 CoreFoundation 0x80ed4 CFRunLoopRunSpecific + 612
12 GraphicsServices 0x1368 GSEventRunModal + 164
13 UIKitCore 0x3a23d0 -[UIApplication _run] + 888
14 UIKitCore 0x3a2034 UIApplicationMain + 340
15 libswiftUIKit.dylib 0x35308 UIApplicationMain(_:_:_:_:) + 104
16 Ski Tracker 0x7160 main + 4340396384 (FriendView.swift:4340396384)
17 ??? 0x1f6938960 (Missing)
If I understand the crash log correctly the code which is causing the crash is within the fetchUserHistoryFromDatabase function:
func fetchUserHistoryFromDatabase(uid : String, completionHandler: #escaping([String : Any]?) -> Void ) {
ref?.child("users").child(uid).child("runData").observeSingleEvent(of: .value, with: { snapshot in
guard let result = snapshot.value as? [String:Any] else {
print("Error no rundata")
completionHandler(nil)
return
}
completionHandler(result)
})
}
This function is called from downloadHistory where potential nil values are handled:
private func downloadHistory(completionHandler: #escaping () -> Void) {
if let id = Auth.auth().currentUser?.uid {
FetchFromDatabase().fetchUserHistoryFromDatabase(uid : id, completionHandler: { [weak self] dict in
if dict != nil {
for run in dict! {
self?.determineTimeStamp(run : run)
}
if !(self!.tempDict.isEmpty) {
let sortedDict = self?.tempDict.keys.sorted(by: { $0 > $1 } )
self?.convertDictToArray(sortedDict: sortedDict!)
}
}
completionHandler()
}
)}
}
Any help here is greatly appreciated.
Remove the force unwrapping from your code. Every ! is an invitation for a crash.
private func downloadHistory(completionHandler: #escaping () -> Void) {
if let id = Auth.auth().currentUser?.uid {
FetchFromDatabase().fetchUserHistoryFromDatabase(uid : id, completionHandler: { [weak self] dict in
guard let self = self else {
completion()
return
}
if let dict = dict {
for run in dict {
self.determineTimeStamp(run : run)
}
if !self.tempDict.isEmpty {
let sortedDict = self.tempDict.keys.sorted(by: { $0 > $1 } )
self.convertDictToArray(sortedDict: sortedDict)
}
}
completionHandler()
}
)}
}
I notice a self! there dangerous, because a user could leave the calling context of the function and since the closure has a capture list of weak self, it should return nil but you are forcing it
try this
private func downloadHistory(completionHandler: #escaping () -> Void) {
if let id = Auth.auth().currentUser?.uid {
FetchFromDatabase().fetchUserHistoryFromDatabase(uid : id, completionHandler: { [weak self] dict in
guard let self = self else { completionHandler()
return }
if let safeDict = dict {
for run in dict {
self.determineTimeStamp(run : run)
}
if (self.tempDict.isEmpty) {
let sortedDict = self.tempDict.keys.sorted(by: { $0 > $1 } )
self.convertDictToArray(sortedDict: sortedDict)
}
}
completionHandler()
}
)}
}

Crashed: com.apple.main-thread partial apply for closure #2

Crashes are reported into firebase console. Can anyone help me. i am sending data to server using Socket.
Here is crash description:
Crashed: com.apple.main-thread
0 AppName 0x10ef40 partial apply for closure #2 in sendDataRecursively() + 4329697088 (swift:4329697088)
1 AppName 0x23824 thunk for #escaping #callee_guaranteed () -> () + 4328732708 (<compiler-generated>:4328732708)
2 libdispatch.dylib 0x1e68 _dispatch_call_block_and_release + 32
3 libdispatch.dylib 0x3a2c _dispatch_client_callout + 20
4 libdispatch.dylib 0x11f48 _dispatch_main_queue_drain + 928
5 libdispatch.dylib 0x11b98 _dispatch_main_queue_callback_4CF + 44
6 CoreFoundation 0x522f0
CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
7 CoreFoundation 0xc1f4 __CFRunLoopRun + 2532
8 CoreFoundation 0x1f6b8 CFRunLoopRunSpecific + 600
9 GraphicsServices 0x1374 GSEventRunModal + 164
10 UIKitCore 0x513e88 -[UIApplication _run] + 1100
11 UIKitCore 0x2955ec UIApplicationMain + 364
12 AppName 0x48dac main + 17 (AppDelegate.swift:17)
13 ??? 0x1008edce4 (Missing)
Here is my function:
#objc func sendDataRecursively() {
let reachability = try! Reachability()
if reachability.connection != .unavailable {
DispatchQueue.global(qos: .userInitiated).async { //previous .bakground
if self.msgCnt == 127 {
self.msgCnt = 0
}
self.msgCnt += 1
self.sendRequest()
}
} else {
DispatchQueue.main.async {
self.previousStatusWhenDisconnect = self.motionDetectionLbl?.text ?? ""
self.appDelegate.statusLbl?.text = String(format: "%# %#", (self.appDelegate.statusLbl?.text)!, StartVCStringsEnglish.disConnectedString)
}
self.networkTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.checkNetworkRecursively), userInfo: nil, repeats: true)
}
}
Here is the my other function. i am sending data to my Socket function. i did't got the crash but its reported into firebase. Also in firebase has not much more information about the crash. its just show the function name only.
private func sendRequest() {
self.calculateMessageData()
var requestData: Data?
var txData = [UInt8()]
var crc: Int
if self.msgID == Int8(EnMessageType.basicSafetyMessage.rawValue) {
requestData = self.getBasicSafetyMessage()
} else {
requestData = self.getPersonalSafetyMessage()
}
crc = computeCRC(data: requestData!, length: requestData!.count)
// wrap data in 7E, do byte stuffing and add CRC
txData = []
txData.append(0x7E)
for ii in 0..<requestData!.count {
switch requestData![ii] {
case 0x7D:
txData.append(0x7D)
txData.append(0x5D)
break
case 0x7E:
txData.append(0x7D)
txData.append(0x5E)
break
default:
txData.append(requestData![ii])
break
}
}
txData.append((UInt8)(crc >> 8))
txData.append((UInt8)(crc & 0xFF))
txData.append(0x7E)
requestData = (Data)(txData)
if AppSingletonVariable.sharedInstance.isConnected == true { AppSingletonVariable.sharedInstance.mySocket.sendDataToServer(reqData: requestData!)
}
}
Thanks,
You can see from the crash description that there is issue in 2nd closure in sendDataRecursively() function:
DispatchQueue.main.async {
self.previousStatusWhenDisconnect = self.motionDetectionLbl?.text ?? ""
self.appDelegate.statusLbl?.text = String(format: "%# %#", (self.appDelegate.statusLbl?.text)!, StartVCStringsEnglish.disConnectedString)
}
self.networkTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.checkNetworkRecursively), userInfo: nil, repeats: true)
The issue is probably '!' in this expression:
(self.appDelegate.statusLbl?.text)!
If statusLbl is nil, this code crashes. As it was mentioned in comment, it's not safe to force unwrap optionals and this is the reason.
Replace your closure with this:
DispatchQueue.main.async {
self.previousStatusWhenDisconnect = self.motionDetectionLbl?.text ?? ""
if let text = self.appDelegate.statusLbl?.text {
self.appDelegate.statusLbl?.text = String(format: "%# %#", text, StartVCStringsEnglish.disConnectedString)
}
}
self.networkTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.checkNetworkRecursively), userInfo: nil, repeats: true)

iOS App Store app crashes during login (not in development)

So this may be because UserDefaults are getting reset after a period of time, maybe because I update the OS frequently, but a released version of my iOS app after a period of time will crash on my login screen, probably where I check for saved credentials (in UserDefaults). Reinstalling the app fixes the issue. Console returns a lot of :
Unsupported use of UIKit view-customization API off the main thread. -setAlignsToKeyboard: sent to <_UIAlertControllerView: 0x125b2d070; frame = (0 0; 414 896); layer = <CALayer: 0x283f652e0>>
And my system logs show an error on this thread:
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 4
Application Specific Information:
abort() called
Thread 4 name: Dispatch queue: com.apple.NSURLSession-delegate Thread
4 Crashed: 0 libsystem_kernel.dylib 0x00000001bfb4e414 0x1bfb26000 +
164884 1 libsystem_pthread.dylib 0x00000001dd6a8b50 0x1dd6a6000 +
11088 2 libsystem_c.dylib 0x000000019b027b74 0x19afb1000 + 486260 3
libc++abi.dylib 0x00000001a6d1acf8 0x1a6d07000 + 81144 4
libc++abi.dylib 0x00000001a6d0be4c 0x1a6d07000 + 20044 5
libobjc.A.dylib 0x00000001a6c14f64 0x1a6c0e000 + 28516 6
libc++abi.dylib 0x00000001a6d1a0e0 0x1a6d07000 + 78048 7
libc++abi.dylib 0x00000001a6d1a06c 0x1a6d07000 + 77932 8
libdispatch.dylib 0x00000001917eddc4 0x1917ea000 + 15812 9
libdispatch.dylib 0x00000001917f510c 0x1917ea000 + 45324 10
libdispatch.dylib 0x00000001917f5c90 0x1917ea000 + 48272 11
libdispatch.dylib 0x00000001917ffd78 0x1917ea000 + 89464 12
libsystem_pthread.dylib 0x00000001dd6a9814 0x1dd6a6000 + 14356 13
libsystem_pthread.dylib 0x00000001dd6b076c 0x1dd6a6000 + 42860
Here is some code that I use to check saved credentials. In the backend API I cannot see any login attempts. If it helps, I can see this viewcontroller for a split second right before it crashes. Not sure if that rules out viewdidload.
override func viewDidLoad() {
super.viewDidLoad()
addLoadingSpinner()
bLogIn.titleLabel?.font = UIFont.setToVoiceLight()
self.tfCustomerID.delegate = self
self.tfUsername.delegate = self
self.tfPassword.delegate = self
tfUsername.keyboardType = .default
tfPassword.textContentType = .password
setupUI()
if UserDefaults.standard.string(forKey: UserDefaultsKeys.session) != nil
&& UserDefaults.standard.string(forKey: UserDefaultsKeys.savedCred) == "True" {
login_session = UserDefaults.standard.string(forKey: UserDefaultsKeys.session)!
check_session()
}
else if UserDefaults.standard.string(forKey: UserDefaultsKeys.savedCred) == "True" &&
UserDefaults.standard.string(forKey: UserDefaultsKeys.usesBiometrics) == "True" {
promptTouchOrFaceID()
}
removeLoadingSpinner()
}
override func viewWillAppear(_ animated: Bool) {
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo:
UIInterfaceOrientation.portrait)
cbSave.isChecked = UserDefaults.standard.string(forKey: UserDefaultsKeys.savedCred) == "True"
addObservers()
}
func check_session() {
UserDefaults.standard.set(login_session, forKey: "session")
UserInfo.access_token = UserDefaults.standard.string(forKey: "session")!
var request = URLRequest(url: NSURL(string: checksession_url)! as URL)
request.httpMethod = .GET
request.addValues(...)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
//VERIFIED THAT NEVER GETTING TO API
DispatchQueue.main.async {
...
}
} else {
self.promptTouchOrFaceID()
UserDefaults.standard.set(nil, forKey: UserDefaultsKeys.session)
}
}
task.resume()
}
Here is my code for biometrics prompt:
func promptTouchOrFaceID() {
//create context for touch auth
let authenticationContext = LAContext()
var error: NSError?
authenticationContext.localizedFallbackTitle = ""
let biometricType = authenticationContext.biometricType
//check if the device has a fingerprint sensor, exit if not
guard authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
error: &error) else {
let title = "Error"
var message = ""
switch biometricType {
case .faceID:
message = "This device does not have a FaceID sensor or the sensor is not enabled."
case .touchID:
message = "This device does not have a TouchID sensor or the sensor is not enabled."
case .none:
message = "This device does not have any sensors to use TouchID or FaceID"
}
AlertService.showAlert(on: self, title: title, message: message)
UserDefaults.standard.set("False", forKey: UserDefaultsKeys.usesBiometrics)
removeLoadingSpinner()
return
}
authenticationContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Please use your fingerprint to authenticate.",
reply: { [unowned self] (success, error) -> Void in
if (success) {
//fingerprint recognized, set this possible and go to view controller
OperationQueue.main.addOperation({ () -> Void in
self.fillInUserDetails()
self.login_now(
username:self.tfUsername.text!,
password: self.userDefaults.string(forKey: UserDefaultsKeys.password)!,
customer: self.tfCustomerID.text!)
})
}
})
}
Just a wild shot, but do you have NSFaceIDUsageDescription key in your plist file. I remember having a problem like this a few months back.

Crashed: com.apple.main-thread EXC_BREAKPOINT 0x0000000100c5009c keyboard_arrow_up

I am new iOS development, I got this error from firebase crash analytics. Can anyone help me why this errors occurs?
Crashed: com.apple.main-thread
0 People Time Tracking 0x100c5009c closure #1 in closure #1 in SelectJobScreen.getPreviousStatus() (SelectJobScreen.swift:798)
1 People Time Tracking 0x100cb2648 thunk for #escaping #callee_guaranteed () -> () (<compiler-generated>)
2 libdispatch.dylib 0x1e6993a38 _dispatch_call_block_and_release + 24
3 libdispatch.dylib 0x1e69947d4 _dispatch_client_callout + 16
4 libdispatch.dylib 0x1e6942004 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1068
5 CoreFoundation 0x1e6ee4ec0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
6 CoreFoundation 0x1e6edfdf8 __CFRunLoopRun + 1924
7 CoreFoundation 0x1e6edf354 CFRunLoopRunSpecific + 436
8 GraphicsServices 0x1e90df79c GSEventRunModal + 104
9 UIKitCore 0x212cc5b68 UIApplicationMain + 212
10 People Time Tracking 0x100c1afcc main (TodoItem.swift:17)
11 libdyld.dylib 0x1e69a58e0 start + 4
I've tried figuring out what could cause this crash for a few days now, and haven't been able to reproduce it. I don't see any implicit unwraps or optionals here, but sessionId is a non-optional value in the session object if that matters.
I am using swift 4.1, and the crashes occur on on iOS devices running all the different flavours of iOS 10, 11, and 12. The app does support some builds of iOS 9, but none have been reported (although that may be irrelevant because the iOS 9 user base for the app is extremely small)
In Error log it's showing this function getPreviousStatus()
func getPreviousStatus() {
let connect = JsonManger()
let app = UIApplication.shared.delegate as! AppDelegate
let user:User = app.dataManager.gUser
if Reachability.isConnectedToNetwork() {
self.showHUD( msg: "Loading...." )
connect.getLogDetails(baseUrl: user.ClientWeb, email: user.EmailID, password: user.Password, brugerId: user.BrugerID, success: { (res) in
var indud = false
if ( res.object(forKey: "indud") != nil ){
indud = res.object(forKey: "indud") as! Bool
}
if indud {
var isTodo = false
if res.object(forKey: "isToDo") != nil {
isTodo = res.object(forKey: "isToDo") as! Bool
}
if isTodo {
var str = res.object(forKey: "JobId") as! String
let index = str.index(str.startIndex, offsetBy: 1)
str = str.substring(from: index)
let prjId = Int(str)!
let project = app.dataManager.gProject.getProject(id: prjId)
let todoId = res.object(forKey: "TodoId") as! String
let todo = app.dataManager.gTodo.getTodo(id: Int(todoId)!)
self.project = project
self.todoItem = todo
app.dataManager.isCheckedin = true
self.des = res.object(forKey: "JobDescription") as? String
let startTime = res.object(forKey: "Dato2") as! String
DispatchQueue.main.async {
let ud = UserDefaults.standard
ud.set(true, forKey: "isCheckedIn")
ud.set( 1, forKey:"type")
ud.set( self.project.ID!, forKey: "projectId" )
ud.set( self.todoItem.ID! , forKey: "todoId" )
// print(" todo data is : \(self.todoItem.ID!)")
ud.set( self.des, forKey: "des")
ud.set( startTime,forKey: "startTime")
ud.set( startTime, forKey: "checkInTime" )
ud.synchronize()
self.hideHUD()
self.performSegue(withIdentifier: "goStartTodoFromSelect", sender: nil )
}
} else {
var jobId = res.object(forKey: "JobId") as! String
jobId = jobId.replacingOccurrences(of: "P", with: "")
self.des = res.object(forKey: "JobDescription") as? String
let jobCode = app.dataManager.gJobCode.getJobCode(id: Int(jobId)! )
self.jobCodeItem = jobCode
// let chekinTime = res.object(forKey: "Dato2") as! String
let startTime = "2019-05-15T19:45:00"
DispatchQueue.main.async {
app.dataManager.isCheckedin = true
let ud = UserDefaults.standard
ud.set(true, forKey: "isCheckedIn")
ud.set( 0, forKey:"type")
ud.set( jobId, forKey: "jobId" )
ud.set( startTime,forKey: "startTime")
ud.set( startTime, forKey: "checkInTime" )
if res.object(forKey: "JobDescription") != nil {
self.des = res.object(forKey: "JobDescription") as? String
ud.set( self.des, forKey: "des")
}
ud.synchronize()
DispatchQueue.main.async {
self.hideHUD()
self.performSegue(withIdentifier: "goStartJob", sender: nil )
}
}
}
} else {
DispatchQueue.main.async {
self.hideHUD()
// self.popToRoot()
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: SelectJobScreen.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
}
}
}) { (error) in
DispatchQueue.main.async {
self.hideHUD()
// self.popToRoot()
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: SelectJobScreen.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
}
}
} else {
print("Record Not Found")
}
}
Inside of that getPreviousStatus() functions getting null values , check it once using debugging
DispatchQueue.main.async {
# mainly in this thread getting error check it once
let ud = UserDefaults.standard
ud.set(true, forKey: "isCheckedIn")
ud.set( 1, forKey:"type")
ud.set( self.project.ID!, forKey: "projectId" )
ud.set( self.todoItem.ID! , forKey: "todoId" )
// print(" todo data is : \(self.todoItem.ID!)")
ud.set( self.des, forKey: "des")
ud.set( startTime,forKey: "startTime")
ud.set( startTime, forKey: "checkInTime" )
ud.synchronize()
self.hideHUD()
self.performSegue(withIdentifier: "goStartTodoFromSelect", sender: nil )
}

Serious Application Core Data Error Swift3

I am trying to get data from multiple apis and saving it to my coredata database. Earlier it comes once in ten times. but now i am getting it every time.
I have created a DispatchGroup and trying to hit api one by one. Below is my code.
let group = DispatchGroup()
group.enter()
SharedFunctions.getCourseSessions {
print("Course Session Done")
group.leave()
}
group.enter()
SharedFunctions.getCourseContent {
print("Course Content Done")
group.leave()
}
group.enter()
SharedFunctions.getCourseQuiz {
print("Course Quiz Done")
group.leave()
}
group.notify(queue: DispatchQueue.global(qos: .background)) {
print("All async calls were run!")
DispatchQueue.main.async {
ACProgressHUD.shared.hideHUD()
completrion()
}
}
Below is my fetching and saving data from api
class func getCourseSessions(completion: #escaping () -> ()) {
let param = "module=getCourseSessions&userid=\(User.uId)&Akey=\(User.akey)&schedule_course_id=\(User.scheduleCourseId)"
SharedFunctions.callWebServices(url: URLS.Base_URL, methodName: "POST", parameters: param, istoken: false, tokenval: "", completion: { (jsonDict) in
print(jsonDict)
DispatchQueue.main.async {
if ((jsonDict.value(forKey: "message") as! NSDictionary).value(forKey: "success") as! String) == "true" {
SharedGlobalVariables.arrayCourseSessions = (((jsonDict.value(forKey: "message") as AnyObject).value(forKey: "data") as AnyObject).value(forKey: "result")) as! NSMutableArray
print(SharedGlobalVariables.arrayCourseSessions.count)
// DispatchQueue.main.async {
SharedGlobalVariables.LoginBool = true
// get a reference to the app delegate
if #available(iOS 10.0, *) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
print(SharedGlobalVariables.arrayCourseSessions.count)
for j in 0...SharedGlobalVariables.arrayCourseSessions.count - 1 {
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Course_Sessions", in: managedContext)
let courseSessionsScreen = Course_Sessions(entity: entity!, insertInto: managedContext)
if let arrData = SharedGlobalVariables.arrayCourseSessions[j] as? NSDictionary {
if let courseId = arrData.value(forKey: "course_id") as? Int16 {
courseSessionsScreen.course_id = courseId
}
if let userId = arrData.value(forKey: "user_id") as? Int16 {
courseSessionsScreen.user_id = userId
}
if let enableNextScreenSequence = arrData.value(forKey: "enable_nextscreen_sequence") as? Int16 {
courseSessionsScreen.enable_nextscreen_sequence = enableNextScreenSequence
}
}
do {
try managedContext.save()
// getCourseSessionProperties()
} catch let error as NSError {
print(error)
}
}
} else {
// Fallback on earlier versions
}
//}
}
completion()
}
})
}
There is no perticular place to crash app crash. it crash any where like above methode i am passing all apis.
Getting This error:
Error Domain=NSCocoaErrorDomain Code=132001 "(null)" UserInfo={message=attempt to recursively call -save: on the context aborted, stack trace=(
0 CoreData 0x0000000111ff3892 -[NSManagedObjectContext save:] + 306
1 Tuneem 0x000000010f64046c _TFFFZFC6Tuneem15SharedFunctions26getCourseSessionPropertiesFT10completionFT_T__T_U_FCSo12NSDictionaryT_U_FT_T_U_FT_T_ + 60
2 Tuneem 0x000000010f629197 _TTRXFo___XFdCb___ + 39
3 CoreData 0x000000011200cb52 developerSubmittedBlockToNSManagedObjectContextPerform + 178
4 libdispatch.dylib 0x000000011bf0205c _dispatch_client_callout + 8
5 libdispatch.dylib 0x000000011bee094f _dispatch_queue_serial_drain + 221
6 libdispatch.dylib 0x000000011bee1669 _dispatch_queue_invoke + 1084
7 libdispatch.dylib 0x000000011bee1b32 _dispatch_queue_override_invoke + 654
8 libdispatch.dylib 0x000000011bee3ec4 _dispatch_root_queue_drain + 634
9 libdispatch.dylib 0x000000011bee3bef _dispatch_worker_thread3 + 123
10 libsystem_pthread.dylib 0x000000011c299712 _pthread_wqthread + 1299
11 libsystem_pthread.dylib 0x000000011c2991ed start_wqthread + 13
)}
Error Domain=NSCocoaErrorDomain Code=132001 "(null)" UserInfo=. {message=attempt to recursively call -save: on the context aborted, stack trace=(
0 CoreData 0x0000000111ff3892 -[NSManagedObjectContext save:] + 306
1 Tuneem 0x000000010f64046c _TFFFZFC6Tuneem15SharedFunctions26getCourseSessionPropertiesFT10completionFT_T__T_U_FCSo12NSDictionaryT_U_FT_T_U_FT_T_ + 60
2 Tuneem 0x000000010f629197 _TTRXFo___XFdCb___ + 39
3 CoreData 0x000000011200cb52 developerSubmittedBlockToNSManagedObjectContextPerform + 178
4 libdispatch.dylib 0x000000011bf0205c _dispatch_client_callout + 8
5 libdispatch.dylib 0x000000011bee094f _dispatch_queue_serial_drain + 221
6 libdispatch.dylib 0x000000011bee1669 _dispatch_queue_invoke + 1084
7 libdispatch.dylib 0x000000011bee1b32 _dispatch_queue_override_invoke + 654
8 libdispatch.dylib 0x000000011bee3ec4 _dispatch_root_queue_drain + 634
9 libdispatch.dylib 0x000000011bee3bef _dispatch_worker_thread3 + 123
10 libsystem_pthread.dylib 0x000000011c299712 _pthread_wqthread + 1299
11 libsystem_pthread.dylib 0x000000011c2991ed start_wqthread + 13
)}
Trying to solve it from last couple of days getting no idea, any help will be appreciate.

Resources