Crashing when attempting to write to realm - swift

I have an app that takes recordings of passing vehicles and information about them. A client of ours is experiencing a crash when using the app, but I can't find the source. This is the report that I get from Crashlytics:
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000098
Crashed: com.apple.main-thread
0 Realm 0x100d2f298 realm::Table::get_link_target(unsigned long) + 28
1 Realm 0x100b046f0 _ZZZN12_GLOBAL__N_110makeSetterIU8__strongP13RLMObjectBaseS3_EEP11objc_objectP11RLMPropertyEUb1_ENKUlvE_clEv (bind_ptr.hpp:186)
2 Realm 0x100b046f0 _ZZZN12_GLOBAL__N_110makeSetterIU8__strongP13RLMObjectBaseS3_EEP11objc_objectP11RLMPropertyEUb1_ENKUlvE_clEv (bind_ptr.hpp:186)
3 Realm 0x100b0462c ___ZN12_GLOBAL__N_110makeSetterIU8__strongP13RLMObjectBaseS3_EEP11objc_objectP11RLMProperty_block_invoke_2 (RLMAccessor.mm:313)
4 App Name 0x10070a398 SurveyController.(selected(button : RadioButton, in : RadioGroup) -> ()).(closure #1) (Survey Controller.swift:170)
5 RealmSwift 0x1007ee1e4 Realm.write(() throws -> ()) throws -> () (Realm.swift:155)
6 App Name 0x10070b200 specialized SurveyController.selected(button : RadioButton, in : RadioGroup) -> () (Survey Controller.swift:169)
7 App Name 0x10070a64c #objc SurveyController.selected(button : RadioButton, in : RadioGroup) -> () (Survey Controller.swift)
8 App Name 0x100715b24 specialized RadioGroup.buttonTapped(UITapGestureRecognizer) -> () (Radio Group.swift:77)
9 App Name 0x100715028 #objc RadioGroup.buttonTapped(UITapGestureRecognizer) -> () (Radio Group.swift)
10 UIKit 0x18e4f66e8 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64
11 UIKit 0x18ea633b4 _UIGestureRecognizerSendTargetActions + 124
12 UIKit 0x18e658e38 _UIGestureRecognizerSendActions + 320
13 UIKit 0x18e4f5740 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 764
14 UIKit 0x18ea54bd4 _UIGestureEnvironmentUpdate + 1096
15 UIKit 0x18e4ef4d8 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404
16 UIKit 0x18e4ef010 -[UIGestureEnvironment _updateGesturesForEvent:window:] + 276
17 UIKit 0x18e4ee874 -[UIWindow sendEvent:] + 3132
18 UIKit 0x18e4ed1d0 -[UIApplication sendEvent:] + 340
19 UIKit 0x18ecced1c __dispatchPreprocessedEventFromEventQueue + 2340
20 UIKit 0x18ecd12c8 __handleEventQueueInternal + 4744
21 UIKit 0x18ecca368 __handleHIDEventFetcherDrain + 152
22 CoreFoundation 0x1846b3404 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
23 CoreFoundation 0x1846b2c2c __CFRunLoopDoSources0 + 276
24 CoreFoundation 0x1846b079c __CFRunLoopRun + 1204
25 CoreFoundation 0x1845d0da8 CFRunLoopRunSpecific + 552
26 GraphicsServices 0x1865b5020 GSEventRunModal + 100
27 UIKit 0x18e5ed758 UIApplicationMain + 236
28 App Name 0x100701994 main (Image Controller.swift:15)
29 libdyld.dylib 0x184061fc0 start + 4
Line 4, SurveyController.(selected(button : RadioButton, in : RadioGroup) -> ()).(closure #1) (Survey Controller.swift:170) is where I'm assuming the cause of the issue if coming from. This is that block of code:
vehicleGroup.clearSelection() // Line 155
...
func selected(button: RadioButton, in group: RadioGroup) {
if group == vehicleGroup {
let vehicle = realm.objects(Vehicle.self).filter("value = \(button.tag)").first
do {
try realm.write {
recording.vehicle = button.isSelected ? vehicle : nil // Line 170
}
} catch {
record(error: error)
}
}
...
}
// Allows parent controllers to remove selections and reset the view.
func clearSelection() {
for button in buttons {
button.isSelected = false
}
}
Some additional details from the client:
They usually have a few hundred recording made by the time it crashes, but not always. It doesn't always crash when they have that many recordings.
The crash usually kicks them back a screen in the app, but most recently closed the entire thing. I did add the do try catch blocks before the most recent crash, so it might have crashed the whole thing from that, but I thought those would help keep the app open.
What is the cause for the crash? According to Crashlytics, the device still has plenty of RAM left, so I assume it's not a memory leak. Also, like I said, this doesn't happen every time they have a large number of recordings.

Related

Swift Application crashes due to RLMException

I'm currently writing a programm which will be the final project in my major, "Computer Sciences". The application I'm making is written is Swift. It is basically an application which allows to write and classify the tasks that an user planned to do daily, monthly or yearly. I just got stuck in the debug console. I am unable to figure it out.
I asked to most of my classmates if they could help me out trying to understand from where the issue could from.
The issue might be from the searchBar functionality which is written through the following code:
extension CategoryViewController: SwipeTableViewCellDelegate {
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
if let categoryForDeletion = self.categories?[indexPath.row] {
do {
try self.realm.write {
self.realm.delete(categoryForDeletion)
}
} catch {
print("Error deleting the category, \(error)")
}
}
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete-icon")
return [deleteAction]
}
func collectionView(_ collectionView: UICollectionView, editActionsOptionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
var options = SwipeOptions()
options.expansionStyle = .destructive
return options
}
}
I got the issue:
'RLMException', reason: 'Index 2 is out of bounds (must be less than 2).'
*** First throw call stack:
(
0 CoreFoundation 0x000000010519e1bb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x00000001038e6735 objc_exception_throw + 48
2 Realm 0x00000001028b4d3e _Z20RLMThrowResultsErrorP8NSString + 670
3 Realm 0x00000001028b5fa6 _ZL25translateRLMResultsErrorsIZ28-[RLMResults objectAtIndex:]E3$_6EDaOT_P8NSString + 118
4 Realm 0x00000001028b5ece -[RLMResults objectAtIndex:] + 110
5 RealmSwift 0x0000000101ef2e3c $S10RealmSwift7ResultsCyxSicig + 220
6 Todoey2 0x0000000101aea48f $S7Todoey222CategoryViewControllerC05tableC0_19editActionsForRowAt3forSay12SwipeCellKit0L6ActionCGSgSo07UITableC0C_10Foundation9IndexPathVAG0lG11OrientationOtFyAI_APtcfU_ + 303
7 Todoey2 0x0000000101aea8e2 $S7Todoey222CategoryViewControllerC05tableC0_19editActionsForRowAt3forSay12SwipeCellKit0L6ActionCGSgSo07UITableC0C_10Foundation9IndexPathVAG0lG11OrientationOtFyAI_APtcfU_TA + 18
8 SwipeCellKit 0x000000010224c3e8 $S12SwipeCellKit0A10ControllerC7perform6action4hideyAA0A6ActionC_SbtF + 776
9 SwipeCellKit 0x0000000102245d99 $S12SwipeCellKit0A10ControllerC7perform6actionyAA0A6ActionC_tF + 1241
10 SwipeCellKit 0x000000010224b734 $S12SwipeCellKit0A10ControllerC16swipeActionsView_9didSelectyAA0afG0C_AA0A6ActionCtF + 52
11 SwipeCellKit 0x000000010224e199 $S12SwipeCellKit0A10ControllerCAA0A19ActionsViewDelegateA2aDP05swipeeF0_9didSelectyAA0aeF0C_AA0A6ActionCtFTW + 9
12 SwipeCellKit 0x000000010222c40e $S12SwipeCellKit0A11ActionsViewC12actionTapped6buttonyAA0A12ActionButtonC_tF + 590
13 SwipeCellKit 0x000000010222c47c $S12SwipeCellKit0A11ActionsViewC12actionTapped6buttonyAA0A12ActionButtonC_tFTo + 60
14 UIKitCore 0x000000010d233ecb -[UIApplication sendAction:to:from:forEvent:] + 83
15 UIKitCore 0x000000010cc6f0bd -[UIControl sendAction:to:forEvent:] + 67
16 UIKitCore 0x000000010cc6f3da -[UIControl _sendActionsForEvents:withEvent:] + 450
17 UIKitCore 0x000000010cc6e31e -[UIControl touchesEnded:withEvent:] + 583
18 UIKitCore 0x000000010ce07018 _UIGestureEnvironmentSortAndSendDelayedTouches + 5387
19 UIKitCore 0x000000010ce00fd1 _UIGestureEnvironmentUpdate + 1506
20 UIKitCore 0x000000010ce009ad -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 478
21 UIKitCore 0x000000010ce0071d -[UIGestureEnvironment _updateForEvent:window:] + 200
22 UIKitCore 0x000000010d27078a -[UIWindow sendEvent:] + 4058
23 UIKitCore 0x000000010d24e394 -[UIApplication sendEvent:] + 352
24 UIKitCore 0x000000010d3235a9 __dispatchPreprocessedEventFromEventQueue + 3054
25 UIKitCore 0x000000010d3261cb __handleEventQueueInternal + 5948
26 CoreFoundation 0x0000000105103721 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
27 CoreFoundation 0x0000000105102f93 __CFRunLoopDoSources0 + 243
28 CoreFoundation 0x00000001050fd63f __CFRunLoopRun + 1263
29 CoreFoundation 0x00000001050fce11 CFRunLoopRunSpecific + 625
30 GraphicsServices 0x000000010a6731dd GSEventRunModal + 62
31 UIKitCore 0x000000010d23281d UIApplicationMain + 140
32 Todoey2 0x0000000101aef817 main + 71
33 libdyld.dylib 0x0000000104ce9575 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
This is an index out-of-bounds exception:
'RLMException', reason: 'Index 2 is out of bounds (must be less than
2).'
This happens when you subscript an array with an index that is greater or equal to the length of the array (equal to, because array indexes start at 0 not 1).
if let categoryForDeletion = self.categories?[indexPath.row]
The above line will crash if row >= self.categories.count. I would suggest looking into the numberOfRowsForSection function to figure out why you have more rows than categories.
Hard to tell whats going on with very little code.
I'd suggest littering your code with print statements (especially for your array counts, indexpath.row in cellForRow, editActionsForRowAt etc) and see where it's going wrong.
Looks like you are calling delete on a row that doesn't exist in your realm database, because of which it is crashing.
Here's how I'd update the closure
{ action, indexPath in
// handle action by updating model with deletion
print("\(indexPath.row)")
print("\(self.categories?.count)") //if these two mismatch, that's the problem
if let categoryForDeletion = self.categories?[indexPath.row] {
do {
try self.realm.write {
self.realm.delete(categoryForDeletion)
}
} catch {
print("Error deleting the category, \(error)")
}
}
}

Cocoa archived app crashing

I am new in archiving app for testing/distribution. My MacOS cocoa app crash only when built as an archive.
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [0]
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 MY.APP 0x000000010100532a specialized String._CharacterView.index(after:) + 250
1 MY.APP 0x0000000100f55ef9 specialized static TextCompletionNode.hasCommonPrefix(_:with:beyond:) + 153 (AttributeManager.swift:126)
2 MY.APP 0x0000000100f571f9 specialized TextCompletionNode.add(entry:for:) + 1161
3 MY.APP 0x0000000100f584a9 specialized closure #1 in AttributeManager.init(dataSource:loadingHandler:) + 3097
4 MY.APP 0x0000000100f5439e partial apply for closure #1 in AttributeManager.init(dataSource:loadingHandler:) + 30
5 MY.APP 0x000000010104d0a3 SearchQueryCommunicator.messageHandler(_:) + 451
6 MY.APP 0x000000010104d710 protocol witness for MessageHandler.messageHandler(_:) in conformance SearchQueryCommunicator + 16
7 MY.APP 0x000000010102ede8 Socket.handle(object:) + 456
8 MY.APP 0x0000000101031928 specialized Socket.readAvailableBytes(from:) + 1096
9 MY.APP 0x0000000101031c48 specialized Socket.stream(_:handle:) + 104 (Socket.swift:77)
10 MY.APP 0x000000010102ebff #objc Socket.stream(_:handle:) + 47
11 com.apple.CoreFoundation 0x00007fff49548dc4 _signalEventSync + 228
12 com.apple.CoreFoundation 0x00007fff49563736 _cfstream_solo_signalEventSync + 246
13 com.apple.CoreFoundation 0x00007fff49546ca4 _CFStreamSignalEvent + 484
14 com.apple.CFNetwork 0x00007fff48448a62 SocketStream::dispatchSignalFromSocketCallbackUnlocked(SocketStreamSignalHolder*) + 58
15 com.apple.CFNetwork 0x00007fff4844cff9 SocketStream::socketCallback(__CFSocket*, unsigned long, __CFData const*, void const*) + 145
16 com.apple.CFNetwork 0x00007fff4844cf2e SocketStream::_SocketCallBack_stream(__CFSocket*, unsigned long, __CFData const*, void const*, void*) + 70
17 com.apple.CoreFoundation 0x00007fff49546898 __CFSocketPerformV0 + 1016
18 com.apple.CoreFoundation 0x00007fff49527a11 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
19 com.apple.CoreFoundation 0x00007fff495e142c __CFRunLoopDoSource0 + 108
20 com.apple.CoreFoundation 0x00007fff4950a470 __CFRunLoopDoSources0 + 208
21 com.apple.CoreFoundation 0x00007fff495098ed __CFRunLoopRun + 1293
22 com.apple.CoreFoundation 0x00007fff49509153 CFRunLoopRunSpecific + 483
23 com.apple.HIToolbox 0x00007fff487f3d96 RunCurrentEventLoopInMode + 286
24 com.apple.HIToolbox 0x00007fff487f3b06 ReceiveNextEventCommon + 613
25 com.apple.HIToolbox 0x00007fff487f3884 _BlockUntilNextEventMatchingListInModeWithFilter + 64
26 com.apple.AppKit 0x00007fff46aa4a73 _DPSNextEvent + 2085
27 com.apple.AppKit 0x00007fff4723ae34 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
28 com.apple.AppKit 0x00007fff46a99885 -[NSApplication run] + 764
29 com.apple.AppKit 0x00007fff46a68a72 NSApplicationMain + 804
30 MY.APP 0x0000000100f40949 main + 9 (AppDelegate.swift:12)
31 libdyld.dylib 0x00007fff7134a015 start + 1
Here's the TextCompletionNode function:
// we assume firstString and secondString are at least longer than beyond
private static func hasCommonPrefix(_ firstString:String, with secondString:String, beyond beyondIndex:String.Index) -> String? {
assert((firstString.endIndex >= beyondIndex) && (secondString.endIndex >= beyondIndex))
var commonPrefix = String(firstString[..<beyondIndex])
guard secondString.hasPrefix(commonPrefix) else {
return nil
}
var firstIndex = beyondIndex
let firstEndIndex = firstString.endIndex
var previousCommonPrefix: String
repeat {
previousCommonPrefix = commonPrefix
if firstIndex >= firstEndIndex {
break
}
//NSLog("firstString = \"\(firstString)\", firstIndex = \(firstIndex)")
firstIndex = firstString.index(after: firstIndex) // <-- Crashing?
commonPrefix = String(firstString[..<firstIndex])
} while secondString.hasPrefix(commonPrefix)
return previousCommonPrefix
}
Everything is working well when testing the same functionality when running the app from Xcode. I've read that debugging information is removed from archived app so you can't really debug them. I've tried to add a NSLog statement to write some debugging information in the Console app, and nothing is showing. I also tried starting the app from command-line (MyApp.app/Contents/MacOS/MyApp), nothing is showing in the terminal either.
I would like to know more about the conditions before the crash. What should I do?
EDIT: I've tried to flush STDERR and even redirect STDERR into a file based on this answer from this other post: https://stackoverflow.com/a/5938021/301189 and nothing was working. Simply replacing NSLog(_:_:) with printf(_:) helped me to get some output in the terminal. I still don't know why I can't get anything from STDERR in the archived app though.
Also, the above crash does not happen when putting output some output in the terminal. Such a weird bug...

Terminating app due to uncaught exception 'NSInvalidArgumentException', on deleting Row in UITableView [duplicate]

This question already has an answer here:
unrecognized selector sent to instance when no related entities found in Core Data
(1 answer)
Closed 4 years ago.
I am getting the above error when executing the following code:
func tableView(_ tableView: UITableView,
commit editingStyle: UITableViewCellEditingStyle,
forRowAt indexPath: IndexPath) {
let eventsOnArray = selectedRecipient?.events.allObjects // crashes here
guard let eventToRemove = eventsOnArray![indexPath.row] as? Event, editingStyle == .delete else {
return
}
managedContext.delete(eventToRemove)
do {
try managedContext.save()
getEvents()
self.eventList.reloadData()
} catch let error as NSError {
print("Saving error: \(error), description: \(error.userInfo)")
}
}
The detailed error is:
2018-03-11 12:20:49.732482-0400 Card Tracker[1516:29197] -[Recipient events]: unrecognized selector sent to instance 0x600000283840
2018-03-11 12:20:49.746477-0400 Card Tracker[1516:29197] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Recipient events]: unrecognized selector sent to instance 0x600000283840'
*** First throw call stack:
(
0 CoreFoundation 0x000000010fe2f12b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010ef76f41 objc_exception_throw + 48
2 CoreFoundation 0x000000010feb0024 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010fdb1f78 ___forwarding___ + 1432
4 CoreFoundation 0x000000010fdb1958 _CF_forwarding_prep_0 + 120
5 Card Tracker 0x000000010e62b773 _T012Card_Tracker010ViewEventsC10ControllerC05tableC0ySo07UITableC0C_SC0gC16CellEditingStyleO6commit10Foundation9IndexPathV8forRowAttF + 195
6 Card Tracker 0x000000010e62c177 _T012Card_Tracker010ViewEventsC10ControllerC05tableC0ySo07UITableC0C_SC0gC16CellEditingStyleO6commit10Foundation9IndexPathV8forRowAttFTo + 119
7 UIKit 0x0000000110410a5f -[UITableView _animateDeletionOfRowAtIndexPath:] + 177
8 UIKit 0x0000000110419a59 __82-[UITableView _contextualActionForDeletingRowAtIndexPath:usingPresentationValues:]_block_invoke + 59
9 UIKit 0x0000000110953d67 -[UIContextualAction executeHandlerWithView:completionHandler:] + 174
10 UIKit 0x0000000110c41374 -[UISwipeOccurrence _performSwipeAction:inPullview:swipeInfo:] + 702
11 UIKit 0x0000000110c42bd1 -[UISwipeOccurrence swipeActionPullView:tappedAction:] + 112
12 UIKit 0x0000000110d25ed2 -[UISwipeActionPullView _tappedButton:] + 138
13 UIKit 0x00000001102ae972 -[UIApplication sendAction:to:from:forEvent:] + 83
14 UIKit 0x000000011042dc3c -[UIControl sendAction:to:forEvent:] + 67
15 UIKit 0x000000011042df59 -[UIControl _sendActionsForEvents:withEvent:] + 450
16 UIKit 0x000000011042ce86 -[UIControl touchesEnded:withEvent:] + 618
17 UIKit 0x000000011089ebad _UIGestureEnvironmentSortAndSendDelayedTouches + 5560
18 UIKit 0x0000000110898a4d _UIGestureEnvironmentUpdate + 1506
19 UIKit 0x000000011089841f -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 484
20 UIKit 0x00000001108974cb -[UIGestureEnvironment _updateGesturesForEvent:window:] + 288
21 UIKit 0x0000000110325f14 -[UIWindow sendEvent:] + 4102
22 UIKit 0x00000001102c9365 -[UIApplication sendEvent:] + 352
23 UIKit 0x000000012c2fe49d -[UIApplicationAccessibility sendEvent:] + 85
24 UIKit 0x0000000110c15a1d __dispatchPreprocessedEventFromEventQueue + 2809
25 UIKit 0x0000000110c18672 __handleEventQueueInternal + 5957
26 CoreFoundation 0x000000010fdd2101 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
27 CoreFoundation 0x000000010fe71f71 __CFRunLoopDoSource0 + 81
28 CoreFoundation 0x000000010fdb6a19 __CFRunLoopDoSources0 + 185
29 CoreFoundation 0x000000010fdb5fff __CFRunLoopRun + 1279
30 CoreFoundation 0x000000010fdb5889 CFRunLoopRunSpecific + 409
31 GraphicsServices 0x00000001159789c6 GSEventRunModal + 62
32 UIKit 0x00000001102ad5d6 UIApplicationMain + 159
33 Card Tracker 0x000000010e606727 main + 55
34 libdyld.dylib 0x000000011436dd81 start + 1
35 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I am trying to delete a detail row in a Header-Detail based Entity. The crash occurs in the debugger as soon as I leave the line let eventsOnArray. I have placed a break point on that line, the code runs up until that point and then crashes when I use "Step Over".
getEvents:
func getEvents () {
// Now load all Events for this Receipient
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Event")
request.resultType = .dictionaryResultType
do {
events = try managedContext.fetch(request) as! [NSDictionary]
} catch {
print("Core Data Fetch Failed:", error.localizedDescription)
}
}
Core Data Definition:
Chances are that selectedRecepient is not an instance of Recipient class (or at least ObjC runtime thinks so).
Try to examine its type:
print(type(of: selectedRecipient))
If it prints NSManagedObject then you should make sure that Recipient entity has its class set to Recipient in data model editor – this tells Core Data to cast instances of that entity to the corresponding class.

swift simple app always crashing on simulator

My app is basically a webview with a locally stored webapp.
To support URL-Scheme mapping, I call the following function on viewDidLoad, to subscribe to UIApplicationDidBecomeActiveNotification, then when I get such message, I load a webapp into the UIWebView:
/**
* Setup the observer to get notifications about app activation
*/
func initObserver() {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "initWebApp",
name: UIApplicationDidBecomeActiveNotification,
object: nil);
}
/**
* Launches the WebApp, this is called from the observer,
* and appDelegate.appParameters has possible parameters to the webapp
*/
func initWebApp() {
var appDelegate=UIApplication.sharedApplication().delegate as AppDelegate;
println ("- Launch Parameters: "+appDelegate.initParameters);
let path=appDelegate.initParameters,
url=NSURL(string: URL_BASE + "?" + (path ?? "")),
requestObj=NSURLRequest(URL: url!);
mWebView.loadRequest(requestObj);
}
However, when I init the webview in this way (coming from the observed handler) the simulator always crashes with the stacktrace enclosed below as soon as I click anywhere on the window.
On the contrary, If I don't subscribe to the event, and just call initWebApp() from viewDidLoad(), everything works fine (obviously URL Scheme mapping doesn't work, but I mean the webview and its app work 100% without crashing)
Can anybody take a look at this stack trace (it's always the same) and give me any pointers?
Is it a bad practice to manipulate UI objects such as UIWebView from an event handler? (I come from Android where you often have to change threads in similar situations)
2015-04-06 02:49:34.907 FunqTV[14285:518122] -[NSURL _effectiveStatusBarStyleViewController]: unrecognized selector sent to instance 0x7ae1cac0
2015-04-06 02:49:34.919 FunqTV[14285:518122] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURL _effectiveStatusBarStyleViewController]: unrecognized selector sent to instance 0x7ae1cac0'
*** First throw call stack:
*** First throw call stack:
(
0 CoreFoundation 0x00648466 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x02037a97 objc_exception_throw + 44
2 CoreFoundation 0x006502c5 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277
3 CoreFoundation 0x00598bc7 ___forwarding___ + 1047
4 CoreFoundation 0x0059878e _CF_forwarding_prep_0 + 14
5 UIKit 0x00fd3fa8 +[UIViewController _currentStatusBarStyleViewController] + 75
6 UIKit 0x00e63c81 -[UIApplication _updateCurrentStatusBarViewControllerAppearance] + 59
7 UIKit 0x00eb06ea -[UIWindow _updateContextOrderingAndSetLayerHidden:] + 548
8 UIKit 0x00eade74 -[UIWindow _initWithFrame:debugName:scene:attached:] + 336
9 UIKit 0x00eadd1e -[UIWindow _initWithFrame:debugName:attached:] + 79
10 UIKit 0x00eadc7f -[UIWindow _initWithFrame:attached:] + 71
11 UIKit 0x011e6f27 -[UIAutoRotatingWindow _initWithFrame:attached:] + 80
12 UIKit 0x00eadc33 -[UIWindow initWithFrame:] + 63
13 UIKit 0x011e6eba -[UIAutoRotatingWindow initWithFrame:] + 72
14 UIKit 0x011e4e2a -[UITextEffectsWindow initWithFrame:] + 72
15 UIKit 0x00eae09a -[UIWindow initWithContentRect:] + 164
16 UIKit 0x011e4b12 -[UITextEffectsWindow(UIObjectsForPerScreen) _basicInitWithScreen:options:] + 141
17 UIKit 0x011e4bcf -[UITextEffectsWindow(UIObjectsForPerScreen) _initWithScreen:options:] + 182
18 UIKit 0x016fcf8c +[_UIObjectPerScreen objectOfClass:forScreen:withOptions:createIfNecessary:] + 556
19 UIKit 0x011e645c +[UITextEffectsWindow _sharedTextEffectsWindowforScreen:aboveStatusBar:allowHosted:matchesStatusBarOrientationOnAccess:] + 416
20 UIKit 0x011e65b4 +[UITextEffectsWindow sharedTextEffectsWindowForScreen:] + 121
21 UIKit 0x013d173a -[UIPeripheralHost(UIKitInternal) containerWindow] + 156
22 UIKit 0x013d178a -[UIPeripheralHost(UIKitInternal) containerRootController] + 34
23 UIKit 0x013c6e15 -[UIPeripheralHost currentState] + 38
24 UIKit 0x013c6f10 -[UIPeripheralHost isOnScreen] + 35
25 UIKit 0x013d3a6a -[UIPeripheralHost(UIKitInternal) _isCoordinatingWithSystemGestures] + 82
26 UIKit 0x00e70da1 -[UIApplication _shouldDelayTouchesForControlCenter] + 56
27 UIKit 0x00ebd506 -[UIWindow _shouldDelayTouchForSystemGestures:] + 41
28 UIKit 0x0128f8e8 -[_UISystemGestureGateGestureRecognizer touchesBegan:withEvent:] + 498
29 UIKit 0x00eb3946 -[UIWindow _sendGesturesForEvent:] + 567
30 UIKit 0x00eb4abf -[UIWindow sendEvent:] + 769
31 UIKit 0x00e79bb1 -[UIApplication sendEvent:] + 242
32 UIKit 0x00e89bf6 _UIApplicationHandleEventFromQueueEvent + 21066
33 UIKit 0x00e5dbc7 _UIApplicationHandleEventQueue + 2300
34 CoreFoundation 0x0056b98f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
35 CoreFoundation 0x0056149d __CFRunLoopDoSources0 + 253
36 CoreFoundation 0x005609f8 __CFRunLoopRun + 952
37 CoreFoundation 0x0056037b CFRunLoopRunSpecific + 443
38 CoreFoundation 0x005601ab CFRunLoopRunInMode + 123
39 GraphicsServices 0x040152c1 GSEventRunModal + 192
40 GraphicsServices 0x040150fe GSEventRun + 104
41 UIKit 0x00e619b6 UIApplicationMain + 1526
42 FunqTV 0x0007dfbe top_level_code + 78
43 FunqTV 0x0007dffb main + 43
44 libdyld.dylib 0x027a5ac9 start + 1
45 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
If I wrap the call to initWebApp() into a dispatch_async() block, it works:
/**
* Setup the observer to get notifications about app activation
*/
func initObserver() {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "requestInitWebApp",
name: UIApplicationDidBecomeActiveNotification,
object: nil);
}
/**
* Called from the observer. It now dispatches async a call to the init
* function rather than calling it directly from the observer thread.
*/
func requestInitWebApp() {
println ("Dispatching async call to init webview");
dispatch_async(dispatch_get_main_queue()) {
self.initWebApp();
}
}

Swift - Editing UITextView from inside callback crashes app

I have the following code that makes a HTTP Request, then outputs the result to a UITextView:
#IBOutlet var echoLog: UITextView!
#IBAction func sendEcho(sender: AnyObject) {
let callback = { (textString: String) -> Void in
self.echoLog.text = textString // App crashes here :(
}
HTTPRequest("http://localhost/echo", ["echo": "Echo!"], callback)
}
But when I call sendEcho the app crashes with this error:
2014-07-28 20:58:22.218 AppName[10463:144343] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation_Sim/UIFoundation-364/UIFoundation/TextSystem/NSLayoutManager_Private.m:1547
2014-07-28 20:58:22.231 AppName[10463:144343] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
*** First throw call stack:
(
0 CoreFoundation 0x00496ca6 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x01df08bf objc_exception_throw + 44
2 CoreFoundation 0x00496b3a +[NSException raise:format:arguments:] + 138
3 Foundation 0x00904d2e -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 102
4 UIFoundation 0x03344072 -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 418
5 UIFoundation 0x03343d6e -[NSLayoutManager(NSPrivate) _recalculateUsageForTextContainerAtIndex:] + 2017
6 UIFoundation 0x0337da43 -[NSLayoutManager textStorage:edited:range:changeInLength:invalidatedRange:] + 871
7 UIFoundation 0x0337db53 -[NSLayoutManager processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:] + 85
8 UIFoundation 0x033a7a7b -[NSTextStorage _notifyEdited:range:changeInLength:invalidatedRange:] + 153
9 UIFoundation 0x033a759a -[NSTextStorage processEditing] + 458
10 UIFoundation 0x033a7124 -[NSTextStorage endEditing] + 80
11 UIFoundation 0x033a71af -[NSTextStorage coordinateEditing:] + 67
12 UIKit 0x014938ae -[UITextView setAttributedText:] + 250
13 UIKit 0x01499745 -[UITextView setText:] + 149
14 AppName 0x00036216 _TFFC8AppName19FirstViewController8sendEchoFS0_FPSs9AnyObject_T_U_FOS_9JSONValueT_ + 1350
15 AppName 0x0003525a _TPA__TFFC8AppName19FirstViewController8sendEchoFS0_FPSs9AnyObject_T_U_FOS_9JSONValueT_ + 106
16 AppName 0x0001de86 _TFF8AppName11HTTPRequestFTSSGVSs10DictionarySSPSs9AnyObject__FOS_9JSONValueT__T_U_FTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError__T_ + 1350
17 AppName 0x0001d0a4 _TPA__TFF8AppName11HTTPRequestFTSSGVSs10DictionarySSPSs9AnyObject__FOS_9JSONValueT__T_U_FTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError__T_ + 100
18 AppName 0x0001e289 _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT__ + 41
19 AppName 0x0001d15a _TPA__TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFo_iTGSQS__GSQS0__GSQS1____iT__ + 90
20 AppName 0x0001e2d7 _TTRXFo_iTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError___iT__XFo_oGSQS__oGSQS0__oGSQS1___dT__ + 55
21 AppName 0x0001d224 _TPA__TTRXFo_iTGSQCSo6NSData_GSQCSo13NSURLResponse_GSQCSo7NSError___iT__XFo_oGSQS__oGSQS0__oGSQS1___dT__ + 100
22 AppName 0x0001e36e _TTRXFo_oGSQCSo6NSData_oGSQCSo13NSURLResponse_oGSQCSo7NSError__dT__XFdCb_dGSQS__dGSQS0__dGSQS1___dT__ + 142
23 CFNetwork 0x02c36158 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 181
24 Foundation 0x0092da35 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 12
25 Foundation 0x00854635 -[NSBlockOperation main] + 99
26 Foundation 0x00833a97 -[__NSOperationInternal _start:] + 700
27 Foundation 0x008337c9 -[NSOperation start] + 83
28 Foundation 0x00833613 __NSOQSchedule_f + 237
29 libdispatch.dylib 0x022ef3ff _dispatch_client_callout + 14
30 libdispatch.dylib 0x022d8578 _dispatch_queue_drain + 1424
31 libdispatch.dylib 0x022d7f90 _dispatch_queue_invoke + 142
32 libdispatch.dylib 0x022d9e06 _dispatch_root_queue_drain + 312
33 libdispatch.dylib 0x022dae67 _dispatch_worker_thread2 + 45
34 libsystem_pthread.dylib 0x0263fdab _pthread_wqthread + 336
35 libsystem_pthread.dylib 0x02643cce start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Thanks in advance!
It looks like your problem is that you are not on the mainThread, by the second line in the trace.
You are probably still running code in the background, due to the nature of HTTPRequest asynchronous handling of data... that's fine. You just need to get to the main thread, after all is said and done.
Here's how to probably fix it...
#IBAction func sendEcho(sender: AnyObject)
{
let callback = {(textString: String) in
dispatch_sync(dispatch_get_main_queue())
{
self.echoLog.text = textString //Yay!
}
}
HTTPRequest("http://localhost/echo", ["echo": "Echo!"], callback)
}
Reminder time UI updates should only be performed on the mainThread. Simply because doing so provides high priority for this thing to occur. Usually when you try to do UI updates on a background thread, you will see a delay between when the code is executed and when you see results. In this case, an Assertion failure (I like that). If you do not know if you are on the main thread, you can check it out by doing NSThread.isMainThread() which returns a bool.
Warning If you are already on the main thread while calling dispatch_sync(dispatch_get_main_queue()) {...} your app will freeze up, so make sure you know what thread you are on...
Apple will only let you modify UI components on the main event loop. It appears that the HTTPRequest is running callback on a background thread so you will have to explicitly run the change on the main thread:
let callback = { (textString: String) -> Void in
dispatch_async(dispatch_get_main_queue(), {
self.echoLog.text = textString
})
}