SwiftKickMobile / SwiftMessages

A very flexible message bar for UIKit and SwiftUI.
MIT License
7.33k stars 747 forks source link

Crash When opening Swift Messages #286

Closed viveksinghmehta closed 5 years ago

viveksinghmehta commented 5 years ago

2019-03-03 13:08:12.746937+0530 Bill Store[6852:58753] Assertion failure in -[UICollectionViewFlowLayout _getSizingInfosWithExistingSizingDictionary:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.93.8/UICollectionViewFlowLayout.m:1432 2019-03-03 13:08:12.751492+0530 Bill Store[6852:58753] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'negative sizes are not supported in the flow layout' *** First throw call stack: ( 0 CoreFoundation 0x00000001126451bb __exceptionPreprocess + 331 1 libobjc.A.dylib 0x0000000111be3735 objc_exception_throw + 48 2 CoreFoundation 0x0000000112644f42 +[NSException raise:format:arguments:] + 98 3 Foundation 0x0000000110a61877 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 194 4 UIKitCore 0x00000001167fe7e9 -[UICollectionViewFlowLayout _getSizingInfosWithExistingSizingDictionary:] + 3424 5 UIKitCore 0x00000001167fffc4 -[UICollectionViewFlowLayout _fetchItemsInfoForRect:] + 231 6 UIKitCore 0x00000001167f8f74 -[UICollectionViewFlowLayout collectionViewContentSize] + 49 7 UIKitCore 0x00000001167efe14 -[UICollectionViewData _validateContentSize] + 180 8 UIKitCore 0x00000001167effb2 -[UICollectionViewData _prepareToLoadData] + 276 9 UIKitCore 0x00000001167f09fb -[UICollectionViewData validateLayoutInRect:] + 53 10 UIKitCore 0x00000001167bf00e -[UICollectionView layoutSubviews] + 260 11 UIKitCore 0x000000011744c795 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1441 12 QuartzCore 0x0000000111358b19 -[CALayer layoutSublayers] + 175 13 QuartzCore 0x000000011135d9d3 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 395 14 UIKitCore 0x0000000117437077 -[UIView(Hierarchy) layoutBelowIfNeeded] + 1429 15 SwiftMessages 0x0000000111a546b6 $S13SwiftMessages18TopBottomAnimationC7install7contextyAA0E7ContextC_tF + 1830 16 SwiftMessages 0x0000000111a533b1 $S13SwiftMessages18TopBottomAnimationC4show7context10completionyAA0E7ContextC_ySbctF + 577 17 SwiftMessages 0x0000000111a5840e $S13SwiftMessages18TopBottomAnimationCAA8AnimatorA2aDP4show7context10completionyAA0E7ContextC_ySbctFTW + 30 18 SwiftMessages 0x0000000111a2df4d $S13SwiftMessages9PresenterC13showAnimation33_9240CA0FAD7C4E3A99020B5AAC45D767LL10completionyySbc_tF + 285 19 SwiftMessages 0x0000000111a2d96a $S13SwiftMessages9PresenterC4show10completionyySbc_tKF + 682 20 SwiftMessages 0x0000000111a3e9c8 $S13SwiftMessagesAAC11dequeueNext33AB28F0CA9BFF0B16E059C4C20EF9AFAALLyyFyycfU + 392 21 SwiftMessages 0x0000000111a47a81 $S13SwiftMessagesAAC11dequeueNext33_AB28F0CA9BFF0B16E059C4C20EF9AFAALLyyFyycfU_TA + 17 22 SwiftMessages 0x0000000111a2095d $SIeg_IeyB_TR + 45 23 libdispatch.dylib 0x0000000113688595 _dispatch_call_block_and_release + 12 24 libdispatch.dylib 0x0000000113689602 _dispatch_client_callout + 8 25 libdispatch.dylib 0x000000011369699a _dispatch_main_queue_callback_4CF + 1541 26 CoreFoundation 0x00000001125aa3e9 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 9 27 CoreFoundation 0x00000001125a4a76 __CFRunLoopRun + 2342 28 CoreFoundation 0x00000001125a3e11 CFRunLoopRunSpecific + 625 29 GraphicsServices 0x000000011a8981dd GSEventRunModal + 62 30 UIKitCore 0x0000000116f6281d UIApplicationMain + 140 31 Bill Store 0x000000010f9edf37 main + 71 32 libdyld.dylib 0x00000001136ff575 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

viveksinghmehta commented 5 years ago

Crashes when opening Swift messages, it always says Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'negative sizes are not supported in the flow layout' but the size of the collection view cell is not negative.

wtmoose commented 5 years ago

Are you showing a collection view with SwiftMessages? I need to see the code.

viveksinghmehta commented 5 years ago

import UIKit import SwiftMessages

class MainVC: UIViewController {

@IBOutlet weak var dashBoardCollectionView: UICollectionView! {
    didSet {
        dashBoardCollectionView.delegate = self
        dashBoardCollectionView.dataSource = self
    }
}

let identifier = "cell"
private let optionsArray = ["Estimates", "Invoices", "Payments", "Clients", "Products", "Live Chat"]
private let imageArray = [#imageLiteral(resourceName: "analytics"), #imageLiteral(resourceName: "page"), #imageLiteral(resourceName: "piggy-bank"), #imageLiteral(resourceName: "promotion"), #imageLiteral(resourceName: "piggy-bank"), #imageLiteral(resourceName: "money-bag")]

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

@IBAction func notifications(_ sender: UIButton) {
    var config = SwiftMessages.Config()
    config.interactiveHide = true
    config.presentationStyle = .top
    config.duration = .seconds(seconds: 3)

    let message = MessageView.viewFromNib(layout: .cardView)
    message.configureTheme(.success)
    message.button?.isHidden = true
    message.configureContent(title: "Bill Store", body: "Notification")
    message.configureDropShadow()

    SwiftMessages.show(config: config, view: view)
}

@IBAction func settings(_ sender: UIButton) {
    showSuccess(body: "Settings button is pressed")
}

}

extension MainVC : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 6 }

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! DashBoardCell
    cell.layer.cornerRadius = 10.0
    cell.textLabel.text = optionsArray[indexPath.row]
    cell.iconImage.image = imageArray[indexPath.row]
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    print(collectionView.frame.width / 2.1)
    print((collectionView.frame.height / 3) - 10)
    return CGSize(width: collectionView.frame.width / 2.1, height: (collectionView.frame.height / 3) - 10)
}

}

wtmoose commented 5 years ago

Try setting config.presentationContext = .window(windowLevel: .normal).

viveksinghmehta commented 5 years ago

Nothing same error

wtmoose commented 5 years ago

OK. That is a pretty clear sign that your error has nothing to do with SwiftMessages. That setting displays the message in a separate window.

viveksinghmehta commented 5 years ago

It only crashes when I open swift messages. Any suggestions what should I do to make it show.

viveksinghmehta commented 5 years ago

Now I have removed collection view but still the messages does not appears, simulator screen shot - iphone 7 - 2019-03-08 at 22 15 51 this is what it does

wtmoose commented 5 years ago

Your message view probably doesn't have a height.

viveksinghmehta commented 5 years ago

I removed the config and just used the message then it's showing, but when I use SwiftMessages.defaultConfig it is crashing in file WindowViewController.swift. and code is extension WindowViewController { static func newInstance(windowLevel: UIWindow.level?, config: Swiftmessages.Config) -> WindowViewController { return config.windowViewController?(windowLevel, config) ?? WindowViewControler(windowLevel: windowLevel, config: config) }

deshan commented 5 years ago

With latest updates mine also crashes.

Without this line it works var config = SwiftMessages.Config()

Coeur commented 5 years ago

I tested your code, @viveksinghmehta. I did reproduce a crash, but it's because:

  1. presenting the SwiftMessages will call TopBottomAnimation.install(context:)
  2. which calls container.layoutIfNeeded()
  3. which calls your collectionView(_:layout:sizeForItemAt:)
  4. which calculates (collectionView.frame.height / 3) - 10 at a time where your own MainVC.view has a size of CGSize(width: 414, height: 0) (on iPhone XR), meaning that your collectionView.frame is likely also compressed with a height of 0 and your resulting maths returns a negative size.

I do not know if the one to blame is your maths (you could return max(0, (collectionView.frame.height / 3) - 10) to be safe) or if there is a bug in the animation and the view shouldn't be compressed to a height of 0.

Coeur commented 5 years ago

@viveksinghmehta @deshan @wtmoose I've reduced the code needed to reproduce the issue to:

import UIKit
import SwiftMessages

class ViewController: UIViewController {

    @IBAction func notifications(_ sender: UIButton) {
        var config = SwiftMessages.Config()
        config.duration = .seconds(seconds: 3)

        let message = MessageView.viewFromNib(layout: .cardView)
        message.configureTheme(.success)
        message.button?.isHidden = true
        message.configureContent(title: "My Title", body: "Notification")
        message.configureDropShadow()

        SwiftMessages.show(config: config, view: view)
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        return collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = CGSize(width: collectionView.frame.width / 2.1, height: (collectionView.frame.height / 3) - 10)
        print(size)
        return size
    }
}

And I made a sample at: https://github.com/Coeur/SwiftMessages-286 I'll let you investigate.

Note that with my MCVE, I was able to reproduce the issue down to SwiftMessages 3.0.0 (older versions require Swift 2.x, so I can't test them). So if it's a bug from the framework, it's at least like that since year 2016.

ShimaaMagdii commented 5 years ago

@Coeur I experienced the same crash just if i tried to change in the default config or use custom one.

Coeur commented 5 years ago

@ShimaaMagdii your message is unclear to me:

CodingAleCR commented 5 years ago

I am experiencing the same issues when using a custom config, if I call the SwiftMessages.show(:view) then it works, but whenever I pass a custom config onto the show method it crashes. And the worst thing is that it crashes even when not modifying the defaultConfig var

wtmoose commented 5 years ago

@CodingAleCR send me a sample project that crashes and I'll take a look.

CodingAleCR commented 5 years ago

It's propietary so I can't send it to you, but I'll see if I can set it up in a different project and let you know. Thanks!

Coeur commented 5 years ago

@wtmoose There is a sample in my post above already, that matches the use case of the issue author: https://github.com/SwiftKickMobile/SwiftMessages/issues/286#issuecomment-477861819

The problem being that the whole view controller height is reduce to zero when there is a UICollectionViewDelegate, so if there is anything that requires a minimum positive height somewhere, it will not support that compression and crash.

CodingAleCR commented 5 years ago

So my issue was regarding the swift version my project needed (Swift 4) I used version 5.0.1 of SwiftMessages and worked like a charm. I'll update my project as soon as I can. Thanks again for every bit of help.

wtmoose commented 5 years ago

@Coeur thanks for supplying the sample project (I had to look up MCVE).

@IBAction func notifications(_ sender: UIButton) {
    var config = SwiftMessages.Config()
    config.interactiveHide = true
    config.presentationStyle = .top
    config.duration = .seconds(seconds: 3)

    let message = MessageView.viewFromNib(layout: .cardView)
    message.configureTheme(.success)
    message.button?.isHidden = true
    message.configureContent(title: "Bill Store", body: "Notification")
    message.configureDropShadow()

    SwiftMessages.show(config: config, view: view)
}

@viveksinghmehta you're attempting to display your view controller's view as a message, causing it to be relocated in the view hierarchy in such a way that the height is zero and your collection view code crashes. Try changing the last line to the following.

    SwiftMessages.show(config: config, view: message)