Share data between two view controllers via userDeafults - ios

I'm creating UISwitch that controls two view controllers, and I need to share data of UISwitch condition between them. I tried to use User Defaults but got SIGABRT error. What do I need to fix to get it working?
// Its view with UISwitch
#IBAction func SwitchThemeColor(_ sender: UISwitch) {
if SwitchTheme.isOn || traitCollection.userInterfaceStyle == .dark {
view.backgroundColor = UIColor.black
UserDefaults.standard.set(true, forKey: "switchState")
UserDefaults.standard.synchronize()
}
// And that is the view where I want to transfer UISwitch condition
if UserDefaults.standard.bool(forKey: "switchState") == true {
view.backgroundColor = UIColor.black
}
expected: that data transfers and switch controls background of two views
actual: SIGABRT error and it did not work
also I write bt in output and get this:
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff513782c6 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff5141fbf1 libsystem_pthread.dylib`pthread_kill + 284
frame #2: 0x00007fff51308a5c libsystem_c.dylib`abort + 120
frame #3: 0x00007fff4f22e7f8 libc++abi.dylib`abort_message + 231
frame #4: 0x00007fff4f22e9c7 libc++abi.dylib`demangling_terminate_handler() + 262
frame #5: 0x00007fff503b5d7c libobjc.A.dylib`_objc_terminate() + 96
frame #6: 0x00007fff4f23be97 libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x00007fff4f23be39 libc++abi.dylib`std::terminate() + 41
frame #8: 0x00007fff503b5d1c libobjc.A.dylib`objc_terminate + 9
frame #9: 0x000000010ff1cd78 libdispatch.dylib`_dispatch_client_callout + 28
frame #10: 0x000000010ff1fcd5 libdispatch.dylib`_dispatch_block_invoke_direct + 300
frame #11: 0x00007fff3633108a FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
frame #12: 0x00007fff36330d78 FrontBoardServices`-[FBSSerialQueue _queue_performNextIfPossible] + 441
frame #13: 0x00007fff36331287 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 22
frame #14: 0x00007fff23afbac1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #15: 0x00007fff23afb9ec CoreFoundation`__CFRunLoopDoSource0 + 76
frame #16: 0x00007fff23afb21c CoreFoundation`__CFRunLoopDoSources0 + 268
frame #17: 0x00007fff23af5ecf CoreFoundation`__CFRunLoopRun + 1263
frame #18: 0x00007fff23af56b6 CoreFoundation`CFRunLoopRunSpecific + 438
frame #19: 0x00007fff3815cbb0 GraphicsServices`GSEventRunModal + 65
frame #20: 0x00007fff47162a67 UIKitCore`UIApplicationMain + 1621
* frame #21: 0x000000010fa7bdab TabbedAppTest`main at AppDelegate.swift:12:7
frame #22: 0x00007fff5123bcf5 libdyld.dylib`start + 1
frame #23: 0x00007fff5123bcf5 libdyld.dylib`start + 1

Problem is somewhere else - this code should works.
You mention in comment, that you get error message: Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<TabbedAppTest.SecondViewController 0x7f8d84516c60> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key BarItem.
It looks like you have in storyboard/xib file some old outlet for key BarItem in you SecondViewController class. Probably you removed outlet from code programmatically, but outlet in storyboard/xib stays.

Related

performsegue to UINavigationController exception

My app functions correctly, but when I enable an "all exception" breakpoint it fails during this segue (gotoHome). If I bypass the navigation controller and go directly to the initial viewcontroller for the navigation controller the segue works fine with the breakpoint enabled.
I am not subclassing or overriding the UINavigationController. But like I said if I disable the exception breakpoint it works just fine, but I need to be able to enable this to be able to better debug other parts of the application.
Any help would be great.
viewDidAppear from initial StartupViewController. I have tried with and without the timer with same issue.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { t in
let u = XXXXXgetUsername()
let p = XXXXXgetPassword()
if (u == "" || p == "") {
self.performSegue(withIdentifier: "gotoLogin", sender: self)
} else {
if (getPIN() != "" && !pinVerified) {
self.performSegue(withIdentifier: "gotoPIN", sender: self)
} else {
//FAILS at this segue
self.performSegue(withIdentifier: "gotoHome", sender: self) //LINE 37
}
}
}
}
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000103ff8f11 libobjc.A.dylib`objc_exception_throw
frame #1: 0x0000000105702079 CoreFoundation`-[NSException raise] + 9
frame #2: 0x0000000103a17a63 Foundation`-[NSObject(NSKeyValueCoding)
setValue:forKey:] + 292
frame #3: 0x0000000106745117 UIKit`-[UIViewController setValue:forKey:] + 87
frame #4: 0x0000000106f6bea3 UIKit`-[UINibKeyValuePair apply] + 63
frame #5: 0x00000001056a53cd CoreFoundation`-[NSArray
makeObjectsPerformSelector:] + 317
frame #6: 0x0000000106a355d0 UIKit`-[UINib instantiateWithOwner:options:] +
1837
frame #7: 0x0000000106ec5fc2 UIKit`-[UIStoryboard
instantiateViewControllerWithIdentifier:] + 181
frame #8: 0x0000000106ed5874 UIKit`-[UIStoryboardSegueTemplate
instantiateOrFindDestinationViewControllerWithSender:] + 90
frame #9: 0x0000000106ed5ab8 UIKit`-[UIStoryboardSegueTemplate _perform:] + 52
frame #10: 0x0000000106750324 UIKit`-[UIViewController
performSegueWithIdentifier:sender:] + 99
* frame #11: 0x0000000102356516 XXXXXIOS`closure #1 in
StartupViewController.viewDidAppear(t=0x0000608000167ec0,
self=0x00007ffd4ed061d0) at StartupViewController.swift:37
frame #12: 0x00000001023565ea XXXXXIOS`partial apply for closure #1 in
StartupViewController.viewDidAppear(_:) at StartupViewController.swift:0
frame #13: 0x000000010222fcee XXXXXIOS`thunk for #callee_owned (#owned Timer)
-> () at SensorViewController.swift:0
frame #14: 0x0000000103a60b1e Foundation`__NSFireTimer + 83
frame #15: 0x0000000105692174
CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
frame #16: 0x0000000105691e32 CoreFoundation`__CFRunLoopDoTimer + 1026
frame #17: 0x00000001056919ea CoreFoundation`__CFRunLoopDoTimers + 266
frame #18: 0x0000000105689404 CoreFoundation`__CFRunLoopRun + 2308
frame #19: 0x0000000105688889 CoreFoundation`CFRunLoopRunSpecific + 409
frame #20: 0x000000010d3929c6 GraphicsServices`GSEventRunModal + 62
frame #21: 0x00000001065a55d6 UIKit`UIApplicationMain + 159
frame #22: 0x000000010243a2a7 XXXXXIOS`main at AppDelegate.swift:13
frame #23: 0x00000001093d6d81 libdyld.dylib`start + 1
I deleted the view in the storyboard a recreated and linked my view controller to the new view and the exception went away. Not sure what the error was but this solved it.

How to Pass Data Multiple Times from Parent View Controller to Container VC Child in Swift?

I have a button on ViewControllerA (Parent) that I want to update a variable inside of ViewControllerB (Child). ViewControllerB is a container view inside of ViewControllerA.
This is the variable in ViewControllerB I want to update multiple times from the Parent ViewControllerA button press:
#IBOutlet weak var childViewHeight: NSLayoutConstraint!
Because the child view, ViewControllerB, is connected by an embed segue, it seems I can only pass data from ViewControllerA to ViewControllerB once via the prepareForSegue method. The performSegue method causes the program to crash with a SIGABRT Error.
I know it is generally considered bad practice to try to update an IBOutlet from a separate class or view controller, but I need a way for a button press on ViewControllerA to change the height constraint for ViewControllerA and ViewControllerB simultaneously.
If this is impossible in my current approach, please give me another suggestion of how to redesign my app to make this possible.
Update - This is the code that causes the crash:
#IBAction func button(_ sender: AnyObject) {
performSegue(withIdentifier: "seg", sender: self)
}
Update - Here is the result when I type in "bt" in the debug console:
* thread #1: tid = 0x1fcdd, 0x000000010d9b1f06 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x000000010d9b1f06 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x000000010dad24ec libsystem_pthread.dylib`pthread_kill + 90
frame #2: 0x000000010d7040b3 libsystem_c.dylib`abort + 129
frame #3: 0x000000010d9d043a libc++abi.dylib`abort_message + 266
frame #4: 0x000000010d9f4a9f libc++abi.dylib`default_terminate_handler() + 267
frame #5: 0x000000010c7b559f libobjc.A.dylib`_objc_terminate() + 103
frame #6: 0x000000010d9f1c09 libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x000000010d9f1894 libc++abi.dylib`__cxa_rethrow + 99
frame #8: 0x000000010c7b54b7 libobjc.A.dylib`objc_exception_rethrow + 40
frame #9: 0x000000010a2eebf1 CoreFoundation`CFRunLoopRunSpecific + 433
frame #10: 0x000000010f6d7a48 GraphicsServices`GSEventRunModal + 161
frame #11: 0x000000010ad27e8b UIKit`UIApplicationMain + 159
* frame #12: 0x000000010a1c60cf ContainerVC2`main + 111 at AppDelegate.swift:12
frame #13: 0x000000010d6586bd libdyld.dylib`start + 1
Update - Here is the "bt" console output with the exception breakpoint in place:
* thread #1: tid = 0x219bd, 0x000000010afca2ee libobjc.A.dylib`objc_exception_throw, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010afca2ee libobjc.A.dylib`objc_exception_throw
frame #1: 0x0000000108b7dec2 CoreFoundation`+[NSException raise:format:arguments:] + 98
frame #2: 0x0000000109079455 Foundation`-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
frame #3: 0x0000000109f65309 UIKit`__67-[UIStoryboardEmbedSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 438
frame #4: 0x0000000109ce05e4 UIKit`-[UIStoryboardSegueTemplate _performWithDestinationViewController:sender:] + 453
frame #5: 0x0000000109ce03ee UIKit`-[UIStoryboardSegueTemplate _perform:] + 82
frame #6: 0x00000001096dc45b UIKit`-[UIViewController performSegueWithIdentifier:sender:] + 99
* frame #7: 0x00000001089d99b3 ContainerVC2`ViewController1.button(sender=0x00007fff57224658, self=0x00007fcddb707cb0) -> () + 131 at ViewController.swift:9
frame #8: 0x00000001089d9a26 ContainerVC2`#objc ViewController1.button(AnyObject) -> () + 54 at ViewController.swift:0
frame #9: 0x000000010953eb6f UIKit`-[UIApplication sendAction:to:from:forEvent:] + 83
frame #10: 0x00000001096bf927 UIKit`-[UIControl sendAction:to:forEvent:] + 67
frame #11: 0x00000001096bfc08 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 388
frame #12: 0x00000001096be6aa UIKit`-[UIControl touchesBegan:withEvent:] + 414
frame #13: 0x00000001095aabbd UIKit`-[UIWindow _sendTouchesForEvent:] + 1188
frame #14: 0x00000001095ac8d6 UIKit`-[UIWindow sendEvent:] + 3984
frame #15: 0x000000010955a1e1 UIKit`-[UIApplication sendEvent:] + 281
frame #16: 0x0000000109d1502f UIKit`__dispatchPreprocessedEventFromEventQueue + 3314
frame #17: 0x0000000109d0dc4e UIKit`__handleEventQueue + 4879
frame #18: 0x0000000108b1fcb1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #19: 0x0000000108b04c6c CoreFoundation`__CFRunLoopDoSources0 + 556
frame #20: 0x0000000108b04156 CoreFoundation`__CFRunLoopRun + 918
frame #21: 0x0000000108b03b5d CoreFoundation`CFRunLoopRunSpecific + 285
frame #22: 0x000000010deeca48 GraphicsServices`GSEventRunModal + 161
frame #23: 0x000000010953ce8b UIKit`UIApplicationMain + 159
frame #24: 0x00000001089db0cf ContainerVC2`main + 111 at AppDelegate.swift:12
frame #25: 0x000000010be6d6bd libdyld.dylib`start + 1
and here is the "bt" output after I hit the "continue program execution" button once:
* thread #1: tid = 0x219bd, 0x000000010c206607 libc++abi.dylib`__cxa_throw, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
frame #0: 0x000000010c206607 libc++abi.dylib`__cxa_throw
frame #1: 0x000000010afca443 libobjc.A.dylib`objc_exception_throw + 341
frame #2: 0x0000000108b7dec2 CoreFoundation`+[NSException raise:format:arguments:] + 98
frame #3: 0x0000000109079455 Foundation`-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
frame #4: 0x0000000109f65309 UIKit`__67-[UIStoryboardEmbedSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 438
frame #5: 0x0000000109ce05e4 UIKit`-[UIStoryboardSegueTemplate _performWithDestinationViewController:sender:] + 453
frame #6: 0x0000000109ce03ee UIKit`-[UIStoryboardSegueTemplate _perform:] + 82
frame #7: 0x00000001096dc45b UIKit`-[UIViewController performSegueWithIdentifier:sender:] + 99
* frame #8: 0x00000001089d99b3 ContainerVC2`ViewController1.button(sender=0x00007fff57224658, self=0x00007fcddb707cb0) -> () + 131 at ViewController.swift:9
frame #9: 0x00000001089d9a26 ContainerVC2`#objc ViewController1.button(AnyObject) -> () + 54 at ViewController.swift:0
frame #10: 0x000000010953eb6f UIKit`-[UIApplication sendAction:to:from:forEvent:] + 83
frame #11: 0x00000001096bf927 UIKit`-[UIControl sendAction:to:forEvent:] + 67
frame #12: 0x00000001096bfc08 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 388
frame #13: 0x00000001096be6aa UIKit`-[UIControl touchesBegan:withEvent:] + 414
frame #14: 0x00000001095aabbd UIKit`-[UIWindow _sendTouchesForEvent:] + 1188
frame #15: 0x00000001095ac8d6 UIKit`-[UIWindow sendEvent:] + 3984
frame #16: 0x000000010955a1e1 UIKit`-[UIApplication sendEvent:] + 281
frame #17: 0x0000000109d1502f UIKit`__dispatchPreprocessedEventFromEventQueue + 3314
frame #18: 0x0000000109d0dc4e UIKit`__handleEventQueue + 4879
frame #19: 0x0000000108b1fcb1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #20: 0x0000000108b04c6c CoreFoundation`__CFRunLoopDoSources0 + 556
frame #21: 0x0000000108b04156 CoreFoundation`__CFRunLoopRun + 918
frame #22: 0x0000000108b03b5d CoreFoundation`CFRunLoopRunSpecific + 285
frame #23: 0x000000010deeca48 GraphicsServices`GSEventRunModal + 161
frame #24: 0x000000010953ce8b UIKit`UIApplicationMain + 159
frame #25: 0x00000001089db0cf ContainerVC2`main + 111 at AppDelegate.swift:12
frame #26: 0x000000010be6d6bd libdyld.dylib`start + 1
UPDATE - prepareforsegue code:
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "seg" {
var vcB: ViewControllerB?
vcB = segue.desinationViewController as? ViewControllerB
}
You don't need to call performSegue for an embed segue. The embed segue is fired automatically when the containing view controller is loaded from the storyboard.
You can use prepareForSegue in the containing view controller to get a reference to the contained view controller (it will be the destinationViewController in the segue). Once you have the reference you can store it in a property and use that to interact with it. Rather than updating the constraint directly, I would suggest that you invoke a function on the view controller that updates its constraint:
class ViewControllerA: UIViewController {
var viewControllerB: ViewControllerB?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "seg" {
self.viewControllerB = segue.destinationViewController as? ViewControllerB
}
}
#IBAction func button(_ sender: AnyObject) {
self.viewControllerB?.doSomethingWithHeight(newHeight)
}
}
class ViewControllerB: UIViewController {
#IBOutlet weak var childViewHeight: NSLayoutConstraint!
func doSomethingWithHeight(newHeight: CGFloat) {
self.childViewHeight.constant = newHeight
}
}
At the point that prepare for segue is called, ViewController B's outlets have not been set yet. They are all nil and so trying to access one will cause a crash.
For what you are trying to do, the dirtiest approach is to change the layoutContraint's constant from inside view controller A by accessing it through the childViewControllers array of view controller A. You will have to cast the first element in the array (assuming you only have one child) into an object of the view controller B class.
The above is a very dirty way to do it, but it will get the job done until you can learn some more.
#IBAction buttonAction(sender: UIButton) {
if let viewControllerB = childViewControllers[0] as? ViewControllerB {
viewControllerB.childViewHeight.constant = 25.0
}
}
Again, this is a very dirty way to do it, but it will get the job done while you are learning the right way.
I've been asked why the above is such a bad idea...
Imagine that you didn't write the app in question, and you are tasked with fixing a bug with the constraint's constant. The first thing you would need to do to fix the bug would be to find all the places that mutate that constant.
In an ideal world, that constant would only be mutated in one place (I have a single method in my ViewController class called updateUI that handles all the IBOutlet mutation.) If that is the case, then fixing the bug will just be a matter of understanding the one function where the constant is getting changed.
The next best situation is that there is only one class that changes the constraint's constant. Then all you have to do to fix the bug is to understand how the class works. A larger task that understanding a single function, but doable.
However, using the code above means that there are multiple classes that adjust the constraint's constant, and if there are two classes doing it, who's to say there aren't more? In this case, fixing the bug requires an understanding of the entire app.
A better way to do it...
Presumably, you have multiple view controllers on the screen that are interconnected in some way through your Model code. The model represents your source of truth. Your two view controllers should be getting notified when the model changes and update themselves and their views accordingly. If you don't have a model representing the abstraction that is affecting these two views, then you should make one.

Navigation to Different view results in SIGABRT error

I am new to Objective C, and cannot figure out the error I am facing right now. The app was developed by some other developer few years back, and I just have to change some images and upload back as new version (and underline API/webservice got updated). Everything was done fine, but one button in app is causing a crash.
We have two button in our main interface, one shows the listing near by user location, which works, and we have another to show all listing. The calling method for them is same, but when we use Show all listing interface in code it crash application with no error. in Debugger it shows (lldb) and generate SIGABRT in main appdelegate call.
Here is the button code
-(IBAction)btnAllResturantAction:(id)sender
{
[btnAllRestaruant setImage:[UIImage imageNamed:#"all_restaurants_tapped.png"] forState:UIControlStateNormal];
NSLog(#"SearchView : Button CLick for All Resturant");
#try {
HomeViewController *homeView1=[[HomeViewController alloc]initWithNibName:#"HomeViewController" bundle:nil];
[self.navigationController pushViewController:homeView1 animated:YES];
NSLog(#"SearchView: Button CLick complete");
} #catch (NSException *exception){
NSLog(#"Search View: Exception in All Resturant %#", exception.reason);
}
}
When in line by line debug, I can see Log message of "Button Click complete" visible in debugger window, but just after that it fail and crash application, I didn't see any other error message even after I try bt in Debugger window, it shows all framework code. Here is bt result anyways
* thread #1: tid = 0x129d3, 0x0464e62a libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x0464e62a libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x04617664 libsystem_pthread.dylib`pthread_kill + 101
frame #2: 0x043c539d libsystem_c.dylib`abort + 156
frame #3: 0x002ff065 project6`uncaught_exception_handler + 38
frame #4: 0x03eabebe CoreFoundation`__handleUncaughtException + 830
frame #5: 0x0396d0ae libobjc.A.dylib`_objc_terminate() + 100
frame #6: 0x04687d0d libc++abi.dylib`std::__terminate(void (*)()) + 14
frame #7: 0x0468793e libc++abi.dylib`__cxa_rethrow + 103
frame #8: 0x0396cfad libobjc.A.dylib`objc_exception_rethrow + 47
frame #9: 0x03dba7d0 CoreFoundation`CFRunLoopRunSpecific + 672
frame #10: 0x03dba51b CoreFoundation`CFRunLoopRunInMode + 123
frame #11: 0x056ef664 GraphicsServices`GSEventRunModal + 192
frame #12: 0x056ef4a1 GraphicsServices`GSEventRun + 104
frame #13: 0x006941eb UIKit`UIApplicationMain + 160
frame #14: 0x000abf7a project6`main(argc=1, argv=0xbff5587c) + 138 at main.m:14
frame #15: 0x0431ea21 libdyld.dylib`start + 1
Can you guide me where and how I look for error, with this information.
EDIT:
I add Exception Breakpoint which generate this bt
(lldb) bt
thread #1: tid = 0x1368d, 0x03996dd0 libobjc.A.dylib`objc_exception_throw, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
frame #0: 0x03996dd0 libobjc.A.dylib`objc_exception_throw
frame #1: 0x03ed59ad CoreFoundation`+[NSException raise:format:] + 141
frame #2: 0x008873cb UIKit`-[UIViewController _loadViewFromNibNamed:bundle:] + 740
frame #3: 0x00887ccc UIKit`-[UIViewController loadView] + 189
frame #4: 0x008880d8 UIKit`-[UIViewController loadViewIfRequired] + 154
frame #5: 0x0088ebde UIKit`-[UIViewController __viewWillAppear:] + 114
frame #6: 0x008b1d37 UIKit`-[UIViewController(UIContainerViewControllerProtectedMethods) beginAppearanceTransition:animated:] + 202
frame #7: 0x008c4009 UIKit`-[UINavigationController _startCustomTransition:] + 1389
frame #8: 0x008d5bf5 UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 803
frame #9: 0x008d6e3b UIKit`-[UINavigationController __viewWillLayoutSubviews] + 68
frame #10: 0x00ab2193 UIKit`-[UILayoutContainerView layoutSubviews] + 252
frame #11: 0x00787eb7 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 813
frame #12: 0x039ab059 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
frame #13: 0x0586780a QuartzCore`-[CALayer layoutSublayers] + 144
frame #14: 0x0585b4ee QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 388
frame #15: 0x0585b352 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 26
frame #16: 0x0584de8b QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 317
frame #17: 0x05881e03 QuartzCore`CA::Transaction::commit() + 561
frame #18: 0x05883674 QuartzCore`CA::Transaction::flush_transaction() + 50
frame #19: 0x006b7f0a UIKit`_UIApplicationHandleEventQueue + 8398
frame #20: 0x03defd1f CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
frame #21: 0x03de59ab CoreFoundation`__CFRunLoopDoSources0 + 523
frame #22: 0x03de4dc8 CoreFoundation`__CFRunLoopRun + 1032
frame #23: 0x03de4706 CoreFoundation`CFRunLoopRunSpecific + 470
frame #24: 0x03de451b CoreFoundation`CFRunLoopRunInMode + 123
frame #25: 0x05719664 GraphicsServices`GSEventRunModal + 192
frame #26: 0x057194a1 GraphicsServices`GSEventRun + 104
frame #27: 0x006be1eb UIKit`UIApplicationMain + 160
frame #28: 0x000d5f7a project6`main(argc=1, argv=0xbff2b87c) + 138 at main.m:14
frame #29: 0x04348a21 libdyld.dylib`start + 1

EXC_BAD_ACCESS tapping uisearchbar three times

I am trying to implement a search bar in a UICollectionView as a UICollectionViewReusableView
This way I am not using a UISearchController but I am changing the datasource of the collectionview
In my custom layout I am adding the searchbar this way:
override func prepareLayout() {
super.prepareLayout()
var searchBarAttributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: TeacherSearchbarIdentifier, withIndexPath: NSIndexPath(forItem: 0, inSection: 0))
searchBarAttributes.frame = CGRectMake(0, 0, collectionViewContentSize().width, 44)
searchBarAttributes.zIndex = 100
miscAttributes.append(searchBarAttributes)
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
var attributes = [UICollectionViewLayoutAttributes]()
for (idx, attr) in enumerate(miscAttributes) {
if CGRectIntersection(rect, attr.frame) != CGRectNull {
attributes.append(attr)
}
}
return attributes
}
I am setting the delegate like this:
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
var view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: kind, forIndexPath: indexPath) as! UICollectionReusableView
if kind == TeacherSearchbarIdentifier {
controller.searchBar = (view as! TeacherSearchView).searchBar
return view
}
}
The variable controller is the UICollectionViewController which implements the UISearchBarDelegate Protocol
The delegate is set in didSet of the searchBar variable. These are my delegates:
override func scrollViewDidScroll(scrollView: UIScrollView) {
self.view.endEditing(true)
}
func searchBarShouldBeginEditing(searchBar: UISearchBar) -> Bool {
searchBar.setShowsCancelButton(true, animated: true)
return true
}
func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool {
searchBar.setShowsCancelButton(false, animated: true)
searchBar.resignFirstResponder()
return true
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.setShowsCancelButton(false, animated: true)
searchBar.resignFirstResponder()
}
Now my problem!
When I am tapping on the search bar, the keyboard appears. If I press the cancel button or scroll, it dissappears. Just as I want it to. This also works a second time.
BUT!
If I do this a third time, I get a EXC_BAD_ACCESS:
I tried turning on Enabling Zombie Objects, but no information was provided.
I also tried profiling for Zombie Objects, it just crashes without any noticeable information.
Please help me on how I can resolve this error, or give me further debugging instructions.
EDIT 1:
Here is the output from bt all in the lldb debugger:
* thread #1: tid = 0x228fc, 0x000000019502fbd0 libobjc.A.dylib`objc_msgSend + 16, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1cda8beb8)
frame #0: 0x000000019502fbd0 libobjc.A.dylib`objc_msgSend + 16
frame #1: 0x000000018328b2f4 CoreFoundation`-[__NSDictionaryM objectForKey:] + 84
frame #2: 0x00000001884a21b8 UIKit`-[UICollectionView _visibleViewDictForElementCategory:elementKind:] + 96
frame #3: 0x0000000187ff6644 UIKit`-[UICollectionView _indexPathForView:ofType:] + 160
frame #4: 0x000000018849c3dc UIKit`-[UICollectionView _setIsAncestorOfFirstResponder:] + 792
frame #5: 0x0000000187ed9418 UIKit`+[UIView(Internal) _setIsResponderAncestorOfFirstResponder:startingAtFirstResponder:] + 164
frame #6: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #7: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #8: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #9: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #10: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #11: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #12: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #13: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #14: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #15: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #16: 0x0000000187ed925c UIKit`-[UIResponder(Static) _setFirstResponder:] + 56
frame #17: 0x0000000187f1b194 UIKit`-[UITextField _becomeFirstResponder] + 60
frame #18: 0x000000018800f300 UIKit`-[UISearchBarTextField _becomeFirstResponder] + 108
frame #19: 0x0000000187e9ad28 UIKit`-[UIResponder becomeFirstResponder] + 392
frame #20: 0x0000000187e9b0ac UIKit`-[UIView(Hierarchy) becomeFirstResponder] + 124
frame #21: 0x0000000187f19de4 UIKit`-[UITextField becomeFirstResponder] + 68
frame #22: 0x0000000187fc9fc4 UIKit`-[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setFirstResponderIfNecessary] + 200
frame #23: 0x0000000187fc962c UIKit`-[UITextInteractionAssistant(UITextInteractionAssistant_Internal) oneFingerTap:] + 1736
frame #24: 0x0000000187faf070 UIKit`_UIGestureRecognizerSendActions + 276
frame #25: 0x0000000187e486b4 UIKit`-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 580
frame #26: 0x00000001882b938c UIKit`___UIGestureRecognizerUpdate_block_invoke662 + 60
frame #27: 0x0000000187e0c418 UIKit`_UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 292
frame #28: 0x0000000187e0a7c4 UIKit`_UIGestureRecognizerUpdate + 2504
frame #29: 0x0000000187e4682c UIKit`-[UIWindow _sendGesturesForEvent:] + 1044
frame #30: 0x0000000187e45ee4 UIKit`-[UIWindow sendEvent:] + 660
frame #31: 0x0000000187e19120 UIKit`-[UIApplication sendEvent:] + 264
frame #32: 0x00000001880ba2b8 UIKit`_UIApplicationHandleEventFromQueueEvent + 15424
frame #33: 0x0000000187e17634 UIKit`_UIApplicationHandleEventQueue + 1716
frame #34: 0x0000000183358240 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
frame #35: 0x00000001833574e4 CoreFoundation`__CFRunLoopDoSources0 + 264
frame #36: 0x0000000183355594 CoreFoundation`__CFRunLoopRun + 712
frame #37: 0x00000001832812d4 CoreFoundation`CFRunLoopRunSpecific + 396
frame #38: 0x000000018ccdf6fc GraphicsServices`GSEventRunModal + 168
frame #39: 0x0000000187e7ef40 UIKit`UIApplicationMain + 1488
* frame #40: 0x00000001000f0798 My-Project`main + 164 at AppDelegate.swift:14
frame #41: 0x00000001956c6a08 libdyld.dylib`start + 4
thread #2: tid = 0x22939, 0x00000001957c4c24 libsystem_kernel.dylib`kevent64 + 8, queue = 'com.apple.libdispatch-manager'
frame #0: 0x00000001957c4c24 libsystem_kernel.dylib`kevent64 + 8
frame #1: 0x000000010083a588 libdispatch.dylib`_dispatch_mgr_invoke + 276
frame #2: 0x000000010082b09c libdispatch.dylib`_dispatch_mgr_thread + 52
thread #8: tid = 0x229d9, 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #0: 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #1: 0x00000001958792dc libsystem_pthread.dylib`_pthread_wqthread + 992
thread #7: tid = 0x229da, 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #0: 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #1: 0x00000001958792dc libsystem_pthread.dylib`_pthread_wqthread + 992
thread #9: tid = 0x229df, 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #0: 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #1: 0x00000001958792dc libsystem_pthread.dylib`_pthread_wqthread + 992
thread #10: tid = 0x229e1, 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #0: 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #1: 0x00000001958792dc libsystem_pthread.dylib`_pthread_wqthread + 992
thread #11: tid = 0x229e2, 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #0: 0x00000001957dfc78 libsystem_kernel.dylib`__workq_kernreturn + 8
frame #1: 0x00000001958792dc libsystem_pthread.dylib`_pthread_wqthread + 992
thread #12: tid = 0x229e3, 0x00000001957c4e0c libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.NSURLConnectionLoader'
frame #0: 0x00000001957c4e0c libsystem_kernel.dylib`mach_msg_trap + 8
frame #1: 0x00000001957c4c88 libsystem_kernel.dylib`mach_msg + 72
frame #2: 0x0000000183357724 CoreFoundation`__CFRunLoopServiceMachPort + 200
frame #3: 0x0000000183355678 CoreFoundation`__CFRunLoopRun + 940
frame #4: 0x00000001832812d4 CoreFoundation`CFRunLoopRunSpecific + 396
frame #5: 0x0000000182d5e594 CFNetwork`+[NSURLConnection(Loader) _resourceLoadLoop:] + 440
frame #6: 0x00000001842a1db8 Foundation`__NSThread__main__ + 1072
frame #7: 0x000000019587bdc8 libsystem_pthread.dylib`_pthread_body + 164
frame #8: 0x000000019587bd24 libsystem_pthread.dylib`_pthread_start + 160
thread #13: tid = 0x229e6, 0x00000001957df498 libsystem_kernel.dylib`__select + 8, name = 'com.apple.CFSocket.private'
frame #0: 0x00000001957df498 libsystem_kernel.dylib`__select + 8
frame #1: 0x000000018335d128 CoreFoundation`__CFSocketManager + 672
frame #2: 0x000000019587bdc8 libsystem_pthread.dylib`_pthread_body + 164
frame #3: 0x000000019587bd24 libsystem_pthread.dylib`_pthread_start + 160
EDIT 2:
I created a standalone project which produces this error. Just run the project and tap/cancel the searchbar a few times.
Download Project
Video:
Bugreport: rdar://problem/21673802
I came up with a workaround for this in iOS 8. I discovered that the crash only occurred if the kind string of my supplementary view was a Swift string. There was no crash when I used an Objective-C string bridged to Swift. I tried the obvious idea of creating a NSString explicitly in Swift and even tried creating a CFString in Swift and bridging that. However, neither of those efforts were successful.
To easily verify this, try changing TeacherSearchbarIdentifier to an Objective-C string from UIKit like UICollectionElementKindSectionHeader.
A more rigorous workaround would involve creating Objective-C strings for your use case and exposing those to Swift. As an example:
// MyElementKinds.h
#import Foundation;
FOUNDATION_EXPORT NSString *const TeacherSearchbarIdentifier;
// MyElementKinds.m
#import "MyElementKinds.h"
NSString *const TeacherSearchbarIdentifier = #"TeacherSearchbarIdentifier";
I committed a bug report to apple, and they said this:
Apple Developer Relations
Thanks for the update. Upgrading is the solution then.
We are closing this bug report.
If you have questions regarding the resolution of this issue, please
update your bug report with that information.
Please be sure to regularly check new Apple releases for any updates
that might affect this issue.
Basically they don't care about this issue right now because of their upcoming release of iOS 9
I asked what the correct way is to keep compatibility to iOS 8 and the bug report is still open. Let's wait and see!

[UIView _forgetDependentConstraint:]: message sent to deallocated instance

I tried using NSZobie and all others. Still i face issues. can't able to find where app crashed. Please Help. thanks in advance.
*** -[UIView _forgetDependentConstraint:]: message sent to deallocated instance 0x208e0010
(lldb) bt
* thread #1: tid = 0x2503, 0x342b3468 CoreFoundation`___forwarding___ + 192, stop reason = EXC_BREAKPOINT (code=EXC_ARM_B`enter code here`REAKPOINT, subcode=0xdefe)
frame #0: 0x342b3468 CoreFoundation`___forwarding___ + 192
frame #1: 0x3420af68 CoreFoundation`__forwarding_prep_0___ + 24
frame #2: 0x364f24ba UIKit`_updateViewDependenciesForConstraint + 202
frame #3: 0x364f9a2c UIKit`__72-[UIView(AdditionalLayoutSupport) _removeRelevantConstraintsFromEngine:]_block_invoke_0 + 264
frame #4: 0x34c65882 Foundation`-[NSISEngine withAutomaticOptimizationDisabled:] + 166
frame #5: 0x364f98ee UIKit`-[UIView(AdditionalLayoutSupport) _removeRelevantConstraintsFromEngine:] + 94
frame #6: 0x3629f4a0 UIKit`__UIViewWillBeRemovedFromSuperview + 588
frame #7: 0x360e7848 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 56
frame #8: 0x36137f18 UIKit`-[UINavigationTransitionView _cleanupTransition] + 92
frame #9: 0x360ceab2 UIKit`-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 158
frame #10: 0x361438ee UIKit`-[UIViewAnimationState animationDidStop:finished:] + 50
frame #11: 0x35e78c00 QuartzCore`CA::Layer::run_animation_callbacks(void*) + 208
frame #12: 0x3c3f04b6 libdispatch.dylib`_dispatch_client_callout + 22
frame #13: 0x3c3f51bc libdispatch.dylib`_dispatch_main_queue_callback_4CF$VARIANT$mp + 224
frame #14: 0x34284f3a CoreFoundation`__CFRunLoopRun + 1290
frame #15: 0x341f7ebc CoreFoundation`CFRunLoopRunSpecific + 356
frame #16: 0x341f7d48 CoreFoundation`CFRunLoopRunInMode + 104
frame #17: 0x37dd02ea GraphicsServices`GSEventRunModal + 74
frame #18: 0x3610d300 UIKit`UIApplicationMain + 1120
frame #19: 0x000521de MyApp®`main(argc=1, argv=0x2fdb3cf8) + 162 at main.m:6
frame #20: 0x3c410b20 libdyld.dylib`start + 4
Check if you have UIAlertView or animations in view before came back to your view. It seems you are initalize a view with it's local variable, wihout having express use self delegate, or you use removeFromSuperview for a view while actions still call it after remove.

Resources