Unknown cause of crash, Xcode points to unknown function: Array._getElement(_:wasNativeTypeChecked:matchingSubscriptCheck:) + 12 (AppDelegate.swift:0) - swift

I am investigating a crash reported through Xcode crash logs for my app that's live on the app store. In Xcode it points to line #5 with that has the line Array.getElement(:wasNativeTypeChecked:matchingSubscriptCheck:) + 12 (AppDelegate.swift:0). I can't find any information on this function. Because of the lines around it, I have investigated the App Delegate, but nothing is popping out to me as an issue. I am at a loss with how to dive into solving this bug. The main thing I gather is that it occurs when the app receives a remote notification.
Any thoughts on how to investigate this issue or what could be happening would be appreciated.
Here is the crash log
<!-- language: none -->
Incident Identifier: 3406EE83-04DB-4B61-B2E5-758F04A63614
Hardware Model: iPhone13,4
Process: FitSW [5443]
Path: /private/var/containers/Bundle/Application/4ECB1953-2547-4511-BA9B-D1BDFA9B8155/FitSW.app/FitSW
Identifier: FitSW
Version: 3.97 (1)
AppStoreTools: 14C17
AppVariant: 1:iPhone13,4:15
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: FitSW [1058]
Date/Time: 2023-01-13 19:13:15.6975 +0300
Launch Time: 2023-01-13 18:36:32.1730 +0300
OS Version: iPhone OS 15.1.1 (19B81)
Release Type: User
Baseband Version: 2.11.04
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x18112504c __exceptionPreprocess + 220 (NSException.m:200)
1 libobjc.A.dylib 0x199799f54 objc_exception_throw + 60 (objc-exception.mm:565)
2 CoreFoundation 0x1811acc98 -[__NSArray0 objectAtIndex:] + 112 (CFArray.c:103)
3 libswiftCore.dylib 0x185ada7ac _CocoaArrayWrapper.subscript.getter + 36 (CocoaArray.swift:59)
4 FitSW 0x102d545b4 specialized _ArrayBuffer._getElementSlowPath(_:) + 208
5 FitSW 0x102b451d8 specialized Array._getElement(_:wasNativeTypeChecked:matchingSubscriptCheck:) + 12 (AppDelegate.swift:0)
6 FitSW 0x102b451d8 specialized Array.subscript.getter + 12 (AppDelegate.swift:210)
7 FitSW 0x102b451d8 specialized AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:) + 4840
8 FitSW 0x102b428d8 specialized AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:) + 16 (<compiler-generated>:0)
9 FitSW 0x102b428d8 #objc AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:) + 144
10 GoogleUtilities 0x104b2f504 -[GULAppDelegateSwizzler application:donor_didReceiveRemoteNotification:fetchCompletionHandler:] + 432 (GULAppDelegateSwizzler.m:915)
11 UIKitCore 0x183772464 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:] + 8016 (UIApplication.m:10900)
12 UIKitCore 0x183712d50 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 496 (UIScene.m:1492)
13 UIKitCore 0x183756524 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 288 (UIScene.m:1774)
14 UIKitCore 0x1836e0370 -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] + 492 (UIApplicationSceneClientAgent.m:80)
15 FrontBoardServices 0x192c00100 -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] + 528 (FBSScene.m:549)
16 FrontBoardServices 0x192c18d4c __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 + 152 (FBSWorkspaceScenesClient.m:581)
17 FrontBoardServices 0x192bfd6b4 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 240 (FBSWorkspace.m:352)
18 FrontBoardServices 0x192c03b10 __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke + 396 (FBSWorkspaceScenesClient.m:580)
19 libdispatch.dylib 0x180d97660 _dispatch_client_callout + 20 (object.m:560)
20 libdispatch.dylib 0x180d9b118 _dispatch_block_invoke_direct + 264 (queue.c:489)
21 FrontBoardServices 0x192bfef94 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 48 (FBSSerialQueue.m:157)
22 FrontBoardServices 0x192bfe3d4 -[FBSSerialQueue _targetQueue_performNextIfPossible] + 220 (FBSSerialQueue.m:181)
23 FrontBoardServices 0x192c029e4 -[FBSSerialQueue _performNextFromRunLoopSource] + 28 (FBSSerialQueue.m:194)
24 CoreFoundation 0x181147020 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 (CFRunLoop.c:1972)
25 CoreFoundation 0x181157ce0 __CFRunLoopDoSource0 + 208 (CFRunLoop.c:2016)
26 CoreFoundation 0x181091fe8 __CFRunLoopDoSources0 + 268 (CFRunLoop.c:2053)
27 CoreFoundation 0x1810977f4 __CFRunLoopRun + 820 (CFRunLoop.c:2951)
28 CoreFoundation 0x1810ab3b8 CFRunLoopRunSpecific + 600 (CFRunLoop.c:3268)
29 GraphicsServices 0x19ca3b38c GSEventRunModal + 164 (GSEvent.c:2200)
30 UIKitCore 0x183a4b6a8 -[UIApplication _run] + 1100 (UIApplication.m:3493)
31 UIKitCore 0x1837ca7f4 UIApplicationMain + 2092 (UIApplication.m:5046)
32 FitSW 0x1025a0afc main + 68 (AppDelegate.swift:22)
33 dyld 0x10348da24 start + 520 (dyldMain.cpp:876)
Thread 0 name:
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001b80ca964 __pthread_kill + 8 (:-1)
1 libsystem_pthread.dylib 0x00000001f1cb4378 pthread_kill + 268 (pthread.c:1610)
2 libsystem_c.dylib 0x000000018bf62f50 abort + 164 (abort.c:118)
3 libc++abi.dylib 0x00000001998a1bc4 abort_message + 132 (abort_message.cpp:78)
4 libc++abi.dylib 0x0000000199892fd8 demangling_terminate_handler() + 332 (cxa_default_handlers.cpp:71)
5 libobjc.A.dylib 0x00000001997a0064 _objc_terminate() + 144 (objc-exception.mm:701)
6 libc++abi.dylib 0x00000001998a0f58 std::__terminate(void (*)()) + 20 (cxa_handlers.cpp:59)
7 libc++abi.dylib 0x00000001998a0ef4 std::terminate() + 64 (cxa_handlers.cpp:88)
8 libdispatch.dylib 0x0000000180d97674 _dispatch_client_callout + 40 (object.m:563)
9 libdispatch.dylib 0x0000000180d9b118 _dispatch_block_invoke_direct + 264 (queue.c:489)
10 FrontBoardServices 0x0000000192bfef94 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 48 (FBSSerialQueue.m:157)
11 FrontBoardServices 0x0000000192bfe3d4 -[FBSSerialQueue _targetQueue_performNextIfPossible] + 220 (FBSSerialQueue.m:181)
12 FrontBoardServices 0x0000000192c029e4 -[FBSSerialQueue _performNextFromRunLoopSource] + 28 (FBSSerialQueue.m:194)
13 CoreFoundation 0x0000000181147020 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 (CFRunLoop.c:1972)
14 CoreFoundation 0x0000000181157ce0 __CFRunLoopDoSource0 + 208 (CFRunLoop.c:2016)
15 CoreFoundation 0x0000000181091fe8 __CFRunLoopDoSources0 + 268 (CFRunLoop.c:2053)
16 CoreFoundation 0x00000001810977f4 __CFRunLoopRun + 820 (CFRunLoop.c:2951)
17 CoreFoundation 0x00000001810ab3b8 CFRunLoopRunSpecific + 600 (CFRunLoop.c:3268)
18 GraphicsServices 0x000000019ca3b38c GSEventRunModal + 164 (GSEvent.c:2200)
19 UIKitCore 0x0000000183a4b6a8 -[UIApplication _run] + 1100 (UIApplication.m:3493)
20 UIKitCore 0x00000001837ca7f4 UIApplicationMain + 2092 (UIApplication.m:5046)
21 FitSW 0x00000001025a0afc main + 68 (AppDelegate.swift:22)
22 dyld 0x000000010348da24 start + 520 (dyldMain.cpp:876)
Here is the function in question
Line 6 on the crash log highlights the line that follows the MARK
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo["google.c.a.e"] {
print("Message ID: \(messageID)")
}
if let newMessageFlag = userInfo["newMessageFlag"] as? String {
let newMessageFlagInt = (Int(newMessageFlag) ?? 0)
UserDefaults.standard.set(newMessageFlag, forKey: "newMessageFlag")
var newNotificationsInt = 0
if let newNotifications = UserDefaults.standard.value(forKey: "newNotificationFlag") as? String {
newNotificationsInt = Int(newNotifications) ?? 0
}
UIApplication.shared.applicationIconBadgeNumber = newMessageFlagInt + newNotificationsInt
// guard let tabBarController = window?.rootViewController as? UITabBarController else { return }
let applicationState = UIApplication.shared.applicationState
if applicationState != .active {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
guard let tabBarController = self.window?.rootViewController as? MainStartingTabbarViewController else { return }
let navigationController = tabBarController.viewControllers![4] as? UINavigationController // Regardless of the other custom app versions & the user type, the more menu will be the fifth tab
navigationController?.tabBarItem.badgeValue = String(newMessageFlagInt + newNotificationsInt)
var moreTab = navigationController?.viewControllers[0] as? MoreMenuTableViewController
moreTab?.messagesFlagInt = newMessageFlagInt
tabBarController.selectedViewController = tabBarController.viewControllers![4]
let numberOfTabs = tabBarController.viewControllers
let isGroup = userInfo["is_private"] as? String == "0"
let roomIDInt = Int(userInfo["room_id"] as? String ?? "") ?? 0
moreTab?.openMessages(didSelectGroup: isGroup, isShared: false, roomID: roomIDInt)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
}
}
else {
guard let tabBarController = self.window?.rootViewController as? MainStartingTabbarViewController else { return }
if (tabBarController.selectedViewController == tabBarController.viewControllers![4]) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
} else {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTrainerButton"), object: nil)
}
}
}
else if let newNotificationFlag = userInfo["newNotificationFlag"] as? String {
let newNotificationFlagInt = (Int(newNotificationFlag) ?? 0)
UserDefaults.standard.set(newNotificationFlag, forKey: "newNotificationFlag")
var newMessagesInt = 0
//MARK: - This is the line that breaks
if let newMessages = UserDefaults.standard.value(forKey: "newMessageFlag") as? String {
newMessagesInt = Int(newMessages) ?? 0
}
UIApplication.shared.applicationIconBadgeNumber = newMessagesInt + newNotificationFlagInt
guard let tabBarController = self.window?.rootViewController as? UITabBarController else { return }
let navigationController = tabBarController.viewControllers![4] as? UINavigationController // Regardless of the other custom app versions & the user type, the more menu will be the fifth tab
navigationController?.tabBarItem.badgeValue = String(newMessagesInt + newNotificationFlagInt)
let moreTab = navigationController?.viewControllers[0] as? MoreMenuTableViewController
moreTab?.notificationsFlagInt = newNotificationFlagInt
let applicationState = UIApplication.shared.applicationState
if applicationState != .active {
tabBarController.selectedViewController = tabBarController.viewControllers![4]
moreTab?.openNotifications()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
}
else {
if (tabBarController.selectedViewController == tabBarController.viewControllers![4]) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
} else {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTrainerButton"), object: nil)
}
}
}
completionHandler(UIBackgroundFetchResult.newData)
}
I have tried to recreate the problem by running the simulator and opening the app when it receives a remote notification without any success in getting the same error.
Edit Solution:
Thank you to #jrturton for such a helpful and insightful answer. This helped me on many different levels. I had been running through "wait for executable to run", but a little more thorough testing did uncover an error, though it still wasn't the one I posted about.
What I had overlooked was the line the crash report was telling me was the issue was on a previous version than the one I was looking at. When I went back to the version, it was in fact the line on code that you pointed out. So I put a dispatchQueue.asyncAfter in to let it load, and placed a guard statement on the count just in case it still doesn't load in time.
Problematic Code:
let moreTab = navigationController?.viewControllers[0] as? MoreMenuTableViewController
Fixed Code:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
UIApplication.shared.applicationIconBadgeNumber = newMessagesInt + newNotificationFlagInt
guard let tabBarController = self.window?.rootViewController as? UITabBarController,
(tabBarController.viewControllers?.count ?? 0) >= 5,
let navigationController = tabBarController.viewControllers![4] as? UINavigationController,
navigationController.viewControllers.count >= 1 else {
print("hit error with tabBaar or Nav controller")
return }
navigationController.tabBarItem.badgeValue = String(newMessagesInt + newNotificationFlagInt)
let moreTab = navigationController.viewControllers[0] as? MoreMenuTableViewController
moreTab?.notificationsFlagInt = newNotificationFlagInt
let applicationState = UIApplication.shared.applicationState
if applicationState != .active {
tabBarController.selectedViewController = tabBarController.viewControllers![4]
moreTab?.openNotifications()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
}
else {
if (tabBarController.selectedViewController == tabBarController.viewControllers![4]) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "getMessages"), object: nil)
} else {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTrainerButton"), object: nil)
}
}
}

I don't think the line you've highlighted is the crashing line. The crash log points to an array access, and the line you've highlighted isn't doing that.
It seems far more likely that the problem is on one of the many times you're accessing tab view controller or navigation view controller child view controllers via index - those are the only array accessors I can see in that function. Lines like this:
let moreTab = navigationController?.viewControllers[0] as? MoreMenuTableViewController
This line will crash if navigationController exists, but it has no child controller.
My guess is that this is happening when your app is being launched via the remote notification, not necessarily receiving the notification while it is open. That might mean this code is running before your app has finished launching and loading its view controllers.
Debugging notification issues can be tricky, but you can help yourself by creating an .apns file on your desktop containing the notification payload (see https://gist.github.com/muhammetkole/22cf3cc8a7b026f2ea2661b8497b773e for an example, you'll need to fill in your own details).
You can then drop this file on the simulator and it will act as if the notification has been received. You can test this with the app running, or in the background, while it's connected to the debugger.
To debug the process of launching from a notification, kill the app in the simulator, then edit the scheme / info / launch to "wait for executable to run". Build and "run" the project, then drop the file on the simulator, and it will launch the app and connect the debugger.
Hopefully one of those scenarios will allow you to reproduce the bug.

Related

How to populate TableView cell from datasource? I am currently receiving error

I am trying to return an array of Geocoded Placemarks from Mapbox Geocoder to TableView cells, but I am receiving an error (assertion failure in UITableView and failed to obtain a cell). Am I doing something incorrectly with the delegate or index path? I am have looked at similar questions, but I am unable to solve it.
I am using a storyboard; I have triple checked the cell identifier in my storyboard to make sure it aligned to 'with identifier'.
EDIT: I was able to remove the error by changing 'cellForRowAt indexPath: NSIndexPath' to 'cellForRowAt indexPath: IndexPath'.
Now when I enter text into the SearchBar it is returning the array, but the cells are empty even with data. Empty Cells Picture
import UIKit
import MapboxGeocoder
class LocationSearchTable: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var placemarkResults: [GeocodedPlacemark] = []
func forwardGeocoding(addressQuery: String) {
let geocoder = Geocoder(accessToken: "//OMITTED//")
let options = ForwardGeocodeOptions(query: addressQuery)
options.allowedScopes = [.address]
options.allowedISOCountryCodes = ["US"]
options.autocompletesQuery = true
let _ = geocoder.geocode(options) { (placemarks, attribution, error) in
guard let placemarks = placemarks, !placemarks.isEmpty else {
return
}
self.placemarkResults = placemarks
}
print(placemarkResults)
}
}
extension LocationSearchTable: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
guard let searchBarText = searchController.searchBar.text else { return }
let _ = forwardGeocoding(addressQuery: searchBarText)
self.tableView.reloadData()
}
}
extension LocationSearchTable {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return placemarkResults.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
let selectedItem = placemarkResults[indexPath.row].place
cell.textLabel?.text = selectedItem?.name
cell.detailTextLabel?.text = ""
return cell
}
}
2019-06-26 00:45:22.179129-0700 Ride Sharing App[91152:18783310] *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.103.12/UITableView.m:9655
2019-06-26 00:45:22.186549-0700 Ride Sharing App[91152:18783310] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView (<UITableView: 0x7f8fb398e200; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x6000018395c0>; layer = <CALayer: 0x60000161fca0>; contentOffset: {0, -144}; contentSize: {414, 44}; adjustedContentInset: {144, 0, 34, 0}>) failed to obtain a cell from its dataSource (<Ride_Sharing_App.LocationSearchTable: 0x7f8fb2d69660>)'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e2196fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010b3b7ac5 objc_exception_throw + 48
2 CoreFoundation 0x000000010e219482 +[NSException raise:format:arguments:] + 98
3 Foundation 0x000000010ae05927 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 194
4 UIKitCore 0x0000000115f0799f -[UITableView _configureCellForDisplay:forIndexPath:] + 433
5 UIKitCore 0x0000000115f1a6bf -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 911
6 UIKitCore 0x0000000115f1ab65 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 73
7 UIKitCore 0x0000000115ee2d20 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2870
8 UIKitCore 0x0000000115f02e37 -[UITableView layoutSubviews] + 165
9 UIKitCore 0x00000001161af9c1 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1417
10 QuartzCore 0x000000010ec85eae -[CALayer layoutSublayers] + 173
11 QuartzCore 0x000000010ec8ab88 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 396
12 QuartzCore 0x000000010ec96ee4 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 72
13 QuartzCore 0x000000010ec063aa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 328
14 QuartzCore 0x000000010ec3d584 _ZN2CA11Transaction6commitEv + 608
15 QuartzCore 0x000000010ec3dede _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 76
16 CoreFoundation 0x000000010e1800f7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
17 CoreFoundation 0x000000010e17a5be __CFRunLoopDoObservers + 430
18 CoreFoundation 0x000000010e17ac31 __CFRunLoopRun + 1505
19 CoreFoundation 0x000000010e17a302 CFRunLoopRunSpecific + 626
20 GraphicsServices 0x00000001112542fe GSEventRunModal + 65
21 UIKitCore 0x0000000115ce1ba2 UIApplicationMain + 140
22 Ride Sharing App 0x0000000108ac21ab main + 75
23 libdyld.dylib 0x000000010ca4c541 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
your problem could be because you're not setting the delegate & datasource.
so try this :
in your class:
class LocationSearchTable: UITableViewController, UITableViewDelegate, UITableViewDataSource {
//Then set the delegate and dataSource in ViewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
Also make sure you have an outlet for your TableView named tableView

crash in cellForRow : __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION

I have the following crash report in my cellForRow method.
This is not something that I can reproduce myself when running through xCode.
Crashed: com.apple.main-thread
0 App 0x1004a7624 specialized InspectionItemVC.tableView(UITableView, cellForRowAt : IndexPath) -> UITableViewCell (InspectionItemVC.swift:610)
1 App 0x10049f82c #objc InspectionItemVC.tableView(UITableView, cellForRowAt : IndexPath) -> UITableViewCell (InspectionItemVC.swift)
2 UIKit 0x198931d90 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 688
3 UIKit 0x198931fa8 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 80
4 UIKit 0x19891f6ac -[UITableView _updateVisibleCellsNow:isRecursive:] + 2152
5 UIKit 0x198936f98 -[UITableView _performWithCachedTraitCollection:] + 120
6 UIKit 0x1986cf49c -[UITableView layoutSubviews] + 176
7 UIKit 0x1985e9cc0 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1200
8 QuartzCore 0x1957da274 -[CALayer layoutSublayers] + 148
9 QuartzCore 0x1957cede8 CA::Layer::layout_if_needed(CA::Transaction*) + 292
10 UIKit 0x1985fe458 -[UIView(Hierarchy) layoutBelowIfNeeded] + 548
11 UIKit 0x1986a50c8 -[UINavigationController _layoutViewController:] + 1244
12 UIKit 0x1986a2944 -[UINavigationController _layoutTopViewController] + 228
13 UIKit 0x1986bb6f4 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 744
14 UIKit 0x1986bb3d0 -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:] + 420
15 UIKit 0x1986bafa0 -[UINavigationTransitionView _cleanupTransition] + 608
16 UIKit 0x198625060 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
17 UIKit 0x19862320c +[UIViewAnimationState popAnimationState] + 320
18 UIKit 0x1986ae7dc -[UINavigationTransitionView transition:fromView:toView:] + 1860
19 UIKit 0x1986a4764 -[UINavigationController _startTransition:fromViewController:toViewController:] + 2488
20 UIKit 0x1986a3870 -[UINavigationController _startDeferredTransitionIfNeeded:] + 856
21 UIKit 0x1986a3424 -[UINavigationController __viewWillLayoutSubviews] + 64
22 UIKit 0x1986a3388 -[UILayoutContainerView layoutSubviews] + 188
23 UIKit 0x1985e9cc0 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1200
24 QuartzCore 0x1957da274 -[CALayer layoutSublayers] + 148
25 QuartzCore 0x1957cede8 CA::Layer::layout_if_needed(CA::Transaction*) + 292
26 QuartzCore 0x1957ceca8 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32
27 QuartzCore 0x19574a34c CA::Context::commit_transaction(CA::Transaction*) + 252
28 QuartzCore 0x1957713ac CA::Transaction::commit() + 504
29 UIKit 0x1985df308 _afterCACommitHandler + 256
30 CoreFoundation 0x1924689a8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
31 CoreFoundation 0x192466630 __CFRunLoopDoObservers + 372
32 CoreFoundation 0x192466a7c __CFRunLoopRun + 956
33 CoreFoundation 0x192396da4 CFRunLoopRunSpecific + 424
34 GraphicsServices 0x193e01074 GSEventRunModal + 100
35 UIKit 0x198651c9c UIApplicationMain + 208
36 App 0x1000cfd04 main (AppDelegate.swift:22)
37 libdyld.dylib 0x1913a559c start + 4
I read that the error in question is linked to NSNotificationCenter and that I need to remove my observer in viewWillDisappear.
I already had removed my observer in deinit and viewDidDisappear. If I add the removal of the observer to viewWillDisappear also, should this solve my issue?
Also if I add the observer removal to viewWillDisappear, should I get rid of this code in deinit and viewDidDisappear?
Previous code:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
NotificationCenter.default.addObserver(self, selector:#selector(checkTimeout), name: NSNotification.Name(rawValue: "appOpened"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated);
NotificationCenter.default.removeObserver(self)
}
override func viewWillDisappear(_ animated: Bool)
{
//should I add NotificationCenter.default.removeObserver(self) here and remove it from the other two places above?
if let answers = Helper_EQI_Answer.getAnswers(inspectionID)
{
inspection?.answers = answers;
}
}
CellForRow snippet:
I included the case of the switch statement that points to line 610. EQI_Question type is an enum. All cases are satisfied in the switch
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if let item: = insp_Questions?[indexPath.row]{
if 1...12 ~= item.type && answerIDs != nil
{
switch (EQI_QuestionType(rawValue: item.type)!)
{
case .true_false:
if let cell = tableView.dequeueReusableCell(withIdentifier: "IQ_FlipCell") as? IQ_FlipCell
{
cell.table = questionTable;
cell.delegate = self;
cell.qID = answerIDs![indexPath.row];
cell.selectionStyle = .none
//this empty line is 610
if questionNA[indexPath.row]
{
cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_selected"), for: .normal);
cell.questionItem.isHidden = true;
} else {
cell.NABox.setImage(#imageLiteral(resourceName: "checkbox_up"), for: .normal);
cell.questionItem.isHidden = false;
}
let cell2 = cell.formatCell(with: item, for: cell, at: indexPath, qtype: 0)
textHeight[indexPath.row] = cell.questionText.numberOfVisibleLines;
if item.question.characters.count > 40
{
textHeight[indexPath.row] += 1
}
return cell2;
}
}
}
}
return UITableViewCell();
}

Delete UITableViewCell row with NSMutableArray throws exception

I have a tableview and the data inside each cell is an NSMutableArray. I want to delete a row of the tableview each time I swipe left and press the delete button. However it is difficult with an NSMutableArray. I get a Sigabrt everytime I input the code toDoItems.removeObjectAtIndex(indexPath.row).
The error I get is
Terminating with uncaught exception of type NSException 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
Any help on this problem?
Here is code relating to the problem.
ViewDidLoad code containing toDoItems:
let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
let itemListFromUserDefaults:NSMutableArray? = userDefaults.objectForKey("itemList") as? NSMutableArray
if ((itemListFromUserDefaults) != nil){
toDoItems = itemListFromUserDefaults!
}
My NSMutableArray variable
var toDoItems:NSMutableArray! = NSMutableArray()
My commitEditingStyle function:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if(editingStyle == UITableViewCellEditingStyle.Delete){
//This code gives me the error and Sigabrt
toDoItems.removeObjectAtIndex(indexPath.row)
tbl?.reloadData();
}
My numberOfRowsInSection function:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return toDoItems.count
}
My cellForRowAtIndexPath function:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableView
let toDoItem:NSDictionary = toDoItems.objectAtIndex(indexPath.row) as! NSDictionary
cell.lbl.text = toDoItem.objectForKey("itemTitel") as? String
return cell
}
Here is the error
MyPlanner[12373:461118] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
* First throw call stack:
(
0 CoreFoundation 0x0000000109df3d85 exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000109867deb objc_exception_throw + 48
2 CoreFoundation 0x0000000109df3cbd +[NSException raise:format:] + 205
3 CoreFoundation 0x0000000109de9dae -[__NSCFArray removeObjectAtIndex:] + 94
4 MyPlanner 0x0000000109210c53 _TTSf4dg_n_g_n___TFC9MyPlanner14ViewController9tableViewfTCSo11UITableView18commitEditingStyleOSC27UITableViewCellEditingStyle17forRowAtIndexPathCSo11NSIndexPath_T_ + 131
5 MyPlanner 0x000000010920fc3d _TToFC9MyPlanner14ViewController9tableViewfTCSo11UITableView18commitEditingStyleOSC27UITableViewCellEditingStyle17forRowAtIndexPathCSo11NSIndexPath_T_ + 61
6 UIKit 0x000000010ac124c0 -[UITableView animateDeletionOfRowWithCell:] + 205
7 UIKit 0x000000010abe7a3e __52-[UITableView _swipeActionButtonsForRowAtIndexPath:]_block_invoke + 80
8 UIKit 0x000000010ac13eaa -[UITableView _actionButton:pushedInCell:] + 172
9 UIKit 0x000000010ae3aae6 -[UITableViewCell _actionButtonPushed:] + 82
10 UIKit 0x000000010aab4a8d -[UIApplication sendAction:to:from:forEvent:] + 92
11 UIKit 0x000000010ac27e67 -[UIControl sendAction:to:forEvent:] + 67
12 UIKit 0x000000010ac28143 -[UIControl _sendActionsForEvents:withEvent:] + 327
13 UIKit 0x000000010ac27263 -[UIControl touchesEnded:withEvent:] + 601
14 UIKit 0x000000010af9cc52 _UIGestureRecognizerUpdate + 10279
15 UIKit 0x000000010ab2748e -[UIWindow _sendGesturesForEvent:] + 1137
16 UIKit 0x000000010ab286c4 -[UIWindow sendEvent:] + 849
17 UIKit 0x000000010aad3dc6 -[UIApplication sendEvent:] + 263
18 UIKit 0x000000010aaad553 _UIApplicationHandleEventQueue + 6660
19 CoreFoundation 0x0000000109d19301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17
20 CoreFoundation 0x0000000109d0f22c __CFRunLoopDoSources0 + 556
21 CoreFoundation 0x0000000109d0e6e3 __CFRunLoopRun + 867
22 CoreFoundation 0x0000000109d0e0f8 CFRunLoopRunSpecific + 488
23 GraphicsServices 0x000000010ec78ad2 GSEventRunModal + 161
24 UIKit 0x000000010aab2f09 UIApplicationMain + 171
25 MyPlanner 0x00000001092134fd main + 125
26 libdyld.dylib 0x000000010d43d92d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Here is the code where I put in the information(add items) in toDoItems.
#IBAction func ClickedforSelection(sender: AnyObject) {
if delegate != nil {
let information : NSString = txt1.text!
delegate!.userDidEntredInformation(information)
}
let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
var itemList:NSMutableArray? = userDefaults.objectForKey("itemList") as? NSMutableArray
let dataSet:NSMutableDictionary = NSMutableDictionary()
dataSet.setObject(txt.text!, forKey: "itemTitel")
if ((itemList) != nil){ // data already available
let newMutableList:NSMutableArray = NSMutableArray();
for dict:AnyObject in itemList!{
newMutableList.addObject(dict as! NSDictionary)
}
userDefaults.removeObjectForKey("itemList")
newMutableList.addObject(dataSet)
userDefaults.setObject(newMutableList, forKey: "itemList")
}else{ // This is the first todo item in the list
userDefaults.removeObjectForKey("itemList")
itemList = NSMutableArray()
itemList!.addObject(dataSet)
userDefaults.setObject(itemList, forKey: "itemList")
}
userDefaults.synchronize()
NSUserDefaults objectForKey will always return immutable objects. Simply down casting it won't make it mutable. You need to create a mutable array from the immutable array that is returned:
let userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
if let itemListFromUserDefaults = userDefaults.objectForKey("itemList") as? NSArray
toDoItems = itemListFromUserDefaults.mutableCopy()
}

Xcode 7.2 and NSTimer throws uncaught exception

Here is the code:
import UIKit
class ViewController: UIViewController {
var clickNumber:Int = 0
#IBOutlet weak var CountLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
CountLabel.text = "0"
let interval: Double = 60/120*4
var metronomeTimer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: "metronomeFunc:", userInfo: nil, repeats: true)
func metronomeFunc(timer:NSTimer) {
CountLabel.text = String(clickNumber)
clickNumber = clickNumber+1
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I don't know why, but on my new computer this simple thing doesn't work.
Here is what it gives me as a error:
2016-02-07 16:45:19.683 Move And Play[14743:2005023] -[Move_And_Play.ViewController metronomeFunc:]: unrecognized selector sent to instance 0x7f8c0a435c20
2016-02-07 16:45:19.695 Move And Play[14743:2005023] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Move_And_Play.ViewController metronomeFunc:]: unrecognized selector sent to instance 0x7f8c0a435c20'
*** First throw call stack:
(
0 CoreFoundation 0x000000010730ee65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010904edeb objc_exception_throw + 48
2 CoreFoundation 0x000000010731748d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010726490a ___forwarding___ + 970
4 CoreFoundation 0x00000001072644b8 _CF_forwarding_prep_0 + 120
5 Foundation 0x00000001076f40d1 __NSFireTimer + 83
6 CoreFoundation 0x000000010726ec84 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
7 CoreFoundation 0x000000010726e831 __CFRunLoopDoTimer + 1089
8 CoreFoundation 0x0000000107230241 __CFRunLoopRun + 1937
9 CoreFoundation 0x000000010722f828 CFRunLoopRunSpecific + 488
10 GraphicsServices 0x000000010bba3ad2 GSEventRunModal + 161
11 UIKit 0x0000000107b2b610 UIApplicationMain + 171
12 Move And Play 0x0000000106e2c17d main + 109
13 libdyld.dylib 0x0000000109b8592d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
It always worked before on my old computer with old version of xCode
Methods conforming to the target / selector pattern must be declared on the top level of the class.
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
CountLabel.text = "0"
let interval: Double = 2.0 // 60/120*4
var metronomeTimer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: "metronomeFunc:", userInfo: nil, repeats: true)
}
func metronomeFunc(timer:NSTimer) {
CountLabel.text = String(clickNumber)
clickNumber = clickNumber+1
}
...
}
It certainly did not work on your old computer with the nested syntax.

UITableView error returning custom prototype cell

'This coder requires that replaced objects be returned from initWithCoder:'
I'm beating my head over this. UITableViewController-
Here is cellForRow.. which calls a func to return the appropriate cell based on the index. The cells are dynamic prototype cells with reuse identifiers set correctly
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if tableView == self.tableView {
switch indexPath.row {
case 0: return self.imageCellForTableView(tableView, cellForRowAtIndexPath: indexPath)
case 1: return self.descriptionCellForTableView(tableView, cellForRowAtIndexPath: indexPath)
case 2: return self.buttonsCellForTableView(tableView, cellForRowAtIndexPath: indexPath)
case 3: return self.cartCellForTableView(tableView, cellForRowAtIndexPath: indexPath)
case 4: return self.detailsCellForTableView(tableView, cellForRowAtIndexPath: indexPath)
default: print("Error", terminator: "")
}
}
}
Here is the func throwing the error:
func cartCellForTableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// ERROR ON THE FOLLOWING LINE
let cell = tableView.dequeueReusableCellWithIdentifier("addtocart", forIndexPath: indexPath)
let btnAddToCart = cell.viewWithTag(4) as! UIButton
btnAddToCart.layer.borderColor = buttonBorderColor.CGColor
btnAddToCart.layer.borderWidth = buttonBorderWidth
btnAddToCart.setTitleColor(GOLD, forState: UIControlState.Normal)
btnAddToCart.backgroundColor = MAROON
btnAddToCart.addTarget(self, action: "addItemToCartAndBuy:", forControlEvents: UIControlEvents.TouchUpInside)
let btnApplePay = cell.viewWithTag(40) as! UIButton
btnApplePay.addTarget(self, action: "applePay", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
This func, imageCellForTableView: works fine
func imageCellForTableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("image", forIndexPath: indexPath)
let imgItem = cell.viewWithTag(1) as! PFImageView
if let imgFile: PFFile = item.itemImage {
imgItem.file = imgFile
imgItem.loadInBackground({ (image: UIImage?, error: NSError?) -> Void in
self.imgVToAnimate = PFImageView(frame: imgItem.convertRect(imgItem.frame, toView: self.navigationController?.view))
self.imgVToAnimate.file = imgFile
self.imgVToAnimate.loadInBackground()
})
} else {
imgItem.image = UIImage(named: "StoreError")
imgVToAnimate = PFImageView(frame: imgItem.convertRect(imgItem.frame, toView: self.navigationController?.view))
imgVToAnimate.image = UIImage(named: "StoreError")
}
imgVToAnimate.frame = imgItem .convertRect(imgItem.frame, toView: self.navigationController?.view)
imgVToAnimate.contentMode = UIViewContentMode.ScaleAspectFit
imgOriginal = imgItem
return cell
}
Here is the error:
2015-09-10 14:45:10.705 Corpsboard[89830:1947577] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'This coder requires that replaced objects be returned from initWithCoder:'
*** First throw call stack:
(
0 CoreFoundation 0x000000010a1519b5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000109bc5deb objc_exception_throw + 48
2 CoreFoundation 0x000000010a1518ed +[NSException raise:format:] + 205
3 UIKit 0x000000010800d6d1 UINibDecoderDecodeObjectForValue + 780
4 UIKit 0x000000010800d847 UINibDecoderDecodeObjectForValue + 1154
5 UIKit 0x000000010800d3bc -[UINibDecoder decodeObjectForKey:] + 278
6 UIKit 0x0000000107b4cdae -[UIView initWithCoder:] + 898
7 UIKit 0x000000010805e4ab -[UITableViewCellContentView initWithCoder:] + 40
8 UIKit 0x000000010800d686 UINibDecoderDecodeObjectForValue + 705
9 UIKit 0x000000010800d847 UINibDecoderDecodeObjectForValue + 1154
10 UIKit 0x000000010800d3bc -[UINibDecoder decodeObjectForKey:] + 278
11 UIKit 0x0000000107b4cdae -[UIView initWithCoder:] + 898
12 UIKit 0x0000000107e08689 -[UITableViewCell initWithCoder:] + 93
13 UIKit 0x000000010800d686 UINibDecoderDecodeObjectForValue + 705
14 UIKit 0x000000010800d847 UINibDecoderDecodeObjectForValue + 1154
15 UIKit 0x000000010800d3bc -[UINibDecoder decodeObjectForKey:] + 278
16 UIKit 0x0000000107e55a6c -[UINib instantiateWithOwner:options:] + 1290
17 UIKit 0x0000000107bfde91 -[UITableView _dequeueReusableViewOfType:withIdentifier:] + 388
18 UIKit 0x0000000107bfe263 -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:] + 71
19 Corpsboard 0x000000010538b574 _TFC10Corpsboard28StoreItemTableViewController20cartCellForTableViewfS0_FTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 132
20 Corpsboard 0x000000010538556a _TFC10Corpsboard28StoreItemTableViewController9tableViewfS0_FTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 986
21 Corpsboard 0x000000010538711f _TToFC10Corpsboard28StoreItemTableViewController9tableViewfS0_FTCSo11UITableView21cellForRowAtIndexPathCSo11NSIndexPath_CSo15UITableViewCell + 79
22 UIKit 0x0000000107c100c6 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 782
23 UIKit 0x0000000107c101db -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
24 UIKit 0x0000000107be6250 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3187
25 UIKit 0x0000000107c18fa8 -[UITableView _performWithCachedTraitCollection:] + 92
26 UIKit 0x0000000107c01599 -[UITableView layoutSubviews] + 218
27 UIKit 0x0000000107b72a3b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710
28 QuartzCore 0x000000010784536a -[CALayer layoutSublayers] + 146
29 QuartzCore 0x0000000107839bd0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
30 QuartzCore 0x0000000107839a4e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
31 QuartzCore 0x000000010782e1d5 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
32 QuartzCore 0x000000010785b9f0 _ZN2CA11Transaction6commitEv + 508
33 UIKit 0x0000000107ac0556 _UIApplicationHandleEventQueue + 7183
34 CoreFoundation 0x000000010a07db21 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
35 CoreFoundation 0x000000010a073a4c __CFRunLoopDoSources0 + 556
36 CoreFoundation 0x000000010a072f03 __CFRunLoopRun + 867
37 CoreFoundation 0x000000010a072918 CFRunLoopRunSpecific + 488
38 GraphicsServices 0x000000010bc16ad2 GSEventRunModal + 161
39 UIKit 0x0000000107ac599e UIApplicationMain + 171
40 Corpsboard 0x00000001052bdfef main + 111
41 libdyld.dylib 0x000000010b14792d start + 1
42 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Hmm.. try removing the if tableView == self.tableView condition...
...the tableView:cellForRowAtIndexPath: method already passes in a non-nil table view so you don't need to do that.
On another note, is there a reason why you didn't use a static table view controller? If your table is only going to have these 5 rows, it might be a lot easier to just a static table, and drag connections onto your view controller (so you don't have to use viewWithTag etc) it would potentially make this controller a lot simpler!