ios - 带有 UITextField : Trouble with Delegates and Dequequing 的自定义 Xib UITableViewCell

标签 ios uitableview xamarin xamarin.ios

我正在为我的 TableView 创建自定义单元格。我有 8 种不同的细胞。所有细胞都会发生这种情况,但我会为这个例子选择一个来演示发生了什么。我的单元格 NumberCell 中有一个 TextField。您可以在下面看到我如何使用 GetCell 和 SetupDelegates 设置单元格。一切正常,直到我在屏幕上有足够的单元格,您必须开始滚动以创建相同类型的新单元格(这会使旧单元格出队并重新使用)。好吧,我的单元格似乎在交换 answerNumberField.Text,当我将它们从屏幕上滚动然后再打开时,这可能与将 formItem 发送到自定义单元格有关,但我不确定。我想我想知道这是否是在我的自定义单元格中设置我的代表的正确方法。您可以看到我这样做的原因是我可以在单元格中访问 formItem 信息,但这可能是导致问题的原因。我也这样做是为了尝试分离出逻辑,这样我的 GetCell 就不会变得很大。任何帮助将不胜感激,如果您需要更多信息,请询问。谢谢!

注册自定义单元格的 xib 文件:

TableView.RegisterNibForCellReuse (MFNumberCell.Nib, MFNumberCell.Key);

获取单元格

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
    {
        var cell = new UITableViewCell();
        FormItem formItem = formItems [indexPath.Row];

        switch (formItem.type) {
          case "MFNumber":
            var numberCell = (MFNumberCell)tableView.DequeueReusableCell (MFNumberCell.Key, indexPath);
            numberCell.SetupDelegates (formItem, detailVC);
            cell = numberCell;
            break;

           ...
        }
        //Remove inset edge constraints
        cell.SeparatorInset = UIEdgeInsets.Zero;
        cell.LayoutMargins = UIEdgeInsets.Zero;

        //Don't show background highlight when selecting the cell
        cell.SelectionStyle = UITableViewCellSelectionStyle.None;


        return cell;
    }

自定义 NumberCell

public void SetupDelegates (FormItem formItem, DetailViewController detailVC)
    {  

        validationView.Layer.MasksToBounds = false;
        validationView.Layer.CornerRadius = 13;

        //Adds left space before text
        answerNumberField.LeftViewMode = UITextFieldViewMode.Always;
        if (answerNumberField.LeftView == null) {
            UIView leftView = new UIView (new CGRect (0, 0, 15, 25));
            answerNumberField.LeftView = leftView;
        }

        if (!String.IsNullOrWhiteSpace (formItem.answer)) {
            answerNumberField.Text = formItem.answer;
        } else {
            answerNumberField.Text = "";
        }

        answerNumberField.Placeholder = formItem.placeholder;
        answerNumberField.KeyboardType = UIKeyboardType.NumberPad;
        questionTextView.Text = formItem.question_text;
        UtilHelper.UpdateValidationView(formItem, validationView);


        helpButton.TouchUpInside += (object sender, EventArgs e) => {
            var okAlertController = UIAlertController.Create ("Help", formItem.help, UIAlertControllerStyle.Alert);
            okAlertController.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Default, null));
            detailVC.PresentViewController (okAlertController, true, null);
        };



        answerNumberField.ShouldChangeCharacters += (UITextField tf, NSRange range, string replacementText) => {
            string next_answer = tf.Text + replacementText;
            bool isMatch = Regex.IsMatch(next_answer, formItem.input_constraint);

            if(isMatch){ 
                formItem.answer = next_answer;
            }

            UtilHelper.UpdateValidationView(formItem, validationView);

            return isMatch;
        };


        answerNumberField.Ended += (object sender, EventArgs e) => {

            if (String.IsNullOrWhiteSpace(answerNumberField.Text)) {
                formItem.answer = "";
            }else{
                formItem.answer = answerNumberField.Text;
            }

            FormGenerator.updateFormItemInSQLiteDatabase (formItem);
            UtilHelper.UpdateValidationView(formItem, validationView);

        };

    }

这是对我有用的解决方案

创建事件处理程序并将它们保存到单元格中,以便您可以在 TableViewSource 的 CellDisplayingEnded 方法中调用 Remove 方法。

public partial class MFNumberCell : UITableViewCell
{
    public static readonly UINib Nib = UINib.FromName ("MFNumberCell", NSBundle.MainBundle);
    public static readonly NSString Key = new NSString ("MFNumberCell");

    public EventHandler helpButtonClick;
    public UITextFieldChange answerFieldShouldChangeChar;
    public EventHandler answerFieldEnded;


    public MFNumberCell (IntPtr handle) : base (handle)
    {
    }

    public static MFNumberCell Create ()
    {
        return (MFNumberCell)Nib.Instantiate (null, null) [0];
    }


    public void Update (FormItem formItem, DetailViewController detailVC)
    {  

        validationView.Layer.MasksToBounds = false;
        validationView.Layer.CornerRadius = 13;

        //Adds left space before text
        answerNumberField.LeftViewMode = UITextFieldViewMode.Always;
        if (answerNumberField.LeftView == null) {
            UIView leftView = new UIView (new CGRect (0, 0, 15, 25));
            answerNumberField.LeftView = leftView;
        }

        if (!String.IsNullOrWhiteSpace (formItem.answer)) {
            answerNumberField.Text = formItem.answer;
        } else {
            answerNumberField.Text = "";
        }

        answerNumberField.Placeholder = formItem.placeholder;
        answerNumberField.KeyboardType = UIKeyboardType.NumberPad;
        questionTextView.Text = formItem.question_text;
        UtilHelper.UpdateValidationView(formItem, validationView);


        // HELP BUTTON START //

        helpButtonClick = (s, e) => { 
            var okAlertController = UIAlertController.Create ("Help", formItem.help, UIAlertControllerStyle.Alert);
            okAlertController.AddAction (UIAlertAction.Create ("OK", UIAlertActionStyle.Default, null));
            detailVC.PresentViewController (okAlertController, true, null); 
        };

        helpButton.TouchUpInside += helpButtonClick;


        // HELP BUTTON END // 

        // ANSWER TEXT FIELD START //

        answerFieldShouldChangeChar =  (UITextField tf, NSRange range, string replacementText) => {
            string next_answer = tf.Text + replacementText;
            bool isMatch = Regex.IsMatch(next_answer, formItem.input_constraint);

            if(isMatch){ 
                formItem.answer = next_answer;
            }

            UtilHelper.UpdateValidationView(formItem, validationView);

            return isMatch;
        };

        answerNumberField.ShouldChangeCharacters += (UITextFieldChange)answerFieldShouldChangeChar;


        answerFieldEnded = (s, e) => {
            if (String.IsNullOrWhiteSpace (answerNumberField.Text)) {
                formItem.answer = "";
            } else {
                formItem.answer = answerNumberField.Text;
            }

            FormGenerator.updateFormItemInSQLiteDatabase (formItem);
            UtilHelper.UpdateValidationView (formItem, validationView);
        };

        answerNumberField.Ended += answerFieldEnded;

        // ANSWER TEXT FIELD END //


    }

    public void RemoveDelegates(){
        answerNumberField.Ended -= answerFieldEnded;
        answerNumberField.ShouldChangeCharacters -= answerFieldShouldChangeChar;
        helpButton.TouchUpInside -= helpButtonClick; 
    }

}

最佳答案

由于每次单元格即将出现时,您都在 GetCell() 中分配委托(delegate),所以每次单元格即将消失时,您也应该在 CellDisplayingEnded() 中删除它们

您应该在 MFNumberCell 中执行一个名为 RemoveDelegates 的方法 并在 CellDisplayingEnded() 上调用它

关于ios - 带有 UITextField : Trouble with Delegates and Dequequing 的自定义 Xib UITableViewCell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31063597/

相关文章:

ios - AVAudioConverter float32/48khz -> int16/16khz 转换失败

ios - 我的 iAd 代码有问题吗?

ios - 从 UITableViewCell 转入如何包含 indexPath 数据?

ios - 如何更改 InAppSettingsKit 类中的标题部分文本颜色?

android - Xamarin Razor WebView 模板缺少引用

ios - 在 Jenkins 构建机器中构建意外失败

iphone - 沿 X 方向旋转两个 UIImageView

ios - 向下滚动页面一次后显示表格 View 按钮

ios - 在模拟器中模拟 Apple pencil 似乎是可行的

c# - 使用 WCF (IIS 7.5) 从数据库获取值时出现系统错误