按钮单击使整个应用程序崩溃

Posted

技术标签:

【中文标题】按钮单击使整个应用程序崩溃【英文标题】:Button click crashes the whole application 【发布时间】:2015-06-15 12:51:51 【问题描述】:

我目前正在构建应用程序的 UI,但不使用 IB 或情节提要。我有以下层次结构: 1. ViewController:主视图控制器。 2. DrawerViewController:是下抽屉菜单的视图控制器。 主视图控制器将抽屉视图控制器的视图添加为子视图。 3. 添加按钮:这是一个以编程方式创建并添加到drawerViewController 视图的UIButton。

问题是如果我单击添加按钮,应用程序崩溃,输出中绝对没有错误消息,除了 (lldb)。

我尝试了以下方法:

    更改选择器名称和方法名称。 检查了选择器方法的名称。 添加和删除选择器方法的参数。 更改了按钮的名称。 在另一个视图中添加了按钮。

没有办法使用断点来跟踪错误,因为应用程序编译得很好,并且只有在您单击按钮时应用程序才会崩溃。

这是我为显示问题而创建的测试项目的链接:

GitHub

视图控制器:

class ViewController: UIViewController //, DrawerDelegate


//Lower Drawer.
var drawerView: DrawerView!

var drawerViewHidden: Bool = false
var addButton: UIButton!
var viewHeight: CGFloat! = 0
var viewWidth : CGFloat! = 0
var shownDrawerViewY: CGFloat!
var hiddenDrawerViewY: CGFloat!

init()

    super.init(nibName: nil, bundle: nil)


required init(coder aDecoder: NSCoder)

    super.init(coder: aDecoder)




override func viewDidLoad()

    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    //Setup UI
    setUpUI()


override func viewWillAppear(animated: Bool)

    super.viewWillAppear(animated);




override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.



//MARK:- UI initialization.
/**
Private function that setsup the UI.
*/
private func setUpUI()

    setUpDrawer()


//MARK: Drawer setup.

/**
A private function that programatically creataes a drawer and add it to the view.
*/
private func setUpDrawer()

    var controller = DrawerViewController(width: self.view.frame.width, height: self.view.frame.height)

    self.view.addSubview(controller.view)
    //Hide
    // toggleDrawer()




//MARK:- Delegates.

//MARK: DrawerDelegate methods.
func addButtonClicked(sender: UIButton)

    //  toggleDrawer()
   

抽屉视图控制器

class DrawerViewController: UIViewController

    //Drawer variables.
    var drawerViewHidden: Bool = false
    var addPinDrawer: AddPinDrawer!



    var viewHeight: CGFloat! = 0
    var viewWidth : CGFloat! = 0
    var shownDrawerViewY: CGFloat?
    var hiddenDrawerViewY: CGFloat?

    var addButton: UIButton?

    init(width: CGFloat, height: CGFloat)
    
        super.init(nibName: nil, bundle: nil)

        viewWidth  = width
        viewHeight = height

        setUpUI()
    

    override func viewDidLoad()
    
        super.viewDidLoad()

        // Do any additional setup after loading the view.

    

    override func viewWillAppear(animated: Bool)
    
        super.viewWillAppear(animated)


    

    override func didReceiveMemoryWarning()
    
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    


    required override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
    
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    

    required init(coder aDecoder: NSCoder)
    
        fatalError("init(coder:) has not been implemented")
    


    //MARK:- UI setup
     func setUpUI()
    
        setUpDimensions()
        setUpDrawerElements()
//        toggleDrawer()
    

     func setUpDimensions()
    
        //Determine the y in the case drawer is shown
        shownDrawerViewY  = viewHeight * 2.0/8.0

        //Determine the height of the drawer.
        let drawerHeight = viewHeight * 6.0/8.0

        //Determine the y in the case drawer is hidden
        hiddenDrawerViewY = viewHeight * 7.4/8.0

        //Create the frame, starting with the drawer shown.
        let frame = CGRectMake(0, shownDrawerViewY!, viewWidth, drawerHeight)
        //Create a new Drawer View.
        self.view = UIView(frame: frame)

        setUpAddButton(frame)



        //Setup the background image of the drawer.
        self.view.backgroundColor = UIColor(patternImage: UIImage(named: Constants.drawerBackgroundImage)!)
    

    func setUpDrawerElements()
    
        //Setup the button.
        setUpAddPinDrawer()
    

    func setUpAddPinDrawer()
    
        addPinDrawer = AddPinDrawer(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
//        self.view.addSubview(addPinDrawer)
    



    //MARK: Handling drawer toggles
    func toggleDrawer()
    
        //Toggle the variable.
        drawerViewHidden = !drawerViewHidden

        //If the drawer must be hidden.
        if drawerViewHidden
        
            hideDrawer()
        

        //If the drawer must be shown
        else
        
            showDrawer()
        
    

    func hideDrawer()
    
        //Hide the drawer
        UIView.animateWithDuration(0.6, animations:  () -> Void in
            self.view.frame.origin.y = self.hiddenDrawerViewY!
        )
      //  drawerView.hideDrawer()
    

    func showDrawer()
    
        UIView.animateWithDuration(0.6, animations:  () -> Void in
            self.view.frame.origin.y = self.shownDrawerViewY!
        )
      //  drawerView.showDrawer()
    


    func setUpAddButton(frame: CGRect!)
    
        //Determine the button dimensions.
        let width:CGFloat = 75.0//1.0/10.0 * viewHeight
        let x = frame.width/2.0 - width/2.0

        //Button background image.
        let background = UIImage(named: Constants.addButtonBackgroundImage)!

        //Create the button.
        addButton = UIButton(frame: CGRectMake(x, -width/2.0, width, width)) as UIButton
//        addButton!.setImage(background, forState: UIControlState.Normal)

        addButton?.backgroundColor = UIColor.yellowColor()

        //Add the event handler.
        addButton!.addTarget(self, action: "buttonAdd:", forControlEvents: .TouchUpInside)


        //Set it rotated.
//        self.addButton!.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_4))


        //Add the button to the subview.
        self.view.addSubview(addButton!)

//        println(addButton!.targetForAction("test", withSender: addButton)!)
    

    func buttonAdd(sender: UIButton)
    
        println("Helloooo asdf")
    

【问题讨论】:

您的DrawerViewController 也在情节提要中?在 init(coder) 中尝试 fatalError("init(coder:) has not been implemented") 行到 super.init(coder: aDecoder) 你设置断点了吗? @VivekMolkar DrawerViewController 不在情节提要中,情节提要中除了 viewController 类之外什么都没有,而且情节提要中完全是空的。一切都是以编程方式添加的。 @nhgrif 正如我在帖子中提到的,设置 beakpoints 没有用,因为应用程序编译得非常好,并且应用程序只有在您单击按钮时才会崩溃。 我在问你是否设置了一个断点来阻止显示错误消息(从而阻止任何人获得任何有用的信息)。您似乎很可能有一个异常断点。如果您努力验证您没有设置断点,您的应用程序将继续崩溃,我们将看到一条有用的错误消息。而且,断点和编译是完全不相关的。 “应用程序仅在您单击按钮时才会崩溃”是一个很好的机会,可以使用符号断点(如果没有别的)。 【参考方案1】:

我已经解决了这个问题。 DrawerViewController 的初始化有一个很小的错误,在主视图控制器中,我正在创建一个名为 DrawerViewController 的变量并初始化它的视图。一旦方法完成,这个变量将被释放,这意味着所有事件都不会被处理。由于没有处理按钮事件的方法,导致应用崩溃。

解决办法:

将 DrawerViewController 设为实例变量并在主视图控制器中对其进行初始化。

【讨论】:

查看了您的代码,您也可以通过在 ViewController 中添加 DrawerViewController 作为 childviewcontroller 来做到这一点。在您的ViewController.viewDidLoad self.view.addSubview(controller.view) 之后添加以下行 self.addChildViewController(controller)

以上是关于按钮单击使整个应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使画布视图无效时单击按钮后应用程序崩溃(Android Studio,Java)

单击按钮后我的应用程序崩溃[重复]

Logcat 错误描述:按钮启动使应用程序崩溃

React Native Facebook 登录按钮在 iOS 模拟器中使应用程序崩溃

iOS Swift - 文本到语音使应用程序崩溃

IBAction 使 TabBarController 应用程序崩溃