gpt4 book ai didi

objective-c - 直接初始化的委托(delegate)生成 ARC 警告和 EXC_BAD_ACCESS 崩溃

转载 作者:太空狗 更新时间:2023-10-30 03:44:38 25 4
gpt4 key购买 nike

我创建了一个实现 UITextFieldDelegate 的委托(delegate)对象在它自己的名为 NumericTextFieldDelegate 的类中,然后我以这种方式在我的 Controller 中初始化了委托(delegate):

textFieldName.delegate = [NumericTextFieldDelegate new];

我从编译器那里得到了这个警告:

Assigning retained object to unsafe property; object will be released after assignment

这意味着该对象将在分配后释放,事实上,当我运行应用程序并聚焦 UITextField 时,我得到一个 EXC_BAD_ACCESS 并且应用程序崩溃......

我发现让它工作的唯一方法是使用工厂方法创建一个静态变量,该方法分派(dispatch) NumericTextFieldDelegate 的实例:

@interface NumericTextFieldDelegate : NSObject <UITextFieldDelegate>

+(NumericTextFieldDelegate *) getDelegate;

@end

@implementation NumericTextFieldDelegate

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];

// This allows backspace
if ([resultingString length] == 0) {
return true;
}

NSInteger holder;
NSScanner *scan = [NSScanner scannerWithString: resultingString];

return [scan scanInteger: &holder] && [scan isAtEnd];
}

+(NumericTextFieldDelegate *) getDelegate {
static NumericTextFieldDelegate *del;
@synchronized(del) {
if(del == nil)
del = [NumericTextFieldDelegate new];
}
return del;
}

@end

然后当我以这种方式分配委托(delegate)时:

textFieldName.delegate = [NumericTextFieldDelegate getDelegate];

一切正常,但我的问题是:

为什么我不能简单地分配一个类的匿名新实例?为什么赋值后对象自动释放?

为什么我需要这个解决方法?

谢谢。

最佳答案

我同意@Inaziger 的分析。 UITextField 实例的委托(delegate)是一种弱引用。它不持有分配给它的委托(delegate)。根据 ARC,如果没有人持有对它的引用,委托(delegate)将是 nil。因此,将由分配者保留它以便调用委托(delegate)。您编写之前的解决方法是这样的:

- (void) somemethod {
...
id<UITextFieldDelegate> tempDelegate = [NumericTextFieldDelegate new];
textFieldName.delegate = tempDelegate;
...
}

textFieldName 的实例获得了对本地创建的委托(delegate)的引用。 ARC 将在方法调用后将 temDelegate 设置为 nil。但是,文本字段的委托(delegate)仍然持有指向分配给的内存的指针,该指针随后由 ARC 释放。这就是为什么您遇到内存访问崩溃的原因。

通过将 del 作为静态变量保留在您的类中,只要您未将其设置为 nil,它就会在您的应用程序运行周期中保留。我认为最好将静态 del 保留为类级别成员并提供一个 setter,以便您应该记得释放它。像这样的东西:

// in interface definition
+(NumericTextFieldDelegate *) getDelegate;
+(void) setDelegate:(id)newDel;

// in implementation
static NumericTextFieldDelegate* del;

+(NumericTextFieldDelegate *) getDelegate {
@synchronized(del) {
if(del == nil)
del = [NumericTextFieldDelegate new];
}
return del;
}

+(void) setDelegate:(id)newDel {
del = newDel;
}

顺便说一下,您还可以保持之前的解决方法代码不变。您可以将委托(delegate)作为类成员变量或属性保留在文本字段类中。

@interface myTextFieldContainer () {
@proerpty (strong) id<UITextFieldDelegate> delHolder;
...
}

@implementaion myTextFieldContainer {
@sythysis delHolder = _delHodler;
...
self.delHolder = [NumericTextFieldDelegate new];
textFieldName.delegate = self.delHolder;

上述策略的好处是您不必担心在 View Controller 消失时释放委托(delegate)。

关于objective-c - 直接初始化的委托(delegate)生成 ARC 警告和 EXC_BAD_ACCESS 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10837183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com