[UITextField retain]:发送给deallocated实例的消息

时间:2016-05-13 15:26:31

标签: ios swift2 uitextfield

我收到此消息:

  

[UITextField retain]:发送到解除分配的实例的消息。

我理解这条消息但我不知道发送了什么“消息”以及如何阻止它发生....

此代码产生错误:

 func dismissController() {
       self.view.endEditing(true)
             self.dismissViewControllerAnimated(false, completion: nil)
           }

虽然以下工作“很好”,但我不确定为什么在解雇控制器之前我必须延迟:

func dismissController() {
       self.view.endEditing(true)

        let delay = 0.75 * Double(NSEC_PER_SEC)
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
        dispatch_after(time, dispatch_get_main_queue()) { () -> Void in
            self.dismissViewControllerAnimated(false, completion: nil)


        }

           }

编辑:(几乎完整的代码):

 @IBOutlet weak var locationTextView: UITextField!
    @IBOutlet weak var userIDTextView: UITextField!
   var treeLocationArray = NSMutableArray()
    var treeUserIDArray = NSMutableArray()

让pickerView = UIPickerView()     var pickerButton = UIButton()     var keyboardButton = UIButton()     var locationIsSelected = true

   override func viewDidLoad() {
        super.viewDidLoad()

//....

 locationTextView.delegate = self
        userIDTextView.delegate = self
//Get the Plist... etc

 treeLocationArray = dict?.objectForKey("Location") as! NSMutableArray
        treeUserIDArray = dict?.objectForKey("UserID") as! NSMutableArray

 locationTextView.text = userPrefs.objectForKey("DefaultLocation") as? String
            userIDTextView.text = userPrefs.objectForKey("DefaultName") as? String
             locationTextView.text = userPrefs.objectForKey("DefaultLocation") as? String

  /// Create a view for the Accessory View
        let customView = UIView(frame: CGRectMake(0, 0, 10, 50))
        customView.backgroundColor = UIColor.lightGrayColor()


        /// Setup the picker button
        pickerButton = UIButton(frame: CGRectMake(60 , 8, 32, 32) )
        pickerButton.setImage(UIImage(named:"dropIcon"), forState: .Normal)
        pickerButton.tintColor = UIColor.blueColor()
        pickerButton.addTarget(self, action: #selector(UserDefaultsViewController.pickerTapped), forControlEvents: UIControlEvents.TouchUpInside)
        customView.addSubview(pickerButton)

        /// Setup the keyboard button
        keyboardButton = UIButton(frame: CGRectMake(10 , 8, 32, 32) )
        keyboardButton.setImage(UIImage(named:"keyboardIcon"), forState: .Normal)
        keyboardButton.tintColor = UIColor.blueColor()
        keyboardButton.addTarget(self, action: #selector(UserDefaultsViewController.keyboardTapped), forControlEvents: UIControlEvents.TouchUpInside)
        customView.addSubview(keyboardButton)

        locationTextView.inputAccessoryView = customView
        userIDTextView.inputAccessoryView = customView

}

 func textFieldDidBeginEditing(textField: UITextField) {

        if textField == locationTextView {
            locationIsSelected = true


        }

        if textField == userIDTextView {
            locationIsSelected = false

        }


        self.pickerView.reloadAllComponents()

    }


    func keyboardTapped(){

        if locationIsSelected {

            locationTextView.resignFirstResponder()
            locationTextView.inputView = nil
            locationTextView.becomeFirstResponder()

        }

        else {

            userIDTextView.resignFirstResponder()
            userIDTextView.inputView = nil
            userIDTextView.becomeFirstResponder()

        }


    }

    func pickerTapped(){

        if locationIsSelected {

            locationTextView.resignFirstResponder()
            locationTextView.inputView = nil
            locationTextView.inputView = pickerView
            locationTextView.becomeFirstResponder()

        }

        else {

            userIDTextView.resignFirstResponder()
            userIDTextView.inputView = nil
            userIDTextView.inputView = pickerView
            userIDTextView.becomeFirstResponder()

        }

    }

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

        var numberOfComponents = Int()

        if locationIsSelected {
            numberOfComponents = treeLocationArray.count
        }

        else {
            numberOfComponents = treeUserIDArray.count
        }

        return numberOfComponents
    }

    func pickerView(pickerView: UIPickerView, numberOfRowsInSection section: Int) -> Int {

        var numberOfComponents = Int()

        if locationIsSelected {
            numberOfComponents = treeLocationArray.count
        }

        else {
            numberOfComponents = treeUserIDArray.count
        }

        return numberOfComponents
    }

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        var componetString = String()

        if locationIsSelected {
            componetString = (treeLocationArray[row] as? String)!
        }

        else {
            componetString = (treeUserIDArray[row] as? String)!
        }

        return componetString

    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        if locationIsSelected {

            if treeLocationArray.count >= 1 {
            locationTextView.text = treeLocationArray[row] as? String

            }
        }

        else {

            if treeUserIDArray.count >= 1 {

            userIDTextView.text = treeUserIDArray[row] as? String

            }
        }

    }

1 个答案:

答案 0 :(得分:1)

发生此问题是因为您已调用dismissViewControllerAnimated。由于VC生命周期,此VC保存的所有对象将被释放。这意味着,在解雇后使用UI进行的所有操作都不是内存安全的。

来自文档:

  

此方法查看当前视图及其子视图层次结构   当前第一个响应者的文本字段。如果找到一个,   它要求文本字段作为第一响应者辞职。如果力量   参数设置为true,文本字段永远不会被询问;它是   被迫辞职。

因此,我认为你的VC已被解除分配,而endEditing正在寻找彻底的层次结构。这是唯一可能导致记忆问题的原因之一。

为什么在解雇前需要调用endEditing?如果没有这个电话,只需解雇VC。如果你有逻辑,那取决于endEditing - 将它分开并调用而不是endEditing。希望这会有所帮助。

更新:

尝试在viewWillDisappear中调用endEditing - 这会触发视图,在第一个响应者被解雇之前将其重新签名。