0

HEADS UP EDIT:これに対する(簡単な)回答を以下に投稿しました。このすべてのコードを見て時間を無駄にする必要はありません。Jack Lawrence の回答の構造的な提案も参照してください。


で始まる tableViewCell に UITextField を設定しましたenabled = NOenabled = YESその後、ファーストレスポンダーになり、キーボードなどを呼び出すことができるように変更されます。

しかし、一度enabledNO になると、二度と YES になることはありません。

tf.enabled = YES;
printf(" Is tf enabled? %d", [tf isEnabled]); // this prints 0 — it refuses to be re-enabled.

さらに奇妙なことに、UITextField をサブクラス化して単純なカスタム メソッドを指定すると、コントローラからそのメソッドを正常に呼び出すことができます — before enabledは NO に設定されています。一度enabledNO を指定すると、カスタム メソッドを呼び出しても何も起こりません。警告や例外はありません。動かないだけです。

したがって、問題はレスポンダー チェーンの問題だけではありません。一度無効化されたテキストフィールドは、ブラック ホールのように動作します。

セル内の編集可能なテキスト フィールド「TaggedLocations」に関する Apple のデモを見てみましたが、それらenabledは完全に無防備にいじられてnameField.enabled = NO;おりnameField.enabled = YES;、すべてが時計仕掛けのように進んでいます。

もう 1 つの手がかりがあります。UIControl クラスの参照は、「有効な状態が NO の場合、コントロールはタッチ イベントを無視し、サブクラスは異なる方法で描画される可能性があります」と述べています。しかし、再度有効にすることを拒否しますか? メソッド呼び出しの受け入れを拒否しますか? 理解できません。


OK、これはおそらくあなたが本当に見たいと思っている以上のものですが、うまくいけば、そこにいくつかの手がかりが隠されています.

UITextField サブクラスの h および m ファイルは次のとおりです。

#import "FooNameFieldForCell.h"

@implementation FooNameFieldForCell

- (BOOL) canBecomeFirstResponder {
    printf("\nCBFR called, self.enabled is %d.", self.enabled); 
    if (self.enabled)
        return YES;
    else
        return NO;
}

- (BOOL) canYouHearMe:(id)sender {
    printf("Yes, I hear you."); 
    return YES;
}

@end

#import <UIKit/UIKit.h>

@interface FooNameFieldForCell : UITextField {

}

- (BOOL) canYouHearMe:(id)sender;

@end

cellForRow とアクション メソッドは次のとおりです。

BOOL bPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);

// Cell Which Layout
NSString *identifier = nil;
UITableViewCell *cellFooList = nil;
switch (indexPath.row) {
    case 0:
        // this textfield is in row 0
        identifier = bPortrait ? @"cellFooListName_portrait" : @"cellFooListName_landscape";
        cellFooList = [tableView dequeueReusableCellWithIdentifier:identifier];
        if (!cellFooList)
            cellFooList = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
        break;
    // other rows…
}

// Foo
Foo *Foo = [self.frcFoosAllReg_byName.fetchedObjects objectAtIndex:indexPath.section];

// Cell Fill
switch (indexPath.row) {
    case 0: {
        if (cellFooList.tag == 1) {
            for (UIView *subview in cellFooList.subviews) {
                if (subview.tag == 2) {
                    ((FooNameFieldForCell *)cellFooList).text = Foo.FooName;
                    break;
                }
            }
            break;// dequeued cell, already done 
        }

        // button "Edit"
        // (Yes, I know you’re supposed to put this on the navBar, but as a user I have never liked that metaphor. I’m doing the editability by section/row.) 
        UIButton *btnEditFooName = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [btnEditFooName addTarget:self action:@selector(presentEditFooName:) forControlEvents:UIControlEventTouchUpInside]; // the selector is where I’m trying to enable the textfield
        // do button setup & framing
        [btnEditFooName setFrame:rectBtnEditFooName];
        [cellFooList.contentView addSubview:btnEditFooName];

        // TEXTFIELD SETUP FOLLOWS   

        // do framing
        FooNameFieldForCell *tfFooName = [[FooNameFieldForCell alloc] initWithFrame:rectFooName]; 
        [tfFooName canYouHearMe:self]; // custom method runs OK here
        tfFooName.text = Foo.FooName;
        tfFooName.enabled = NO;
        tfFooName.tag = 2; // tag to locate among cell's subviews
        [cellFooList.contentView addSubview:tfFooName];
        [tfFooName release];
        // no row selection allowed
        cellFooList.selectionStyle = UITableViewCellSelectionStyleNone;
        // tag as done
        cellFooList.tag = 1;
        break;
    // other cases…
    }
}
return cellFooList;
}

// Called by the Edit button:
- (void) presentEditFooName:(id)sender {

    // Determine which Foo is associated with sender.
    if (![sender isKindOfClass:[UIButton class]])
        return;
    UIView *cell = ((UIButton *)sender).superview.superview;
    if (!cell || ![cell isKindOfClass:[UITableViewCell class]])
        return;
    NSIndexPath *indexPath = [self.tvFooList indexPathForCell:((UITableViewCell *)cell)];
    Foo *Foo = [self.frcFoosAllReg_byName.fetchedObjects objectAtIndex:indexPath.section];

    FooNameFieldForCell *tfFooName = nil;
    for (UIView *subview in cell.subviews) {
        if (subview.tag == 2) {
            tfFooName = subview;
            break;
        }
    }

    // BLACK HOLE
        // because tfFooName is nil. But why? It shows up in the cell.

    tfFooName.enabled = YES; 
    [tfFooName becomeFirstResponder];
    printf("\ntfFooName can become firstResp? %d", tfFooName.canBecomeFirstResponder); // always prints 0, can't be firstResp
    [tfFooName canYouHearMe:self]; // does not run
    printf(" Is tfFooName enabled? %d", [tfFooName isEnabled]); // prints 0, still disabled

}

さて、私の謎のブラック ホールは -- null であることが判明しました。特にobjective-cはnullの呼び出しを許可しているため、今では明らかです。しかし、別の謎が残っています。フィールドのテキストがセルに表示されるのに、どうして nil になるのでしょうか?

4

3 に答える 3

1

テキストフィールド自体はnilではありません。その通りです。nilの場合、セルには表示されません。代わりに、このコードブロックはセルを見つけていないと思います。

FooNameFieldForCell *tfFooName = nil;
for (UIView *subview in cell.subviews) {
    if (subview.tag == 2) {
        tfFooName = subview;
        break;
    }
}

ブレークポイントを挿入しtfFooName、forループの後またはifステートメント内の値を出力してチェックします。

サブビューまたはスーパービューを検索する代わりに、次のいずれかの方法を使用することを検討してください。

  • Objective-Cランタイムの関連付けられたオブジェクト関数を使用して、NSIndexPathを編集ボタンに関連付け、そのインデックスパスを使用してセルを取得します。
  • Key-Value監視を使用して、テキストフィールドのテキスト値をオブジェクトの値に「バインド」します(セルの再利用とコアデータオブジェクトの障害に注意してください)。
  • のサブクラスを作成しUIButton、indexpathプロパティを追加します(厄介な種類)
  • ブロックベースのイベント処理をに追加しUIButton(最も難しいが最も素晴らしいが、チュートリアルと事前に構築されたソリューションがあります)、で発生させたいことを正確に設定します-tableView:cellForRowAtIndexPath:
于 2012-08-24T03:18:34.820 に答える
0

このような場合にオブジェクトのプロパティの設定に問題がある場合は、次のようにオブジェクトにパブリックメソッドを追加すると便利です。

-(void) setEnabledToYes
{
self.enabled=YES;
}

私はそれが仮帆装の解決策であることを知っていますが、それは以前私のために働いていました

于 2012-08-24T03:05:16.657 に答える
0

いつものように髪をかきむしっていると、ブラックホールの謎は単純なものでした。

これ...

FooNameFieldForCell *tfFooName = nil;
for (UIView *subview in cell.subviews) {
    if (subview.tag == 2) {
        tfFooName = subview;
        break;
    }
}

...これである必要があります:

FooNameFieldForCell *tfFooName = nil;
for (UIView *subview in ((UITableViewCell *)cell).contentView.subviews) {
    if (subview.tag == 2) {
        tfFooName = subview;
        break;
    }
}

カスタム ビューは、セルの直接のサブビューではなく、セルのcontentView内の 1 層下にあります。ああ!無駄な時間がたくさん!

于 2012-08-24T03:37:43.377 に答える