应用程序在iPhone 5.1模拟器和带有iOS 5.1的真实iPhone 4上表现不同 [英] App is behaving different on iPhone 5.1 simulator and real iPhone 4 with iOS 5.1

查看:107
本文介绍了应用程序在iPhone 5.1模拟器和带有iOS 5.1的真实iPhone 4上表现不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当导航控制器的后退按钮的标题发生变化时,在某些情况下,旧标题会被卡住并且新标题将会出现不显示。这种情况仅在某些可重现的情况下发生,而在其他情况下则按其设计。

When the title of a back-button of a navigation controller gets changed, in some cases the old title is stuck and the new title will not be displayed. This happens only in some reproduceable situations, while it works as designed in other situations.

这取决于硬件


  • iPhone 3G(iOS 4.2.1)和模拟器(iOS 5.1)中发生错误

  • 使用相同的源代码iPhone 4上没有错误(iOS 5.1)

这取决于写入标题的单词


  • 当按钮被创建时,它从我的自写创建方法获得与它自动获得的标题相同的单词(即导航控制器堆栈上一页的标题),当其他情况匹配时,则在稍后尝试更改按钮标题时,旧文本卡住,新标题不会显示。

  • 当在创建时按钮获得一个与其默认标题不同的标题的单词时,只要您不指定标题,其标题的每个后续更改都可以正常工作。它的默认标题。

  • 如果在经过许多不同标题的大量修改后,你将单词放在按钮标题上,这是它的默认标题,那么这个单词就会被卡住。以后的更改将不被接受(没有任何消息,并且仅在其他情况匹配时)

这取决于是否按钮在此期间是不可见的。


  • 如果在导航控制器堆栈上推送了另一个视图,那么旧的带有缺陷按钮的页面被新页面隐藏了,当新页面再次从堆栈中弹出时,再次使按钮可见,(当其他情况匹配时),旧文本被卡住并且试用版本发生变化它被忽略(没有任何消息)。

  • 如果按钮是新隐藏的,更改其标题永远不会有问题。我一直都在工作。

在动画期间可以看到正确的标题


  • 当由于上述情况的组合而忽略了改变后退按钮标题的尝试时,无论如何,当这个后退按钮时,正确的标题会显示约0.3秒被点击并且页面的幻灯片向右动画被处理。在动画开始时,旧的标题被正确的标题取代,并且在动画期间可以看到正确的标题。

这是关于 UINavigationController 上的文字返回键。我根据新的语言设置更改了这个按钮标题。目前,我的应用程序在导航控制器堆栈中最多有3个视图控制器。它们中的每一个都是`UITableViewController的不同子类。

It's about the text on a UINavigationController's back button. I change this buttons title in dependence of new language-settings. At the moment my app has a maximum of 3 view controllers in the navigation controllers stack. Each of them is a different subclass of `UITableViewController.

表1,名为 GeneralTableVC 是关于它的根视图叠加。它没有后退按钮。它为用户提供了他在应用程序中存储的内容的摘要,并显示了一个带有设置按钮的工具栏。

Table 1, named GeneralTableVC is the root view on the stack. It has no back button. It gives the user a summary of what he has stored inside the app and it displayes a toolbar with a settings-button.

导航控制器提供此工具栏在表1中可见。它在表2和3中设置为不可见。此时工具栏中只有一个名为设置的按钮。触摸此设置按钮会将表2推入堆栈。

It is the navitation controller who provides this Toolbar that is visible in Table 1. It is set to invisible in Table 2 and 3. At the moment there is only one button in that toolbar named "Settings". Touching this Settings-Button will push Table 2 onto the stack.

表2,名为 SettingsTabVC 有一个后退按钮,这是在模拟器中出现问题但在我的真正运行iOS 5.1的iPhone 4上工作正常。

Table 2, named SettingsTabVC has a back button, and this is the one that makes problems in the simulator but works fine on my real iPhone 4 running iOS 5.1.

通过触摸表2的第一行新表(表3)将被创建并推入堆栈。

By touching the first row of Table 2 a new Table (Table 3) will be created and pushed onto the stack.

表3,名为 LangSelectTableVC 也有回按钮,但这个在两个设备,iPhone模拟器和真正的iPhone 4中工作得很好。

Table 3, named LangSelectTableVC also has a back button, but this one works pretty fine in both devices, iPhone simulator and real iPhone 4.

表3是一个语言选择表,显示所有可用语言的列表(目前只有英语和德语)。触摸行会立即更改设置。将重新绘制活动视图(表3),并在几毫秒内,屏幕上的所有文本都以新语言显示。

Table 3 is a language selection table that displayes a list of all available languages (at the moment just english and german). Touching a row changes settings immediately. The active view (Table 3) will be redrawn, and within a few milliseconds all texts on screen appear in the new language.

重绘表本身没有问题,因为以及导航栏中的标题。但是后退按钮上的文本也必须翻译,这有点棘手。我在两个后退按钮上都完成了相同的技巧,并且它对于表3中可见的按钮工作正常,该按钮指向表2.但是使用完全相同的代码在模拟器中存在问题(但不是真实的iPhone),表2中的按钮指向表1.

Redrawing the table itself is no problem, as well as the title in the navigation bar. But the text on the back button must be translated too, and this is a little bit tricky. I have done the very same trick on both back-buttons, and it works fine for the button visible on Table 3 who is directing to Table 2. But with the very same code there is a problem in the simulator (but not on a real iPhone) with the button on Table 2 who is directing to Table 1.

我给你一些代码片段和一些屏幕截图,向你展示我做了什么以及做了什么正在发生:

I give you some code-snippets and some screenshots to show you what I've done and what is happening:

ARC(正在使用自动引用计数。

我确实定义了重绘协议:

I did define a redraw-Protocol:

Protocols.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

其他表的头文件, SettingsTabVC.h LangSelectTabVC.h 定义相同的属性和相同的init函数

The header files of the other Tables, SettingsTabVC.h and LangSelectTabVC.h define the same properties and an identical init-function

该计划从这里开始:

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 )。表2中的代码( SettingsTabVC.m )和表3( LangSelectTabVC.m )类似。我没有显示实现协议UITableViewDataSource的那些代码部分。我认为这些部分对解释问题并不重要。

Next comes the implementation of Table 1 (GeneralTableVC.m). The Code in Table 2 (SettingsTabVC.m) and Table 3 (LangSelectTabVC.m) is analogously the same. I don't show those parts of code that implements the protocol UITableViewDataSource. I think those parts are not really important for explaining the problem.

在这段代码中你会发现宏 LocalizedString(keyword) NSLocalizedString(关键字,注释)完全相同,它将关键字翻译成所需的语言。我的这个宏的版本使用不同的bundel进行翻译(不是主要包)

In this code you will find the macro LocalizedString(keyword) which does exactly the same as NSLocalizedString(keyword,comment), which is translating the keyword into the desired language. My version of this macro uses a different bundel for translation (not the main bundle)

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 )在屏幕上:

在屏幕按钮的工具栏中,您可以在右侧找到设置按钮。按此按钮可在屏幕上显示下一个表格:

In the toolbar on the screens button, on its right side, you find a settings-button. Pressing this button brings the next table on screen:

观看标题栏中的后退按钮。它显示文本摘要,这是正确的,因为上一个表标题是摘要。

Watch the back button in the title bar. It displays the text "Summary", which is correct, since the previous table title was "Summary".

现在我们选项卡到第一行(语言英语> ):

Now we tab onto the first row ("Language English >"):

一切都很好。
现在让我们改变语言。选项卡德语

哇!现在一切都用德语。甚至后退按钮也已从设置更改为Einstellungen。

Wow! Everything is in German now. Even the back button has changed from "Settings" to "Einstellungen".

在Einstellungen后退按钮上显示标签:

Lets tab on that "Einstellungen" back button:

现在几乎一切都很好;一切都变成了德国人。除了后退按钮之外的所有内容,仍然显示摘要而不是Überblick。我不明白为什么,因为当我在真正的iPhone 4上使用完全相同的源代码完成相同的步骤时,最后一个屏幕看起来像这样:

Almost everthing is fine now; everything has changed into german. Everything but the back button, which still says "Summary" instead of "Überblick". And I do not understand why, because when I do exactly the same steps with exactly the same sourcecode on my real iPhone 4, the last screen looks like this:

注意背面的文字 - 按钮。在真正的iPhone 4上,它是德语单词Überblick(这就是我想要的),但在模拟器中它是英文单词Summary。
这对我来说意味着,在某些手机上(比如我的iPhone 4),用户可以获得预期的效果,但也许在其他手机(可能是iPhone 4S)上,用户会看到错误的显示器。

Mind the text on the back-button. On a real iPhone 4 it is the german word "Überblick" (which is what I want), but in the simulator it is the english word "Summary". And this means to me, on some phones (like my iPhone 4) the user gets what is expected, but maybe on some other phones (maybe iPhone 4S) the user gets a buggy display.

有人知道我的代码有什么问题吗?

Has anybody an idea what is wrong with my code?

编辑: 2012-04-06 09:04 +02:00(欧洲中部夏令时)

2012-04-06 09:04 +02:00 (central european summer time)

我确实设法在另一台硬件上测试我的应用程序,旧的iPhone 3G(iOS 4.2.1)在旧的iPhone上我的应用程序的行为方式与模拟器中的完全相同。在iPhone 4上运行相同的应用程序会产生不同的行为。

I did manage to test my app on an other piece of hardware, an old iPhone 3G (iOS 4.2.1) On the old iPhone my app is behaving exactly the same way like in the simulator. Running the same app on iPhone 4 produces a different behaviour.

更确切地说:


  • 在iPhone 4上(iOS 5.1):应用程序正在执行我想要的操作,没有任何错误行为。

  • 在模拟器上(iOS 5.1):应用程序在导航控制器上显示错误的标题按钮。

  • 在iPhone 3G(iOS 4.2.1)上:应用程序显示与模拟器中相同的错误行为。

编辑: 2012-04-07 10:14 +02:00(欧洲中部夏令时)

2012-04-07 10:14 +02:00 (central european summer time)

通过观看iPhone 3G上的过渡,我喜欢一些有趣且可能有用的东西:当我用错误的文字选中按钮时,会发生以下情况:

By watching the transition on the iPhone 3G, I fond out something interesting and maybe helpfull: When I tab on the button with the wrong text, the following happens:


  1. 错误的文本被正确的文本替换

  2. 在此替换后,视图消失了动画(向右滑动)和底层视图变得可见。此转换的持续时间大约为0.3秒,在此短暂的时间间隔内,所有硬件iPhone和模拟器中都可以看到正确的文本。

但问题仍然是:为什么在iPhone 3G和模拟器中显示wront文本?为什么在iPhone 4中始终可以看到正确的文字?

But the question still is: Why is the wront text displayed in iPhone 3G and Simulator? Why is the correct text always visible in iPhone 4?

对我而言,好像在同一个地方有两个按钮,一个在另一个上面。在iPhone 4中,我的自定义按钮位于前面,隐藏了旧的系统生成按钮,但在模拟器和iPhone 3G中,旧的systemgenerated按钮位于前面,隐藏了我的自定义按钮。但是:即使我隐藏的自定义按钮比系统生成的更大(更宽),也看不到它。只有当幻灯片动画开始时,我的按钮才会显示。

To me it looks, as if there was two buttons at the same place, one over the other. In iPhone 4 "my" custom button is in front, hiding the old systemgenerated button, but in the simulator and in iPhone 3G the old systemgenerated button is in front, hiding my custom button. But: Even if my hidden custom button is bigger (wider) than the systemgenerated, nothing of it is visible. Only when the slide-out animation starts, my button becomes visible.

编辑 2012 -04-07 16:38 +02:00(欧洲中部夏令时)

2012-04-07 16:38 +02:00 (central european summer time)

下一个有趣的事实:

这就是到现在为止发生的事情:

This is what happened until now:

当按钮第一次出现时(第二次截图,见下文),我在上面写了一个标题,即在系统之前就已经成为一个词。然后用户选择一些动作,该按钮被另一个视图隐藏。在另一个用户操作后,按钮再次显示,现在它将获得一个新词作为标题(相同的意思,但新语言),但在iPhone 3G和模拟器上旧标题更强。新标题不会显示。旧标题就在那里。

When the button appers for the first time (2nd screenshot, see below), I put a word as title on it, that is identic to the word it would have become before from the system. Then the user selects some action, and this button is hidden by another view. After another user-action the button is revealed again, it now it shall get a new word as title (same meaning, but new language), but on iPhone 3G and on the simulator the old title is "stronger". The new title will not be displayed. The old title sticks there.

如果首先出现我在按钮上写一个单词作为标题,那就不会发生这种情况,这与系统生成的标题不同。如果第一个标题与默认标题不同,则稍后的更改将在所有iPhone和模拟器上执行。

This does not happen if at first appearence I write a word as title onto the button, that is different from the systemgenerated title. If the first title is different from the default-title, a later change will be executed on all iPhones and on the simulator.

这让我相信,iOS会做一些一种优化:如果,在首次出现按钮时,自定义标题与系统生成的标题相同,则稍后更改按钮标题将被忽略,但仅限于iPhone 3G和模拟器。在iPhone 4上,在任何情况下都允许稍后更改。

That makes me believe, that iOS does some kind of "optimization": If, at first appearance of the button, the custom title is identic to the systemgenerated title, than a later change of the buttons title will be ignored, but only on iPhone 3G and simulator. On iPhone 4 a later change will be allowed in any case.

但是在开头设置不同的标题以防止应用程序出现其错误行为不是一种选择。 / p>

But setting a different title at the beginning to prevent the app from its faulty behaviour is not an option.

推荐答案

Apple支持确实回答



我联系了Apple对此问题的支持,他们确实回答了问题。

Apple support did answer

I contacted Apple support for that issue and they did answer.

问题是,导航栏包含导航控制器堆栈上所有视图的后退按钮以及所有这些按钮需要同时更新。在viewWillAppear-Methods中更新位于堆栈上的视图是好的,但尝试更新此处的后退按钮并不是一个好主意。

The problem was, that the navigation bar holds all back-buttons for views on the navigation controllers stack and all this buttons needs to be updated at the same time. Updating the views that lay on the stack within their viewWillAppear-Methods is good, but trying to update the back-button at this place is no good idea.

解决方案:

扩展UIViewController的界面:

Extend the interface of UIViewController:

@interface UIViewController (extended)
    - (NSString *)localizedKey;
@end

对于在UINavigationController的堆栈上放置视图的每个UIViewController实现此方法:

For each UIViewController that puts a view on the UINavigationController's stack implement this method:

- (NSString*) localizedKey {
    return @"a title-keyword";
}

不要乱用 UIBarButtonItem self.navigationItem.backBarButtonItem

如果出现需要的标题更改,使用此代码片段为所有后退按钮执行此操作(请记住: LocalizedString(key)是一个自编写的宏,类似于 NSLocalizedString( key,comment)):

When if comes that titles need to be changed, do it for ALL back buttons with this snippet of code (remember: LocalizedString(key) is a self-written macro similar to NSLocalizedString(key,comment)):

NSArray* vcs = [self.navigationController viewControllers];
for (UIViewController* vc in vcs) {
    vc.navigationItem.backBarButtonItem.title = LocalizedString([vc localizedKey]);
    vc.title = LocalizedString([vc localizedKey]);
}






逐字回答Apple支持:


我们正在打击导航栏,在错误的时间强制更新。请注意,每个视图控制器中的所有视图都会正确更新。因此导航栏需要特别注意才能得到我们想要的东西。

We're fighting the navigation bar in forcing an update at the wrong time. Notice all the views in each view controller get updated properly. So the navigation bar needs special attention to get what we want.

要使其工作,您需要将后退按钮更改为堆栈上的所有视图控制器一次,(当用户选择一种语言时),而不是每次通过viewWillAppear出现时。

To get this to work, you need to change the back buttons to all the view controllers on the stack at once, (at the time the user selects a language) instead of when they each appear via "viewWillAppear".

这需要能够获取该按钮的本地化密钥以公共方式。我向UIViewController引入了一个类别,可以轻松采用这个:

This requires the ability to obtain the localized key for that button in a public way. I introduced a category to UIViewController to easily adopt this:

@interface UIViewController(扩展)

- (NSString *)localizedKey;

@end

@interface UIViewController (extended)
- (NSString *)localizedKey;
@end

然后您的LangSelectTabVC类可以立即更改所有后退按钮。这种方法会使按钮标题重绘正确。

Then your LangSelectTabVC class can change all the back buttons at once. This approach will make the button titles redraw correctly.

因此在viewWillAppear中,您不必更新每个后退按钮。这样做对UIKit来说似乎为时已晚,无法抓住更新。您还会在发生更新时重新创建新的后退按钮。这不是必需的,只需取当前的一个并更改它的标题:

So in viewWillAppear, you won't have to update each back button. Doing it there appears to be too late for UIKit to catch that update. You also re-create a new back button when an update occurs. This is not necessary, just take the current one and change it's title:

NSArray * vcs = [self.navigationController viewControllers];

for( UIViewController * vc in vcs)

{

vc.navigationItem.backBarButtonItem.title = LocalizedString([vc localizedKey]);

vc.title = LocalizedString( [vc localizedKey]);

}

NSArray *vcs = [self.navigationController viewControllers];
for (UIViewController *vc in vcs)
{
vc.navigationItem.backBarButtonItem.title = LocalizedString([vc localizedKey]);
vc.title = LocalizedString([vc localizedKey]);
}

我附上了一个修改过的项目,显示了这种解决方法。

I've attached a modified project showing this workaround.

这篇关于应用程序在iPhone 5.1模拟器和带有iOS 5.1的真实iPhone 4上表现不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆