0

iOS5 + for iPadには非常に奇妙な行間隔のバグがあります。各UITableViewCellがUITextViewを含むカスタムタイプであるUITableViewを使用している場合、アラビア語などの非AZ言語のテキストの複数行を含むセルは次のようにデキューされます。キーボードがモーダルビューで開かれた後の間違った行の高さ。

注:これはiOSのバグのようですが、アプリがiOS5+のバージョンと下位互換性を持つようにするための回避策を探しています。

バグを再現する方法は次のとおりです。

(1)(a)ストーリーボードで、UIToolbarとUITableViewがあるUIViewControllerを作成します(ただし、独自のサブクラスを作成します)。UITableViewで、識別子が「CellIdentifier」の「Dynamic Prototype」セルを1つ作成し、タグが「1」ですべてのAutoResizeプロパティがオンのUITextViewを作成します(セルのフルサイズを使用します)。

ステップ1aのスクリーンショット

(1)(b)ストーリーボードで、UIToolbarを「toolbar」変数にリンクし、UITableViewを「mainTableView」変数にリンクします。UITableViewの「dataSource」と「delegate」をUIViewControllerに設定し、UITextViewの「delegate」をUIViewControllerに設定します。

(1)(c) UIViewControllerサブクラスに次のコードを追加します。

MyViewController.h:

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UITextViewDelegate>

// the toolbar at the top of the screen
@property (weak, nonatomic) IBOutlet UIToolbar *mainToolbar;

// the table view taking up the screen
@property (weak, nonatomic) IBOutlet UITableView *mainTableView;

@end

MyViewController.m:

#import "MyViewController.h"

@interface MyViewController ()

// array to store text for cells
@property (strong, nonatomic) NSMutableArray *data;

// the number of rows to show
@property (nonatomic) NSInteger numberOfRowsToShow;

// when toolbar buttons are pressed
- (void)showModalViewButtonPressed;
- (void)redrawVisibleCellsButtonPressed;
- (void)insertButtonPressed;
- (void)deleteButtonPressed;

@end

@implementation MyViewController

@synthesize mainTableView;
@synthesize mainToolbar;
@synthesize data;

@synthesize numberOfRowsToShow;

- (void)viewDidLoad {
    [super viewDidLoad];
    // create data array for cell contents
    self.data = [[NSMutableArray alloc] initWithObjects:
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 @"سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام سلام",
                 nil];
    self.numberOfRowsToShow = 0;
    // set toolbar buttons
    [self.mainToolbar setItems:[NSArray arrayWithObjects:
                                [[UIBarButtonItem alloc] initWithTitle:@"Show Modal View" style:UIBarButtonItemStyleBordered target:self action:@selector(showModalViewButtonPressed)],
                                [[UIBarButtonItem alloc] initWithTitle:@"Redraw Visible Cells" style:UIBarButtonItemStyleBordered target:self action:@selector(redrawVisibleCellsButtonPressed)],
                                [[UIBarButtonItem alloc] initWithTitle:@"Insert" style:UIBarButtonItemStyleBordered target:self action:@selector(insertButtonPressed)],
                                [[UIBarButtonItem alloc] initWithTitle:@"Delete" style:UIBarButtonItemStyleBordered target:self action:@selector(deleteButtonPressed)],
                                nil] animated:YES];
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // clean up
    self.data = nil;
    self.mainTableView = nil;
    self.mainToolbar = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // only one section
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // return the number of items in the data array
    return self.numberOfRowsToShow;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // dequeue cell from storyboard
    UITableViewCell *cell = [self.mainTableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
    // get text view
    UITextView *cellText = (UITextView *)[cell viewWithTag:1];
    // set text using data array
    cellText.text = [self.data objectAtIndex:indexPath.row];
    // set large font
    cellText.font = [UIFont systemFontOfSize:20.0f];
    // set background color based on whether the line spacing is correct
    if (cellText.contentSize.height == 100.0f) {
        // correct height sets a green background
        cellText.backgroundColor = [UIColor greenColor];
    } else if (cellText.contentSize.height == 88.0f) {
        // wrong height sets a red background
        cellText.backgroundColor = [UIColor redColor];
    }
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // return constant height
    return 150.0f;
}

- (void)textViewDidChange:(UITextView *)textView {
    // get parent cell for text view
    UITableViewCell *parentCell = (UITableViewCell *)textView.superview.superview;
    // get parent cell indent path
    NSIndexPath *parentIndexPath = [self.mainTableView indexPathForCell:parentCell];
    // save new text to data array
    [self.data replaceObjectAtIndex:parentIndexPath.row withObject:textView.text];
}

#pragma mark - Other methods

- (void)showModalViewButtonPressed {
    // segue to modal view
    [self performSegueWithIdentifier:@"modalSegue" sender:self];
}

- (void)redrawVisibleCellsButtonPressed {
    // reload all visible cells in the table view
    [self.mainTableView reloadRowsAtIndexPaths:[self.mainTableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}

- (void)insertButtonPressed {
    // insert a cell in the table view (increments number of rows to show first)
    [self.mainTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:self.numberOfRowsToShow++ inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}

- (void)deleteButtonPressed {
    // delete a cell in the table view (decrements number of rows to show first)
    [self.mainTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:--self.numberOfRowsToShow inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}

@end

(2)(a)ストーリーボードで、UINavigationControllerとUIViewControllerを作成し(サブクラス化も)、そのプロパティでUIViewControllerをUINavigationControllerのルートビューコントローラーとして設定します。「完了」ボタンのあるUIToolbarをUIViewControllerとUITextFieldに追加します。UINavigationControllerに「modalSegue」と呼ばれるメインビューコントローラーにモーダルセグエを追加します。

ステップ2aのスクリーンショット

(2)(b)ストーリーボードで、[完了]ボタンをIBActionの[closeButtonPressed]にリンクします。

(2)(c)次のコードをモーダルUIViewControllerに追加します。

MyModalViewController.h:

#import <UIKit/UIKit.h>

@interface MyModalViewController : UIViewController

- (IBAction)closeButtonPressed:(id)sender;

@end

MyModalViewController.m:

#import "MyModalViewController.h"

@implementation MyModalViewController

- (IBAction)closeButtonPressed:(id)sender {
    [self dismissModalViewControllerAnimated:YES];
}

@end

テスト:

(1)アプリケーションを実行します。画面が読み込まれると、UITableViewにはコンテンツがありません。

ステップ1のスクリーンショット

(2)ツールバーの「挿入」ボタンを数回タップします。2つのセルが緑色で追加されます。ここでの行間隔は、アラビア語と英語のみを含む行の場合、4ピクセル高くなっていることに注意してください(セル内のすべて英語のテキストでこれを試すことができます)。この段階で、アプリの正しい動作を確認できます。

ステップ2のスクリーンショット

(3)「モーダルビューを表示」ボタンをタップし、モーダルビューが開いたら、UITextField内をタップしてキーボードを開きます。[完了]をタップして、モーダルビューを閉じます。この時点から、バグはUITableViewで発生します(次の手順を参照)。

ステップ3のスクリーンショット

(4)「挿入」をさらに数回タップします。すべての新しいセルが赤であることに注意してください。これは、新しいセルの行の間隔が間違っているためです。これは、テキストがすべて英語の文字である場合に使用される間隔です。これは、以前のようにアラビア語に余分な4ピクセルが追加されなくなったためです。

ステップ4のスクリーンショット

(5)いくつかのバグを実際に確認するには、[表示されているセルを再描画]ボタンをタップし、セルが再描画されるときにUITableViewの周囲の色が変化するのを確認します。

ディスカッション:キーボードがモーダルビューで開かれた後にデキューされた新しいセルの行の高さが、アラビア語やその他の英語以外のテキストに対して間違っているようです。これは、UITableViewのキャッシュメカニズムに関連しているようです。課題は、すべての状況で適切な行間隔がロードされるソリューションを見つけることです。

4

1 に答える 1

0

これは完璧な解決策ではなく、ハック/回避策です。Appleがこのバグを修正すると、本当の解決策が生まれます。

注意:この回答は、AppleDeveloperSupportによって推奨されました。

このバグは、UITextFieldまたはUISearchBarがスタイルフォームシートのモーダルビューの最初のレスポンダーになった後、UITableViewCells内のすべてのUITextViewで発生します。

回避策は次のいずれかです。

  1. UITextViewをサブクラス化して、実際のコントロールを使用する代わりに、独自のバージョンのUITextFieldとUISearchBarを作成します。
  2. UITableViewCell内でUITextViewを使用しないでください。代わりに、CoreTextを使用して独自のバージョンを作成してください。

オプション1ははるかに高速ですが、スクロールに関連する独自の課題があります。オプション2はうまく機能しますが、時間がかかります。良い出発点としてEGOTextViewを調べてください。

于 2012-08-29T01:59:23.103 に答える