手短に:
ナビコントローラーの戻るボタンのタイトルを変更すると、古いタイトルのままで新しいタイトルが表示されない場合がある。これは、再現可能な状況でのみ発生しますが、他の状況では設計どおりに機能します。
ハードウェアに依存します
- このエラーは、iPhone 3G (iOS 4.2.1) およびシミュレーター (iOS 5.1) で発生します。
- ソースコードが同じならiPhone 4 (iOS 5.1)でもエラーなし
タイトルに書いてある言葉にもよる
- ボタンが作成され、自分で書いた作成メソッドから、自動的に取得されるタイトルと同じ単語 (つまり、ナビゲーション コントローラーのスタックの前のページのタイトル) を取得し、他の状況が一致すると、後でボタンのタイトルを変更しようとすると、古いテキストがスタックし、新しいタイトルが表示されません。
- ボタンの作成時に、デフォルトのタイトルとは異なるタイトルとして単語を取得すると、デフォルトのタイトルを割り当てない限り、その後のタイトルの変更はすべて正常に機能します。
- 多くの異なるタイトルで多くの成功した変更の後、デフォルトのタイトルである単語をボタンのタイトルに付けると、この単語は動かなくなります。それ以降の変更は受け付けません(メッセージなしで、他の状況が一致する場合のみ)
その間、ボタンが非表示だったかどうかによって異なります。
- 別のビューがナビゲーション コントローラー スタックにプッシュされた場合、欠陥のあるボタンを含む古いページが新しいページによって非表示になり、後で新しいページがスタックから再度ポップされて、ボタンが再び表示されるようになった場合 (および他の状況が一致する場合)、古いテキストは動かなくなり、それを変更する試行は (メッセージなしで) 無視されます。
- ボタンが非表示になったばかりの場合は、タイトルを変更しても問題ありません。私はいつも働いています。
アニメーション中に正しいタイトルが表示される
- 上記の状況の組み合わせにより、戻るボタンのタイトルを変更する試みが無視された場合、この戻るボタンが押され、ページの右にスライドするアニメーションが実行されると、適切なタイトルが約 0.3 秒間表示されます。処理されます。アニメーションの開始時に、古いスタック タイトルが適切なタイトルに置き換えられ、アニメーション中に正しいタイトルが表示されます。
詳細な説明
UINavigationController
の戻るボタンのテキストについてです。新しい言語設定に応じて、このボタンのタイトルを変更します。現在、私のアプリには、ナビゲーション コントローラー スタックに最大 3 つのビュー コントローラーがあります。それらのそれぞれは、UITableViewController の異なるサブクラスです。
表 1 の名前GeneralTableVC
は、スタックのルート ビューです。戻るボタンはありません。アプリ内に保存した内容の概要をユーザーに提供し、設定ボタンのあるツールバーを表示します。
表 1 に表示されているのは、このツールバーを提供するナビゲーション コントローラーです。表 2 と 3 では非表示に設定されています。現時点では、そのツールバーには「設定」という名前のボタンが 1 つしかありません。この設定ボタンに触れると、テーブル 2 がスタックにプッシュされます。
名前付きの表 2 にSettingsTabVC
は戻るボタンがあり、これはシミュレーターで問題を起こすものですが、iOS 5.1 を実行している実際の iPhone 4 では問題なく動作します。
表 2 の最初の行に触れると、新しい表 (表 3) が作成され、スタックにプッシュされます。
表 3 にLangSelectTableVC
も戻るボタンがありますが、これは iPhone シミュレーターと実際の iPhone 4 の両方のデバイスで問題なく動作します。
表 3 は、使用可能なすべての言語 (現時点では英語とドイツ語のみ) のリストを表示する言語選択テーブルです。行に触れると、すぐに設定が変更されます。アクティブ ビュー (表 3) が再描画され、数ミリ秒以内に画面上のすべてのテキストが新しい言語で表示されます。
テーブル自体とナビゲーション バーのタイトルの再描画は問題ありません。しかし、戻るボタンのテキストも翻訳する必要があり、これは少し注意が必要です。両方の戻るボタンでまったく同じトリックを実行しましたが、表 3 に表示されている表 2 に向けられているボタンで問題なく動作します。しかし、まったく同じコードでは、シミュレーターに問題があります (実際のiPhone) を表 2 のボタンで表 1 に向けている人。
私が行ったことと何が起こっているかを示すために、いくつかのコードスニペットといくつかのスクリーンショットを提供します。
ソースコード
ARC (自動参照カウント) が使用されています。
redraw-Protocol を定義しました:
プロトコル.h
#ifndef ToDo_Project_Protocols_h
#define ToDo_Project_Protocols_h
@protocol redrawProt
- (void) mustRedraw;
@end
#endif
これは、表 1 のヘッダーです。
GeneralTableVC.h
#import <UIKit/UIKit.h>
#import "Protocols.h"
// some other imports
@interface GeneralTabVC : UITableViewController <redrawProt>
@property id<redrawProt> parent;
@property Boolean mustRedrawMyself;
@property NSString* backTitle;
@property UIBarButtonItem* myBackButton;
@property UIBarButtonItem* parBackButton;
- (id) initWithParent:(id<redrawProt>)par andBackTitle:(NSString*)bT andBackButton:(UIBarButtonItem*)bB;
@end
他のテーブルのヘッダー ファイルで、同じプロパティと同一の init-functionSettingsTabVC.h
を定義します。LangSelectTabVC.h
プログラムはここから始まります:
AppDelegate.m の一部
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// some code
GeneralTabVC* genTabCon = [[GeneralTabVC alloc] initWithParent:nil andBackTitle:nil andBackButton:nil];
UINavigationController* navCon = [[UINavigationController alloc] initWithRootViewController:genTabCon];
// some other code
}
次は、表 1 の実装です ( GeneralTableVC.m
)。SettingsTabVC.m
表 2 ( ) と表 3 ( )のコードLangSelectTabVC.m
は同じです。プロトコル UITableViewDataSource を実装するコードの部分は示していません。それらの部分は、問題を説明する上であまり重要ではないと思います。
このコードには、キーワードを目的の言語に翻訳するLocalizedString(keyword)
とまったく同じことを行うマクロがあります。NSLocalizedString(keyword,comment)
このマクロの私のバージョンは、翻訳に別のバンドルを使用します (メイン バンドルではありません)。
GeneralTableVC.m
#import "GeneralTabVC.h"
#import "SettingsTabVC.h"
#define MYTITLE @"summary"
id<redrawProt> parent;
Boolean mustRedrawMyself;
NSString* backTitle;
UIBarButtonItem* myBackButton;
UIBarButtonItem* parBackButton;
@interface GeneralTabVC ()
@end
@implementation GeneralTabVC
@synthesize parent, mustRedrawMyself, backTitle, myBackButton, parBackButton;
- (void) mustRedraw {
self.mustRedrawMyself = YES;
}
- (void) redraw {
if ((self.parBackButton) && (self.backTitle)) {
// Important!
// here I change the back buttons title!
self.parBackButton.title = LocalizedString(self.backTitle);
}
if (self.parent) {
[self.parent mustRedraw];
}
self.title = LocalizedString(MYTITLE);
[self.tableView reloadData];
self.mustRedrawMyself = NO;
}
- (id) initWithParent:(id<redrawProt>)par andBackTitle:(NSString*)bT andBackButton:(UIBarButtonItem *)bB {
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
self.parent = par;
self.mustRedrawMyself = NO;
self.backTitle = bT;
self.parBackButton = bB;
}
return self;
}
- (void) toolbarInit {
// this method exists only in Table 1, not in other tables
// it creates a UIBarButtonItem, adds it to self.toolbarItems
// and makes it visible
}
- (void)SettingsAction:(id)sender {
// this method exists only in Table 1, not in other tables
// it will be executed after the user tabs on the settings-
// button in the toolbar
SettingsTabVC* setTabCon = [[SettingsTabVC alloc] initWithParent:self andBackTitle:MYTITLE andBackButton:self.myBackButton];
[self.navigationController pushViewController:setTabCon animated:YES];
}
- (void) viewDidLoad {
[super viewDidLoad];
self.title = LocalizedString(MYTITLE);
// I want an Edit-Button. Localization of this button is
// not yet done. At the moment is uses the systems language,
// not the apps language.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self toolbarInit];
}
- (void) viewWillAppear:(BOOL)animated {
// this is an important method! Maybe here is the reason for
// my problem!
[super viewWillAppear:animated];
// When ever this controllers view is going to appear, and
// when ever it is necessary to redraw it in a new language,
// it will redraw itself:
if (self.mustRedrawMyself) {
[self redraw];
}
// And here comes the buggy back button:
// When ever this controllers view is going to appear,
// a new back button will be created with a title in the
// new language:
UIBarButtonItem* BB = [[UIBarButtonItem alloc] init];
BB.title = LocalizedString(MYTITLE);
self.myBackButton = BB;
self.navigationItem.backBarButtonItem = self.myBackButton;
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// show toolbar:
[self.navigationController setToolbarHidden:NO animated:YES];
}
// next methods are about InterfaceOrientation and the
// UITableViewDataSource protocoll. They are not important
// for the problem.
// but maybe the very last method is important. It comes in
// different versions in the three implementation files:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// This is the version of GeneralTableVC.m (Table 1)
// It does nothing (at the actual stage of expansion, in later
// versions it will start the main business logic of this app)
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// This is the version of SettingsTableVC.m (Table 2)
// Tabbing onto row 0 of section 0 will push the
// language-selection-table (Table 3) on screen:
if (indexPath.section == 0) {
if (indexPath.row == 0) {
// create Table 3:
LangSelectTabVC* langTabCon = [[LangSelectTabVC alloc] initWithParent:self andBackTitle:MYTITLE andBackButton:self.myBackButton];
[self.navigationController pushViewController:langTabCon animated:YES];
} else {
// do something else (nothing at this stage of expansion)
}
} else {
// do something else (nothing at this stage of expansion)
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// This is the version of LangSelectTableVC.m (Table 3)
// here I do some magic to select and store the new language.
// Part of this magic is transforming indexPath.row
// into a valid language-code, putting it into the
// settings-object, and registering this object to
// NSUserDefaults
}
@end
スクリーンショット
iPhone 5.1 シミュレーターでアプリを起動すると、表 1 ( GeneralTableVC
) が画面に表示されます。
画面ボタンのツールバーの右側に、設定ボタンがあります。このボタンを押すと、次の表が画面に表示されます。
タイトル バーの [戻る] ボタンに注目してください。前の表のタイトルが「Summary」だったので、正しい「Summary」というテキストが表示されます。
Language English >
次に、最初の行 (" ")にタブで移動します。
すべて順調。では、言語を変更してみましょう。「 」のタブGerman
:
わお!今はすべてドイツ語です。戻るボタンも「設定」から「Einstellungen」に変わりました。
その「Einstellungen」の戻るボタンにタブを付けましょう:
今はほとんど何も問題ありません。すべてがドイツ語に変わりました。「ユーバーブリック」ではなく「概要」と表示されている戻るボタン以外のすべて。実際の iPhone 4 でまったく同じソースコードを使用してまったく同じ手順を実行すると、最後の画面は次のようになります。
戻るボタンのテキストに注意してください。実際の iPhone 4 ではドイツ語の "Überblick" (私が欲しいもの) ですが、シミュレーターでは英語の "Summary" です。そして、これは私にとって、一部の電話 (私の iPhone 4 など) では期待どおりの結果が得られることを意味しますが、他の一部の電話 (iPhone 4S など) ではバグのある表示になる可能性があります。
私のコードの何が問題なのか、誰にもわかりませんか?
編集
編集: 2012-04-06 09:04 +02:00 (中央ヨーロッパの夏時間)
他のハードウェア、古い iPhone 3G (iOS 4.2.1) でアプリをテストすることができました。古い iPhone では、アプリはシミュレーターとまったく同じように動作します。同じアプリを iPhone 4 で実行すると、動作が異なります。
より正確には:
- iPhone 4 (iOS 5.1) の場合: アプリは意図したとおりに動作しており、動作に問題はありません。
- シミュレーター (iOS 5.1): アプリは、ナビゲーション コントローラーの [戻る] ボタンに間違ったタイトルを表示します。
- iPhone 3G (iOS 4.2.1) の場合: アプリは、シミュレーターと同じ問題のある動作を示します。
編集: 2012-04-07 10:14 +02:00 (中央ヨーロッパの夏時間)
iPhone 3G のトランジションを見て、何か興味深く、おそらく役立つことに気付きました: 間違ったテキストのボタンをタブで押すと、次のことが起こります:
- 間違ったテキストは正しいテキストに置き換えられます
- この置換後、ビューはアニメーション表示されなくなり (右にスライド)、下にあるビューが表示されます。この遷移の持続時間は約 0.3 秒で、この短い間隔で、すべてのハードウェア iPhone とシミュレーターで正しいテキストが表示されます。
しかし、問題はまだあります: iPhone 3G と Simulator で誤ったテキストが表示されるのはなぜですか? iPhone 4 で常に正しいテキストが表示されるのはなぜですか?
私には、同じ場所に 2 つのボタンが重なっているかのように見えます。iPhone 4 では「私の」カスタム ボタンが前面にあり、古いシステム生成ボタンが隠されていますが、シミュレータと iPhone 3G では古いシステム生成ボタンが前面にあり、カスタム ボタンが隠されています。しかし: 非表示のカスタム ボタンがシステムで生成されたものよりも大きい (幅が広い) 場合でも、何も表示されません。スライド アウト アニメーションが開始されたときにのみ、私のボタンが表示されます。
編集: 2012-04-07 16:38 +02:00 (中央ヨーロッパの夏時間)
次の興味深い事実:
これは今までに起こったことです:
ボタンが初めて表示されたとき (2 番目のスクリーンショット、以下を参照)、タイトルとして単語を付けました。これは、システムからの前の単語と同じです。次に、ユーザーが何らかのアクションを選択すると、このボタンは別のビューによって隠されます。別のユーザーアクションの後、ボタンが再び表示され、タイトルとして新しい単語 (同じ意味ですが、新しい言語) が取得されますが、iPhone 3G およびシミュレーターでは、古いタイトルの方が「より強力」です。新しいタイトルは表示されません。古いタイトルがそのまま残っています。
これは、最初にボタンにタイトルとして単語を書き込んだ場合には発生しません。これは、システムによって生成されたタイトルとは異なります。最初のタイトルが default-title と異なる場合、後の変更はすべての iPhone とシミュレーターで実行されます。
これは、iOS が何らかの「最適化」を行っていることを私に信じさせます。ボタンの最初の外観で、カスタム タイトルがシステム生成のタイトルと同一である場合、その後のボタン タイトルの変更は無視されますが、iPhone でのみです。 3G とシミュレーター。iPhone 4 では、その後の変更はどのような場合でも許可されます。
ただし、アプリの動作不良を防ぐために、最初に別のタイトルを設定することはできません。