在我重新加载 UIView 之前,更新标签文本不起作用

Posted

技术标签:

【中文标题】在我重新加载 UIView 之前,更新标签文本不起作用【英文标题】:Updating label text doesn't work until I reload the UIView 【发布时间】:2014-10-01 18:15:57 【问题描述】:

我正在努力解决一个我根本不明白的问题。这是以下场景:

    我尝试在 ios 中创建一个多视图向导。经过深思熟虑,我决定采用一种可能并不理想但能帮助我保持代码整洁的方法。我不想链接十个视图控制器并手动管理。 向导有一个视图控制器。在开始时,它会将一定数量的 UIView 加载到视图中,并允许我左右滚动。代码如下。 UIViews 是在界面生成器中创建的,我有一个包含所有视图的 XIB 文件。 每个 UIView 都有更多连接到文件所有者的 IBOutlets(例如标签),在本例中为向导视图控制器。

除了加载的 UIViews 上的标签不更新这一事实之外,这一切都非常有效。问题来了:

    我调用向导,它会立即加载所有 UIView 和 Outlets 我跳过向导。

    然后问题就出现了:

    示例: 第 2 步有一个调用通讯录的按钮(有效) 地址簿打开,返回一个对象(有效) 但是当我分配一个值时,我在 UIView“步骤 2”上的标签没有更新。

只有在我从向导中删除此 UIView 并将其重新添加后,它才能工作。在我看来, UIView 加载正确,但对其插座的任何后续更改都不起作用。

顺便说一句,我验证了标签以及按钮和所有内容可能都已连接。当标签作为 XIB 的一部分加载时,我只是无法更新标签,并且在初始加载后值会发生变化。

代码:

向导加载 UIViews:

-(void)configureWizard

    self.showsHorizontalScrollIndicator = NO;
    self.showsVerticalScrollIndicator = NO;
    self.scrollEnabled = NO;
    self.contentSize = CGSizeMake(CGRectGetWidth(self.frame) * [wizardDelegate numberOfSteps], CGRectGetHeight(self.frame));
    self.delegate = self;


-(void)loadWizard

    [self configureWizard];
    [self updateNavButtonsIfNecessary];
    currentIndex = 0;
    for (int i = 0; i<[wizardDelegate numberOfSteps]; i++)
    
        [self loadWizardStepAtIndex:i];
    


- (void)loadWizardStepAtIndex:(int)index 
    CGRect frame = self.frame;
    frame.origin.x = CGRectGetWidth(frame) * index;
    frame.origin.y = 0;
    UIView *view = [wizardDelegate viewForStepAtIndex:index];
    view.frame = frame;

    [self addSubview:view];

向导主视图 Controller.h(文件所有者)

@property (strong, nonatomic) IBOutlet UIView *memberwizard_1;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_2;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_3;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_4;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_5;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_6;
@property (strong, nonatomic) IBOutlet UIView *memberwizard_7;


@property (strong, nonatomic) IBOutlet UIButton *wizard2_lookupExistingContact;
@property (strong, nonatomic) IBOutlet UILabel *wizard2_nameLabel;

向导主视图 Controller.m(文件所有者)

-(UIView *)viewForStepAtIndex:(int)index

    [[[NSBundle mainBundle]loadNibNamed:@"wizard_newMember" owner:self options:nil] lastObject];;

    switch (index) 
        case 0:
            return self.memberwizard_1;
            break;
        case 1:
            return self.memberwizard_2;
            break;
        case 2:
            return self.memberwizard_3;
            break;
        case 3:
            return self.memberwizard_4;
            break;
        case 4:
            return self.memberwizard_5;
            break;
        case 5:
            return self.memberwizard_6;
            break;
        case 6:
            return self.memberwizard_7;
            break;

        default:
            return self.memberwizard_1;
    

通讯录返回函数

-(void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person

    [self displayPersonRecord:person];
    [self dismissViewControllerAnimated:YES completion:nil];

尝试更新第二个 UIView 上的标签(这是出现问题的地方 - 它不起作用)。

-(void) displayPersonRecord:(ABRecordRef)person

    NSString *firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *lastName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSLog(@"Name is %@", [NSString stringWithFormat:@"%@ %@", firstName, lastName]);
    self.wizard2_nameLabel.text = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
    [self.wizardDelegate refresh:self.memberwizard_2]; //if called, the current view will be removed and re-added - then the label gets updated.

但正如我提到的,如果我重新加载视图,它就会起作用(见截图)

重新加载方法 重要提示:这是讨厌的代码,不用于生产,它只是一个测试,看看重新加载视图是否有帮助。

-(void)refresh:(UIView *) oldView

    [oldView removeFromSuperview];
    CGRect frame = self.frame;
    frame.origin.x = CGRectGetWidth(frame) * currentIndex;
    frame.origin.y = 0;
    //UIView *view = [wizardDelegate viewForStepAtIndex:currentIndex];
    oldView.frame = frame;
    [self addSubview:oldView];

如果此时我从向导中删除 self.memberwizard_2 视图并将其重新添加到一切正常,但它不会马上。这可能与我启动 UIViews 的方式有关吗?顺便说一句,最后一段中的 NSLog 也可以显示联系人的姓名。

如果有人知道处理向导的更简单方法,请告诉我:) PageViewControllers 很痛苦,因为我需要在屏幕之间切换一个对象,但需要在每个屏幕中显示不同的操作。

非常感谢并为代码混乱道歉,我试图让它尽可能清晰,但也许不是。

【问题讨论】:

[self.wizardDelegate refresh:[self.memberwizard_2]; 这里的左括号和右括号的数量不一样。首先,尝试解决此问题。 [self.wizardDelegate refresh:self.memberwizard_2]; 感谢您的评论,但这是一个错字(或复制粘贴错误)。但这不是问题,因为我实际上不想使用这种刷新方法。我想弄清楚为什么标签一开始没有更新 您是否尝试过使用调试器单步执行您的代码? 在将新字符串分配给标签之前,如果使用NSLog(@"Object: %@, View: %@, Subviews: %@, Label: %@", self, self.memberwizard_2, self.view.subviews, self.wizard2_nameLabel),您会看到什么? 尝试 awakeFromNib 而不是在 -(UIView *)viewForStepAtIndex:(int)index 中加载它。因为视图已经加载。不要加载另一个。 【参考方案1】:

这就是我认为出错的地方。对于每个“WizardStep”,您调用viewForStepAtIndex,它会加载NIB 并返回相关视图。然后将其添加为子视图。但是当您处理下一个 WizardStep 时,NIB 会再次加载,这会创建其所有对象的新实例并将所有 Outlets 和 Actions 重新连接到新加载的对象。因此,您刚刚添加为子视图的视图(因此显示)不再被您的网点指向。因此,当您更新标签时,它不会更新屏幕上的标签,而是完全不在层次结构中的视图上的一个完全不同的标签。

所以,我会修改你的代码,使loadNibNamed: 方法只运行一次。

【讨论】:

好吧,它来了:我一定是因为盯着这个问题而脑死亡。当然,您是对的(Antonio 也是如此)- 我在没有注意到的情况下一遍又一遍地加载相同的东西,造成了完全的混乱。我现在对其进行了更改,以便视图控制器加载了 NIB 并完成......它就像一个魅力。就像我说的——脑死亡!非常感谢您的帮助 - 安东尼奥和您(当然还有其他人!)

以上是关于在我重新加载 UIView 之前,更新标签文本不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 UIView 中重新加载 JSON 提要

如何重新加载 UIView

更改自定义 UIView 的 UILabel 文本不起作用

UITableviewCell 在重新加载时显示旧数据和新数据

在 uitableviewcell 中更新标签文本而不重新加载整个表格

使用 nib 中的视图重新加载 UIView 属性