应用程序在 iPhone 5.1 模拟器和装有 iOS 5.1 的真实 iPhone 4 上表现不同

2023-12-21

简而言之:

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

这取决于硬件

  • 该错误发生在 iPhone 3G (iOS 4.2.1) 和模拟器 (iOS 5.1) 上
  • 使用相同的源代码,iPhone 4 (iOS 5.1) 上没有错误

这取决于标题中写入的单词

  • 创建按钮时,它从我自己编写的创建方法中获取与自动获取的标题相同的单词(即导航控制器堆栈上的上一页的标题),并且当其他情况匹配时,然后,当稍后尝试更改按钮的标题时,旧文本会卡住并且新标题将不会显示。
  • 当在创建时按钮获得一个与其默认标题不同的单词作为标题时,只要您不为其分配默认标题,则其标题的每次更改都可以正常工作。
  • 如果在对许多不同的标题进行多次成功更改之后,您将单词放在按钮标题上(这是其默认标题),那么该单词就会被卡住。以后的更改将不被接受(没有任何消息,并且只有在其他情况匹配的情况下)

这取决于按钮是否同时不可见。

  • 如果另一个视图被推送到导航控制器堆栈上,则带有有缺陷按钮的旧页面会被新页面隐藏,并且当新页面稍后再次从堆栈中弹出时,这会使按钮再次可见,(并且当其他情况匹配)然后旧文本被卡住并且更改它的尝试被忽略(没有任何消息)。
  • 如果该按钮是较新隐藏的,则更改其标题永远不会有问题。我总是工作。

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

  • 当由于上述情况的组合而忽略更改后退按钮标题的尝试时,当按下后退按钮并且页面向右滑动的动画为时,正确的标题无论如何都会在大约 0.3 秒内可见。处理。在动画开始时,旧的卡住标题将被正确的标题替换,并且正确的标题在动画期间可见。

详细说明

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

表1、命名GeneralTableVC是堆栈上的根视图。它没有后退按钮。它为用户提供了应用程序中存储内容的摘要,并显示带有设置按钮的工具栏。

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

表2、命名SettingsTabVC有一个后退按钮,这个按钮在模拟器中会出现问题,但在我运行 iOS 5.1 的真实 iPhone 4 上运行良好。

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

表3、命名LangSelectTableVC还有一个后退按钮,但这个按钮在两种设备(iPhone 模拟器和真实 iPhone 4)中都工作得很好。

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

重绘表格本身没有问题,导航栏中的标题也是如此。但后退按钮上的文字也必须翻译,这有点棘手。我对两个后退按钮都做了同样的技巧,对于表 3 上可见的指向表 2 的按钮来说效果很好。但是使用完全相同的代码,模拟器中存在问题(但在真实的设备上则不然) iPhone),表 2 上有按钮指向表 1。

我给您一些代码片段和一些屏幕截图,以向您展示我所做的事情以及正在发生的事情:


源代码

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

我确实定义了一个重绘协议:

协议.h

#ifndef ToDo_Project_Protocols_h
#define ToDo_Project_Protocols_h

@protocol redrawProt
- (void) mustRedraw;
@end

#endif

这是表 1 的标题:

通用表VC.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 and 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)。表2中的代码(SettingsTabVC.m)和表3(LangSelectTabVC.m) 类似地是相同的。我没有展示实现 UITableViewDataSource 协议的代码部分。我认为这些部分对于解释问题来说并不重要。

在此代码中,您将找到宏LocalizedString(keyword)其作用与NSLocalizedString(keyword,comment),即将关键字翻译成所需的语言。我的这个宏版本使用不同的捆绑包进行翻译(不是主捆绑包)

通用表VC.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”。

现在我们用 Tab 键切换到第一行(“Language English >"):

一切安好。 现在让我们更改语言。选项卡“German":

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

让我们点击“Einstellungen”后退按钮:

现在几乎一切都很好;一切都变成了德语。除了后退按钮之外的所有内容,该按钮仍然显示“Summary”而不是“Überblick”。我不明白为什么,因为当我在真正的 iPhone 4 上使用完全相同的源代码执行完全相同的步骤时,最后一个屏幕如下所示:

注意后退按钮上的文字。在真正的 iPhone 4 上,它是德语单词“Überblick”(这就是我想要的),但在模拟器中它是英语单词“Summary”。 这对我来说意味着,在某些手机(例如我的 iPhone 4)上,用户会得到预期的结果,但在其他一些手机(可能是 iPhone 4S)上,用户可能会遇到有问题的显示。

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


EDITs

Edit: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) 上:应用程序显示与模拟器中相同的错误行为。

Edit:2012-04-07 10:14 +02:00(中欧夏令时间)

通过观察 iPhone 3G 上的转换,我发现了一些有趣的事情,并且可能会有所帮助:当我点击带有错误文本的按钮时,会发生以下情况:

  1. 错误的文本被正确的文本替换
  2. 替换后,视图以动画方式消失(向右滑动),并且底层视图变得可见。此转换的持续时间约为 0.3 秒,在这段较短的时间内,所有硬件 iPhone 和模拟器中都可以看到正确的文本。

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

在我看来,好像同一个地方有两个按钮,一个在另一个上。在 iPhone 4 中,“我的”自定义按钮位于前面,隐藏了旧的系统生成的按钮,但在模拟器和 iPhone 3G 中,旧的系统生成的按钮位于前面,隐藏了我的自定义按钮。但是:即使我隐藏的自定义按钮比系统生成的更大(更宽),也看不到任何内容。仅当滑出动画开始时,我的按钮才可见。


Edit:2012-04-07 16:38 +02:00(中欧夏令时间)

下一个有趣的事实:

这是到目前为止发生的事情:

当该按钮第一次出现时(第二张屏幕截图,见下文),我在其上放置了一个单词作为标题,该单词与系统之前生成的单词相同。然后用户选择某个操作,并且该按钮被另一个视图隐藏。在另一次用户操作之后,按钮再次显示,现在它应该得到一个新词作为标题(含义相同,但新语言),但在 iPhone 3G 和模拟器上,旧标题“更强”。新标题将不会显示。旧标题仍保留在那里。

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

这让我相信,iOS 做了某种“优化”:如果按钮第一次出现时,自定义标题与系统生成的标题相同,则按钮标题的后续更改将被忽略,但仅限于 iPhone 3G和模拟器。在 iPhone 4 上,无论如何都允许稍后进行更改。

但在开始时设置不同的标题来防止应用程序出现错误行为并不是一种选择。


我怀疑您所看到的问题归因于模拟器上发生的序列与真实硬件之间的微妙时序问题。

视图控件不一定在 viewDidLoad 中实例化,因此您应该等到 viewWillAppear 来设置标题值(等)。

以下内容具有建设性意义,请本着其意图进行理解:

在不详细检查您的代码的情况下,我怀疑您想要实现的目标可以更确定地实现。你想要做的事情并不困难或不寻常,但我担心你的代码看起来不必要地复杂 - 可能是由于你试图修复这些计时问题。

查看一些简单的示例和教程,并简化您的代码,以便它不使用标志来跟踪状态(mustRedrawMyself),因为这不是必需的。记住在 viewWillAppear 之前不要设置视图/控件的属性,看看你进展如何。

如果您还没有的话,您可能还想查看对本地化的内置支持。

祝你好运。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用程序在 iPhone 5.1 模拟器和装有 iOS 5.1 的真实 iPhone 4 上表现不同 的相关文章

  • iPhone 开发 - XMLParser 与 libxml2 与 TouchXML

    我找不到这些解析技术的比较 哪一种最常用 问候 穆斯塔法 NSXMLParser 是一个SAX http en wikipedia org wiki Simple API for XML解析器 这意味着它遍历 XML 文档 并通知您 通过委
  • Cocoapods 和 Xcode,ld:找不到 -lAFNetworking 的库

    我有这个 pod 文件包含所有这些库 platform ios 7 0 target PP for iPad do pod AFNetworking 1 1 pod RaptureXML 1 0 pod NoticeView pod iVe
  • LocalNotifications 的振动和声音

    如何向本地通知添加振动和声音 code UILocalNotification notification UILocalNotification alloc init NSDate firedate settime date notific
  • 来自应用程序的 Apple TV 上的 AirPlay 元数据 (AVPlayer - MPVolumeView)

    我的应用程序成功通过 AVPlayer 传输 MP3 我实现了一个 MPVolumeView 来引入 AirPlay 支持 效果很好 但我注意到我的苹果电视上的标题信息没有显示流式 MP3 中的任何内容 而只是显示 未知 信息 是否有办法从
  • 存储应用内购买的正确且安全的方式

    在设备上存储应用内购买的最佳方式是什么 这样购买也可以离线访问 但是 购买的安全性没有受到损害 不要在设备上存储任何有价值的东西 因为它不可信 并且很容易被有动机的人破坏 现在 所有这一切都取决于所购买物品的类型和价值 以及如果物品受损会发
  • 访问 iPhone 上用户的短信

    有没有一种方法可以访问用户的短信 没有互联网连接 显然 不尝试获取客户的消息 并分析应用程序中的文本 如果没有 出于安全原因 这是完全可以理解的 但我想我还是会问 不 你只能发送它们 S http developer apple com l
  • 从故事板向 UILabel 属性字符串添加下划线失败

    从故事板中我选择有问题的 UILabel 然后在属性检查器 gt 标签 gt 我选择 属性 同样在属性检查器 gt 标签 gt 文本 gt 我选择内容 然后我单击字体图标并选择下划线 基本上 我从弹出的 字体 窗口中选择的任何更改都不会生效
  • iOS 上的 Phonegap 3.5 媒体插件错误“无法使用 AvAudioRecorder 开始录音”

    我试图让用户在 Phonegap 应用程序中录制音频文件 它在 Android 上运行良好 但在 iOS 上 当开始录制时出现以下错误 无法使用 AvAudioRecorder 开始录音 我使用 wav 文件名 首先创建该文件 我已按照我找
  • 什么是 Core Audio 错误 561015905?为什么当我使用锁定按钮时会发生这种情况?

    自从升级到 iOS 10 和 Xcode 8 以来 每当我使用锁定按钮关闭屏幕时 我的 iOS 应用程序就会抛出错误并崩溃 错误是 由于未捕获的异常 com apple coreaudio avfaudio 而终止应用程序 原因 错误 56
  • 将核心数据数据库/.sqlite 文件同步到 Dropbox

    我正在尝试将我的核心数据数据库 sqlite 文件同步 上传到保管箱 一旦我的用户登录 我就有一个上传文件的按钮 IBAction sync NSString localPath NSBundle mainBundle pathForRes
  • SpriteKit中滚动背景的速度逐渐增加

    我正在 SpriteKit 中制作一个简单的游戏 并且我有一个滚动背景 简单的情况是 在加载游戏场景时 一些背景图像彼此相邻放置 然后当图像滚动到屏幕外时 图像会水平移动 这是我的游戏场景中的代码didMoveToView method s
  • iOS9 按需访问和下载资源

    我正在尝试实现新的 iOS9 功能应用程序细化 我了解如何在 Xcode 7 中标记图像并启用按需资源 但我不明白如何在我的应用程序中实现 NSBundleResourceRequest 有人可以帮助我 我将不胜感激 大部分信息都可以在 A
  • 需要从另一个viewController调用其他viewController中的方法

    我有一个具有多个视图控制器的应用程序 其中一些视图控制器包含运行各种任务的方法 我需要做的是 当初始 viewController 加载时 在其他 viewController 中调用这些方法 以便它们在后台运行 但是 我在执行此操作时遇到
  • 当 Firebase 数据库中的值发生更改时创建推送通知

    我想在 firebase 数据库中的值发生更改时向用户发送推送通知 这是我的数据库 Battles 00000111 062B3333 4046 4FB4 AA37 C2B05853E497 BattleProgress Player1 l
  • 检测图像中的特定对象,即使用 opencv 进行图像分割

    我必须选择 iPhone 上图像中可见的任何特定对象 基本上我的项目是根据我的触摸来分割图像对象 我遵循的方法是首先检测图像的轮廓 然后根据手指触摸选择特定序列 有没有其他方法更强大 因为我必须在视频帧上运行它 我在该项目中使用 OpenC
  • 如何为应用程序加载器创建上传文件?

    当我使用应用程序加载器时 它要求我 选择 要上传的文件 如果我理解正确 它应该是我在应用程序包的 产品 下看到的 appName app 文件 我右键单击它并选择 在 Finder 中显示 以访问库中的特定文件 那么我应该将其压缩 ZIP
  • 在滚动视图内的 ImageView 中裁剪缩放图像

    我已经做了很多努力 最后我需要帮助 谢谢 目标 1 如何将 imageView 放入 ScrollView 中 2 我如何在scrollView内部裁剪缩放图像 我在滚动视图中有一个 imageView 我想要缩放后裁剪图像 该图像显示在滚
  • 使用 XCode 5 的 iPhone 弹出窗口视图

    我想重复使用 iPhone 中描述的弹出窗口这个视频 http youtu be 1iykxemuxbk这正是我所需要的 问题是我无法绑定UIViewController弹出窗口的属性UIViewController就像视频中一样 该视频的
  • PerformSegueWithIdentifier 不会产生带有标识符错误的 Segue

    我很难让 PerformSegueWithIdentifier 正常工作 我不断得到 Receiver
  • iPhone 向右翻转按钮(如 iTunes)

    我正在尝试在两种视图之间切换 这很简单 代码如下 但我还想同时翻转用于执行翻转的按钮 当您播放曲目时 您可以在 iPod 应用程序中看到此行为 点击翻转按钮可在封面艺术和曲目列表之间翻转 但同时会翻转按钮 这是导航控制器上的一个页面 我要翻

随机推荐