没有取消分配带有inputAccessoryView的UIViewController

时间:2014-07-06 12:57:29

标签: ios objective-c ios7 uiviewcontroller uiresponder

我有UIViewController的简单子类(下面的代码)。 如果我附加inputAccessoryView,我的viewcontroller永远不会被释放。如果我没有在viewDidLoad中设置inputAccessoryView,则按预期调用dealloc。

我错过了什么吗?

@interface IMTestViewController : UIViewController

@property (nonatomic, strong) UIView *messageInputView;
@property(nonatomic, readwrite, strong) UIView *inputAccessoryView;

@end

@implementation IMTestViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{

}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.inputAccessoryView = self.messageInputView;
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (UIView *)messageInputView
{
    if (_messageInputView == nil)
    {
        _messageInputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 45)];
        _messageInputView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    }
    return _messageInputView;
}
@end

我已经没有想法了。 谢谢。

2 个答案:

答案 0 :(得分:7)

不幸的是,对我来说,@ rdelmar的回答并不奏效。花了一些时间试图解决它后,我发现了这篇文章:http://derpturkey.com/uitextfield-docked-like-ios-messenger/

我的目标是即使键盘没有,也可以看到输入附件视图,就像所有IM应用程序一样。我之前已将UIViewController自定义类子类化为允许它成为第一响应者并将我的自定义子视图返回为inputAccessoryView。这阻止了视图控制器被解除分配。现在我将控制器的视图子类化,以实现与上面链接中推荐的相同的东西,一切似乎都能正常工作。

编辑:经过一些测试,我可以确认自定义的UIView被解除分配。

编辑2:唯一的缺点是您无法使键盘显示在viewWillAppear中,inputAccessoryView尚未添加到视图层次结构中且无法成为第一响应者

答案 1 :(得分:0)

这个问题已经很老了,但是我在2019年尝试在iOS 12中使用inputAccessoryView时遇到了这个问题。

今天,分配问题仍然存在,dvkch's answer中提到的文章中提出的第一个解决方案也不起作用。本文中的第二种解决方案(涉及动画)工作量太大,并且当用户使用带有scrollView.keyboardDismissMode = .interactive的UIScrollView交互地关闭键盘时,效果不佳。

我能想到的最好方法是将UITextField上的第一响应者UITextViewinputAccessoryView nil设置为viewDidDisappear。这样可以完全消除内存泄漏,并且似乎没有任何副作用或不利之处。

这是完整的Swift 4.2示例:

class MyViewController: UIViewController {
    /// You could also add your text field or text view programmatically, 
    /// but let's say it's coming from a .xib for now...
    @IBOutlet private weak var myTextField: UITextField!

    /// This is required for the inputAccessoryView to work.
    override internal var canBecomeFirstResponder: Bool {
        return true
    }

    /// Here's a nice empty red view that will be used as an
    /// input accessory.
    private lazy var accessoryView: UIView = {
        let accessoryView = UIView()
        accessoryView.backgroundColor = UIColor.red
        accessoryView.frame.size = CGSize(
            width: view.frame.size.width,
            height: 45
        )

        return accessoryView
    } ()

    override var inputAccessoryView: UIView? {
        return accessoryView
    }

    /// This is required to avoid leaking the `inputAccessoryView`
    /// when the keyboard is open and the `UIViewController`
    /// is deallocated.
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        myTextField.inputAccessoryView = nil
    }
}