LeoNatan / LNPopupController

A framework for presenting view controllers as popups of other view controllers, much like the Apple Music and Podcasts apps.
MIT License
3.03k stars 340 forks source link

Crash on Startup ios 12.1 #306

Closed zaidfadhil closed 5 years ago

zaidfadhil commented 5 years ago

im having a crash on start up , im using version 2.6.1

-[Project.TabBarVC _ln_addChildViewController:]: unrecognized selector sent to instance 0x7fd8ff058000

screen shot 2018-11-07 at 10 08 05 am

iOS 12.1 Xcode 10.1 Swift 4.2

LeoNatan commented 5 years ago

I am unable to reproduce. Please upload a small demo project that reproduces the issue.

wiencheck commented 5 years ago

I have the same exact issue, it was working fine on 2.5.27 zrzut ekranu 2018-11-07 o 13 07 36

func setPopupViewController() {
        guard let miniVC = Storyboard.miniPlayer.instantiate() as? MiniPlayerViewController, let walkRootVC = Storyboard.WalkPlayer.root.instantiate() as? WalkRootViewController else {
            return
        }
        miniVC.onHamburgerPress = { [weak self] in
            self?.onHamburgerPress?()
        }
        miniVC.onItemPress = { [weak self] in
            self?.openPopup(animated: true, completion: nil)
        }
        popupBar.customBarViewController = miniVC
        popupBar.inheritsVisualStyleFromDockingView = false
        popupContentView.popupInteractionGestureRecognizer.delegate = walkRootVC
        popupBar.isTranslucent = true
        popupBar.subviews.first(where: {$0 is UIVisualEffectView})?.isHidden = true
        popupBar.clipsToBounds = false
        popupBar.backgroundColor = .clear

        popupContentView.popupCloseButtonStyle = .none
        popupInteractionStyle = .snap

        walkRootVC.onPopupClose = { [weak self] in
            self?.closePopup(animated: true, completion: nil)
        }
        presentPopupBar(withContentViewController: walkRootVC, animated: true, completion: nil)
    }
LeoNatan commented 5 years ago

For now, go back to the previous stable version (2.5.x). But I will need a demo project, since I am unable to reproduce.

If you run the included example project, does it crash too?

942v commented 5 years ago

Hi @LeoNatan, I'm, seeing the same issue.

I've tracked it down to here: (UIViewController+LNPopupSupportPrivate.m: 532)

 static inline __attribute__((always_inline)) void _LNPopupSupportSetPopupInsetsForViewController_modern(UIViewController* controller, BOOL layout, UIEdgeInsets popupEdgeInsets)
{
    if([controller isKindOfClass:UITabBarController.class] || [controller isKindOfClass:UINavigationController.class] || [controller isKindOfClass:UISplitViewController.class])
    {
        [((UINavigationController*)controller).viewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * __nonnull obj, NSUInteger idx, BOOL * __nonnull stop) {
            _LNPopupSupportSetPopupInsetsForViewController_modern(obj, NO, popupEdgeInsets);
        }];
    }
    else
    {
        [controller _ln_setPopupSafeAreaInsets:popupEdgeInsets];
    }

    if(layout)
    {
        [controller.view setNeedsUpdateConstraints];
        [controller.view setNeedsLayout];
        [controller.view layoutIfNeeded];
    }
}

if the controller is a UITabBarController then it crashes because it's casting the controller as a UINavigationController and trying to get .viewControllers

((UINavigationController*)controller).viewControllers

I can change the if to not allowing UITabBarController but I don't know if that is going to mess things up.

iDevelopper commented 5 years ago

@942v , This is Objective C language then you can try to replace:

((UINavigationController*)controller).viewControllers with

[controller viewControllers]

LeoNatan commented 5 years ago

@iDevelopper That's not the issue. All the controllers mentioned there respond to @selector(viewControllers). Whether I use the message or property notation, it doesn't matter, it goes to the same selector.

@942v Unlike Swift, ObjC doesn't mind casting objects from one class to another. That's not the issue. Both UINavigationController and UITabBarController respond to viewControllers.

I need a demo project recreating the issue.

iDevelopper commented 5 years ago

@LeoNatan , yes sorry you're right!

LeoNatan commented 5 years ago

I think there may be two issues here, from the two different crashes provided (by @DevZaid and @wiencheck).

The first one is worrying me because it seems to try to call _ln_addChildViewController: directly, which isn't supposed to happen. It probably means swizzling failed somewhere. But I can't reproduce it to know where.

darkForestCat commented 5 years ago

I have the same error when I am trying to work with UISearchBar and UISearchController. Also the problem with addChildViewController

iDevelopper commented 5 years ago

@LeoNatan , testing your example (Map demo), you can reproduce a crash when you tap on the custom popup bar.

LeoNatan commented 5 years ago

@iDevelopper Indeed, just reproduced. I will look at it soon.

I fear there are several crashes here, and this is one of them. I still need demo projects for the split view and tab bar crashes. Thanks

iDevelopper commented 5 years ago

Looks like @DevZaid has a tab bar controller as a view controller of the split view controller, no?

LeoNatan commented 5 years ago

Yes, but somehow the tab bar controller is adding a child view controller to the split view. The first crash trace doesn't make a whole lot of sense to me. The other ones are likely I just forgot to if some statements.

LeoNatan commented 5 years ago

Uff, I think I found the source of all crashes. It's a bug in the swizzling.

zaidfadhil commented 5 years ago

sorry for the late reply , i made a fast demo to show you the crash

https://drive.google.com/file/d/1bXG1SsQBoaxLOjI3esCILSlMK8drHJ6F/view?usp=sharing

basically all im doing is adding ViewControllers to the TabBarViewController

class TabBarVC: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        tabBar.tintColor = .green
        tabBar.isTranslucent = false

        let vc1 = UIViewController()
        vc1.view.backgroundColor = .white
        vc1.title = "VC 1"
        let v1 = UINavigationController(rootViewController: vc1)

        let vc2 = UIViewController()
        vc2.view.backgroundColor = .white
        vc2.title = "VC 2"
        let v2 = UINavigationController(rootViewController: vc2)

        let views = [v1, v2]
        self.viewControllers = views

    }
}
LeoNatan commented 5 years ago

Please try with v2.6.2

zaidfadhil commented 5 years ago

Yes, Thank you every thing is working fine now