返回键在 UIAlertView 上的 UITextField 中不起作用 .. SIGSEGV
Posted
技术标签:
【中文标题】返回键在 UIAlertView 上的 UITextField 中不起作用 .. SIGSEGV【英文标题】:Return key doesn't work in a UITextField on a UIAlertView .. SIGSEGV 【发布时间】:2011-12-01 15:00:33 【问题描述】:当我在UIViewController
中使用UITextField
时,我能够使用ShouldReturn
捕获返回键的键盘事件:
public override void ViewDidLoad ()
this.txtPassword.ShouldReturn = (tf) =>
tf.ResignFirstResponder();
return true;
;
...但是当我使用UIAlertView
时,我在尝试使用ShouldReturn
时遇到了SIGSEGV 错误:
public override void ViewDidLoad ()
base.ViewDidLoad ();
loginScreen = new UIAlertView();
loginScreen.Title = "Login";
loginScreen.AlertViewStyle = UIAlertViewStyle.LoginAndPasswordInput;//type login and pass
loginScreen.AddButton ("Cancel");
//username
UITextField usernameField = loginScreen.GetTextField(0);
usernameField.KeyboardType = UIKeyboardType.Default;
usernameField.ReturnKeyType = UIReturnKeyType.Next;
usernameField.ClearButtonMode = UITextFieldViewMode.WhileEditing;
//password
UITextField passwordField = loginScreen.GetTextField(1);
passwordField.KeyboardType = UIKeyboardType.Default;
passwordField.ReturnKeyType = UIReturnKeyType.Next;
passwordField.ClearButtonMode = UITextFieldViewMode.WhileEditing;
//(Error SIGSEV happens here!!! and the resignfirstresponder doesn't work)
passwordField.ShouldReturn = (tf) =>
tf.ResignFirstResponder();
return true;
;
loginScreen.Show();
我不知道到底发生了什么,这可能是一个错误或者我做错了什么?
【问题讨论】:
这可能发生在 GC 收集(托管)实例(例如 passwordField)时。现在您提供的代码看起来是正确的 - 但也许某些东西(稍后)允许处置loginScreen
(这也将允许处置文本字段)。你能提供一个完整的测试用例吗?您可以将此类附加到bugzilla.xamarin.com 上的错误报告中,谢谢!
我在 MT 5.2.11 上使用完全相同的代码,但有一点不同:我的 ShouldReturn 看起来像这样:pwd.ShouldReturn = delegate passwordField.ResignFirstResponder();返回真; - 所以我正在捕获我想辞职的文本字段,这似乎阻止了收集。
【参考方案1】:
在 ViewDidLoad 范围内创建并且在方法执行后应该保持活动状态(不是垃圾回收)的对象,必须在包含类中具有引用。
private UIAlertView _loginScreen; // Declare reference.
private UITextField _usernameField; // Declare reference.
private UITextField _passwordField; // Declare reference.
public override void ViewDidLoad ()
base.ViewDidLoad ();
_loginScreen = new UIAlertView(); // Set reference.
_loginScreen.Title = "Login";
_loginScreen.AlertViewStyle = UIAlertViewStyle.LoginAndPasswordInput;
_loginScreen.AddButton ("Cancel");
//username
_usernameField = _loginScreen.GetTextField(0); // Set reference.
_usernameField.KeyboardType = UIKeyboardType.Default;
_usernameField.ReturnKeyType = UIReturnKeyType.Next;
_usernameField.ClearButtonMode = UITextFieldViewMode.WhileEditing;
//password
_passwordField = _loginScreen.GetTextField(1); // Set reference.
_passwordField.KeyboardType = UIKeyboardType.Default;
_passwordField.ReturnKeyType = UIReturnKeyType.Next;
_passwordField.ClearButtonMode = UITextFieldViewMode.WhileEditing;
//(Error SIGSEV happens here!!! and the resignfirstresponder doesn't work)
_passwordField.ShouldReturn = (tf) => // Use reference.
// This delegate will be executed at a later time, ensure its owner
// object is rooted with a reference.
tf.ResignFirstResponder();
return true;
;
_loginScreen.Show();
用户poupou当然是第一个回答这个问题的,但我想把它和示例代码一起放在一起,因为这个错误让我咬了太多次。很难调试,并且可能在垃圾回收后意外发生。
我的经验法则;每当使用new
或工厂方法时,都应该存储一个引用,除非该对象超出范围,或者已经通过引用嵌套到另一个对象中。
出于这个原因,我在字段前加上下划线,它表示“这个对象将跨越这个对象的方法范围,并且可以很容易地与方法变量(没有下划线的变量)区分开来。
现在,对于这种情况,GetTextField()
似乎创建了一个包装对象而不是引用。虽然loginScreen
字段是有根的,但从GetTextField()
返回的对象不是根,并且容易被垃圾回收。由于意外行为,我会说这是 MonoTouch API 中的错误。
【讨论】:
用户要求 UITextView 而不是 UITextField @MyKuLLSKI 发生 SIGSEGV 错误是因为在 ShouldReturn lambda 中引用的垃圾收集 UITextField(请参阅 tf 参数)。这就是问题。与 UIAlertView 无关。在投反对票之前阅读。以上是关于返回键在 UIAlertView 上的 UITextField 中不起作用 .. SIGSEGV的主要内容,如果未能解决你的问题,请参考以下文章