ViewController 实现 UITextFieldDelegate 时出错

Posted

技术标签:

【中文标题】ViewController 实现 UITextFieldDelegate 时出错【英文标题】:Error when ViewController is implementing UITextFieldDelegate 【发布时间】:2011-06-25 19:22:36 【问题描述】:

在我的 ViewController 类中实现 UITextFieldDelegate 时,在文本字段中输入第一个字符时会引发以下错误:

-[MyViewController respondsToSelector:]: message sent to deallocated instance...

所以,我尝试创建一个单独的类(仅继承 NSObject)并实现 UITextFieldDelegate。你猜怎么着,效果很好。但是,这引入了一些其他问题,因为我必须做很多我想避免的丑陋的跨类通信。这是我的应用委托代码的相关部分:

@interface RMSAppDelegate : NSObject <UIApplicationDelegate,
                                      UITabBarControllerDelegate>

@property (nonatomic, retain) UIViewController* myViewController;

@end

@implementation MyAppDelegate

@synthesize myViewController;

- (BOOL)application:(UIApplication *)application
            didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    myViewController = [[MyViewController alloc]
                         initWithNibName:@"MyView" bundle:nil];
    [self.window setRootViewController:myViewController];
    [self.window makeKeyAndVisible];
    return YES;


@end

.. 这是正在显示的内容:

@interface MyViewController : UIViewController <UITextFieldDelegate>

@property (nonatomic, retain) IBOutlet UITextField* pinTextField;
- (void)viewDidLoad;

@end

@implementation MyViewController

@synthesize pinTextField;

- (void)viewDidLoad 
    // DOES NOT WORK (WHY?)
    //[pinTextField setDelegate:self];

    // WORKS, BUT I'D LIKE TO AVOID
    [pinTextField setDelegate:[[[MyTextFieldDelegate alloc] init] autorelease];

    [pinTextField becomeFirstResponder];
    [super viewDidLoad];


@end

如果您看到任何我可以做得更好的代码(甚至是离题),请发表评论。

【问题讨论】:

@albertamg:谢谢,我已将代码修改为示例,但遗漏了一些内容。去掉dealloc方法,缩短代码,专注问题 【参考方案1】:

由于您要求提供题外话代码 cmets:您忘记致电 [super viewDidLoad]。您也不需要重新声明原型来覆盖它。 @synthesize textFieldDelegate 无效,因为您在名为 textFieldDelegate 的类中没有属性。而你的 dealloc 方法正在释放一个名为 tfd 的 ivar,它似乎实际上并不存在于类中。

您真正的问题是您在分配视图控制器的任何时候都没有正确保留它。可能是视图控制器在 nib 中被实例化并与 ivar 关联,而不是声明为 retain 的属性,或者没有与任何东西关联。或者可能是您在代码中分配它,将其视图添加为某事物的子视图,然后在不保留视图控制器本身的情况下释放它。或者可能只是你在不应该发布的时候发布了它。

您的其他类特别有效,因为您正在泄漏对象,因此它永远不会被释放。如果您采用这种方法,更好的解决方案是在分配对象时将其存储在 ivar 中,然后在 deallocviewDidUnload 中释放它(并将 ivar 设置为 nil)。

【讨论】:

较新版本的编译器将使用 @synthesize 生成您的实例变量:@synthesize foo = _foo; 将使用下划线名称创建 ivar(从风格上建议,以免新编码人员混淆他们正在访问的内容) 同意,您在提供的代码范围之外未充分保留 MyViewController 的实例 我已经更新了我的代码并将 UIVC 的 init 添加到我的问题中。请查阅! @synthesize 不需要多余的 ivar 声明,因为 bshirley 声明 这只是一点点帮助。当然它“可能是我在不应该发布的时候发布了一些东西”......但这不总是message sent to deallocated instance 在对象上的原因吗?无论如何,我现在已经发布了更多代码,所以看看 :) @Simeon:你会惊讶地发现人们经常需要被告知这一点。您更新的代码工作正常。很明显,您正在尝试减少代码以仅显示错误,但是当您这样做时,您需要确保减少的代码仍然显示错误。【参考方案2】:

好的,我终于自己解决了这个问题。我没有更改代码。我的 NIB (.xib) 是罪魁祸首!

我认为嵌套的 UIViewControllers 是可以的,我仍然认为它们在某些情况下是可以的(并且可能使用另一种编程方法)。无论如何,我正在用一个 NIB 初始化我的类 MyViewController,它在 Objects 面板中有一个 UIViewController 作为第一个对象。

我通过将 UIView 作为“对象”面板中的第一个对象并将文件的所有者设置为 UIViewController 来解决此问题。

代码正确,NIB 错误。感谢您的帮助。

【讨论】:

以上是关于ViewController 实现 UITextFieldDelegate 时出错的主要内容,如果未能解决你的问题,请参考以下文章

ViewController 实现 UITextFieldDelegate 时出错

实现可重用和可配置的 ViewController

实现从 viewController 到 DataManager 类的委托

dealloc 方法从 Xcode 4 中的 ViewController 实现文件模板中消失了吗?

检测哪个 viewController 呈现了 SideMenu 并为其呈现实现适当的功能

你可以为不同的目标有两个同名的 ViewController 实现吗?