2011-12-01 62 views
2

當我使用的UIViewController我能捕獲返回鍵的鍵盤事件與ShouldReturn一個UITextField返回鍵不爲UITextField上UIAlertView中工作.. SIGSEGV

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(); 

我不知道究竟是什麼發生的事情,這可能是一個bug或我做錯了什麼?

+1

GC收集(託管)實例(例如passwordField)時可能會發生這種情況現在,您提供的代碼看起來是正確的 - 但也許(稍後)允許「loginScreen」被丟棄(這將允許文本字段也被丟棄)。你能提供一個完整的測試案例嗎?您可以附加到http://bugzilla.xamarin.com上的錯誤報告謝謝! – poupou

+0

我在MT 5.2.11上使用完全相同的代碼,只有一點區別:我的ShouldReturn看起來像這樣:pwd.ShouldReturn = delegate {passwordField.ResignFirstResponder();返回true; } - 所以我捕獲我想要辭職的文本字段,這似乎阻止收集。 – Krumelur

回答

0

在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或使用工廠方法,都應該存儲引用,除非對象超出範圍,或者已經使用引用嵌套到另一個對象中。

爲此,我prefix字段以下劃線,它標誌着「這個對象將會在方法作用域生活在這個對象,可以從方法的變量很容易區分(那些沒有下劃線)。

現在,看起來對於這種情況GetTextField()創建一個包裝器對象,而不是一個引用雖然loginScreen字段是根源,從GetTextField()返回的對象不是,並且傾向於垃圾回收我會說這是一個在MonoTouch API中的錯誤,由於意外的行爲

+0

用戶詢問UITextView NOT UITextField – MyKuLLSKI

+0

@MyKuLLSKI由於在ShouldReturn lambda中引用了垃圾回收UITextField,因此發生SIGSEGV錯誤(請參閱tf參數)。這是個問題。沒有什麼特別與UIAlertView。閱讀之前,你downvote。 –

+0

閱讀OP標題 – MyKuLLSKI