EXC_BAD_ACCESS tapping uisearchbar three times
Asked Answered
H

2

32

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:

EXC_BAD_ACCESS (code=1, address=0x14ac0beb8)

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:

Short gif showing crash

Bugreport: rdar://problem/21673802

Hardtop answered 28/6, 2015 at 10:37 Comment(27)
Post the debugger outputContraband
@Buster there is no output in the consoleHardtop
When you get the crash the debugger should say (lldb). At that point type bt all and post the result.Eocene
@Eocene I edited my question adding the outputHardtop
I am not able to reproduce this. Can you provide a standalone empty project where this crash occurs?Eocene
Okay I will create one, it will come back to you later todayHardtop
@Eocene I added a download link at the bottomHardtop
Conclusion: 1 shouldn't tap cancel 3 times :)Gantrisin
@user3351949 good idea ;) unfortunately if you search, exit searchbar, search again a few times the app crashesHardtop
@PNGamingPower Lets call it a feature ;) Like fast way to exit an app BTW I will take look on it, hope I will help ... It will take a time .. I have 0 simulators installed :(Gantrisin
@PNGamingPower If you could track whether the next click will crash you could rename cancel to QUITGantrisin
From the backtrace it looks like a bug in the UIResponder chain. I'm still investigating.Eocene
Should i radar a possible bug?Hardtop
@PNGamingPower Definitely. If it's not a bug, at least Apple will tell you where the problem is. I'm still trying to figure this out as well.Eocene
@Eocene I reported a bug, lets see how Apple respondsHardtop
I converted your project to Swift2 because I only have Xcode 7 on El Capitan and everything was working fine no crashes at all. However, there is one bug inside of func filterUsingString(filter: String) in TeachersDataManager because you aren't using the filteredItems array you create check it out. I tried using the search bar and things didnt filter in the search but however many times I click the bar it doesn't crashOvercrop
Keep in mind that they probably won't get to your bug report until Wednesdayish if you're lucky, based on my previous experience with the bug reporter.Grief
Oh. i want to try your code but i can't, i only have xcode 6.2. :(Catling
I don't yet understand why, but the problem exists because your search bar is added as a supplementary view to your collection view. If you change your UICollectionViewController to UIViewController and add search bar above your collection view then everything works fine. Might be a solution as long as you are happy with the fact that it will not scroll with your collection view :)Vaso
Off topic, but this is a good way to find the cause of these crashes. natashatherobot.com/xcode-debugging-trickRosarosabel
hey can you attach a sample project?Captious
@SaqibSaud there is a download link above the video at the bottom of the questionHardtop
I would keep stripping the project down to the point where it stops crashing and then you can build it back up. You could commit each strip down so you can build it back up easily. my hunch is the UI setup when the search bar resigns it triggers the collection view to find a new first responder. Good luckAnhydride
@PNGamingPower did Apple respond to your bug report?Eocene
@Eocene actually yes they did... Last night. They ask me to test it with iOS 9 beta. I will give it a shotHardtop
Like @ManavGabhawala said, it works in iOS 9. Let's see what Apple tells us nowHardtop
@Eocene alright they closed the bug report, telling us upgrading to iOS 9 is the solution. I am not happy with this answer but what everHardtop
B
1

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";
Barcroft answered 25/4, 2016 at 0:32 Comment(1)
Thank you for your answer. I will eventually take a look into itHardtop
H
1

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!

Hardtop answered 27/7, 2015 at 8:34 Comment(7)
Did Apple ever get back to you about fixing this on iOS 8?Eocene
No they did not. It is marked as an open bug report and the order of the messages inside the issue is wrong, I think something messed up thereHardtop
No i didn't. Do you want me to add it?Hardtop
Yes please! It will help other devs who encounter the same issue. Thank you.Eocene
Openradar: rdar://problem/21673802Hardtop
What happened to this issue? Did Apple get back?Canaday
@Canaday they closed the bug report because it is not present in iOS 9 anymore, without providing a solution for iOS 8Hardtop
B
1

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";
Barcroft answered 25/4, 2016 at 0:32 Comment(1)
Thank you for your answer. I will eventually take a look into itHardtop

© 2022 - 2024 — McMap. All rights reserved.