@IBAction在递归调用时崩溃

时间:2015-06-23 12:52:34

标签: ios swift recursion ibaction

当我递归调用@IBAction

时,我发生了这次崩溃
0   Goga  0x00000001000b90b8 function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed> of Goga.NewViewController.emailButtonPressed (Goga.NewViewController)(ObjectiveC.UIButton) -> () (NewViewController.swift:0)
1   Goga  0x00000001000c0488 Goga.NewViewController.(emailButtonPressed (Goga.NewViewController) -> (ObjectiveC.UIButton) -> ()).(closure #2) (NewViewController.swift:872)
2   Goga  0x00000001000bd250 partial apply forwarder for reabstraction thunk helper from @callee_owned (@in ObjectiveC.UIAlertAction!) -> (@out ()) to @callee_owned (@owned ObjectiveC.UIAlertAction!) -> (@unowned ()) (NewViewController.swift:0)

这是代码及其中发生的行

allowedToSend = false
@IBAction func emailButtonPressed(sender: UIButton) {

  if !allowedToSend {

    let controller = UIAlertController(title: title,
                    message: "Are you sure you want to send the Email?",
                    preferredStyle: .Alert) 

     controller.addAction(UIAlertAction(title: "Yes please, send.", style: .Default, handler: {
                    action in

                    self.allowedToSend = true; 
                    self.emailButtonPressed(sender) <=== WHERE THE CRASH HAPPENED
            }))  

     controller.addAction(UIAlertAction(title: "Cancel", style: .Default, handler: nil))
     presentViewController(controller, animated: true, completion: nil)
     return // exit the function

  }

  // Reset the value
  allowedToSend = false

  // Sending code

  let text = textArea.text
  let to = toLabel.text

    ....    

}   

你可能会问,为什么我不把“发送代码”放在处理程序中,因为我这样做只是针对用户即将批量发送给他的地址簿中的所有联系人的特定情况。因此,我提醒她,在发送之前她会这样做。

我不确定这样的实现有什么问题以及为什么Swift抱怨这个问题,因为我在调试模式下测试了它并且它看起来很好。为什么会这样?

编辑

如果我可以深入了解崩溃的含义,那就太好了。

3 个答案:

答案 0 :(得分:3)

我建议将功能分解为可读性和可维护性。这也将解决递归问题并消除对allowedToSend属性的需求。在任何情况下,由于简化了执行路径,因此调试起来会更容易。

@IBAction func emailButtonPressed(sender: UIButton) {
    self.confirm();
}

func confirm() {
    let controller = UIAlertController(title: title,
                message: "Are you sure you want to send the Email?",
                preferredStyle: .Alert) 

    controller.addAction(UIAlertAction(title: "Yes please, send.", style: .Default, handler: {
                action in 
                self.send()
    }))  

    controller.addAction(UIAlertAction(title: "Cancel", style: .Default, handler: nil))
    presentViewController(controller, animated: true, completion: nil)
}

func send() {
    let text = textArea.text
    let to = toLabel.text
    ....
}

答案 1 :(得分:0)

我认为你有无限的递归。 在行self.emailButtonPressed(sender)allowedToSend = false上设置断点并运行应用程序,您将看到第二个从未被调用过。

答案 2 :(得分:0)

我发现了这个问题。它与递归无关,甚至与代码分解成块。问题是:程序崩溃,因为在展开可选值时发现nil。奇怪的是,该错误消息无法在崩溃日志文件中找到。所以,对于那些看到这个(以及我未来的自我)的人,请务必检查您的选项。

示例:

let cell = tableView.cellForRowAtIndexPath(indexPath)
cell.textLabel.text = "Hello" // CRASH if the cell is not visible in the view

要解决上述问题,只需打包到if let

即可
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
   cell.textLabel.text = "Hello" // Never get executed if cell is nil
}