iOS 根据对象 ivar 以编程方式构建视图

Posted

技术标签:

【中文标题】iOS 根据对象 ivar 以编程方式构建视图【英文标题】:iOS build view programatically depending on object ivar 【发布时间】:2011-06-15 14:29:14 【问题描述】:

我有一个非常有趣的问题,它涉及loadViewviewDidLoadviewWillAppear 和 ivar 的状态。我有一个基于导航的应用程序。从我的第一级视图中,我有一个表格列表,然后单击其中一个单元格,它将带我进入第二级视图(详细视图)。当我单击一个单元格时,我还将一个“Office”对象(其中包含像streetAddressboxAddress 这样的字符串)添加到被推送的视图控制器中。然后,我使用 Office 对象中的内容填充详细视图,例如 [box setText:[self.office boxAddress]];(框是 UILabel)。现在我想在这里实现的是,有时 boxAddress 的 stringValue 是空的,在这种情况下,我不想向 UILabel 添加一个空字符串,而是想将下一个 UILabel 向上移动(并取代箱地址)。因此,因此我进行了条件检查以查看 boxAddress 是否为空,如果是,则应使用特定坐标设置 UILabels,如果不为空,则应使用其他特定坐标设置 UILabels。

我知道如果您希望每次加载视图时都运行代码,您应该使用viewWillAppear。但由于某种原因,viewWillAppear 似乎仅在boxAddress 字符串为空时才运行。如果我单击具有空 boxAddress 的单元格,它将使用来自我单击的最后一个具有非空 boxAddress 的单元格的 boxAddress 中的值。

我会把我的代码贴在这里,看看你能不能告诉我我在这里做错了什么。

// Implement loadView to create a view hierarchy programmatically, 
// without using a nib.
- (void)loadView 

    //allocate the view
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

    //set the view's background color
    self.view.backgroundColor = [UIColor whiteColor];


- (void)viewDidLoad


    //add the labels
    name = [[UILabel alloc] initWithFrame:CGRectMake(10.0,10.0,320.0,20.0)];
    [name setBackgroundColor:[UIColor clearColor]];
    [name setTextColor:[UIColor blackColor]];

    street = [[UILabel alloc] initWithFrame:CGRectMake(10.0,30.0,320.0,20.0)];
    [street setBackgroundColor:[UIColor clearColor]];
    [street setTextColor:[UIColor blackColor]];

    //if no box address, move up the rest of the addresses
    if ([[self.office boxAddress] length] == 0) 

        zip = [[UILabel alloc] initWithFrame:CGRectMake(10.0,50.0,320.0,20.0)];
        [zip setBackgroundColor:[UIColor clearColor]];
        [zip setTextColor:[UIColor blackColor]];

        phone = [[UILabel alloc] initWithFrame:CGRectMake(10.0,70.0,320.0,20.0)];
        [phone setBackgroundColor:[UIColor clearColor]];
        [phone setTextColor:[UIColor blackColor]];

        fax = [[UILabel alloc] initWithFrame:CGRectMake(10.0,90.0,320.0,20.0)];
        [fax setBackgroundColor:[UIColor clearColor]];
        [fax setTextColor:[UIColor blackColor]];

        [self.view addSubview:name];
        [self.view addSubview:street];
        [self.view addSubview:zip];
        [self.view addSubview:phone];
        [self.view addSubview:fax];

     else 

        box = [[UILabel alloc] initWithFrame:CGRectMake(10.0,50.0,320.0,20.0)];
        [box setBackgroundColor:[UIColor clearColor]];
        [box setTextColor:[UIColor blackColor]];

        zip = [[UILabel alloc] initWithFrame:CGRectMake(10.0,70.0,320.0,20.0)];
        [zip setBackgroundColor:[UIColor clearColor]];
        [zip setTextColor:[UIColor blackColor]];

        phone = [[UILabel alloc] initWithFrame:CGRectMake(10.0,90.0,320.0,20.0)];
        [phone setBackgroundColor:[UIColor clearColor]];
        [phone setTextColor:[UIColor blackColor]];

        fax = [[UILabel alloc] initWithFrame:CGRectMake(10.0,110.0,320.0,20.0)];
        [fax setBackgroundColor:[UIColor clearColor]];
        [fax setTextColor:[UIColor blackColor]];

        [self.view addSubview:name];
        [self.view addSubview:street];
        [self.view addSubview:box];
        [self.view addSubview:zip];
        [self.view addSubview:phone];
        [self.view addSubview:fax];
    

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.


// viewWillAppear method is run every time the view is loaded as opposite to the viewDidLoad method which only is run once
// in this program DisclosureDetail view needs to be loaded for each detail view with different content each time
- (void)viewWillAppear:(BOOL)animated 

    NSLog(@"%@", [self.office boxAddress]);

    [name setText:[self.office name]];
    [street setText:[self.office streetAddress]];
    if ([[self.office boxAddress] length] > 0) 
        [box setText:[self.office boxAddress]];
    
    [zip setText:[NSString stringWithFormat:@"%@ %@", [self.office zipCode], [self.office city]]];
    [phone setText:[self.office phoneNo]];
    [fax setText:[self.office faxNo]];

    [super viewWillAppear:animated];

【问题讨论】:

【参考方案1】:
if ([[self.office boxAddress] length] > 0) 
    [box setText:[self.office boxAddress]];

如果 boxAddress 的长度为 0,那么 box 将继续包含您在上次视图出现时在其中设置的任何文本。

您将需要在每次视图出现时隐藏和显示box,而不仅仅是在加载视图时,因为视图可能已加载然后用于显示多个不同的offices。

【讨论】:

但我认为每次显示视图时都会运行 viewWillAppear 方法,因此如果boxAddress 为空,它不应该显示吗?我将如何隐藏和显示box?如果我隐藏它,那么它下面的 UILabel 会被放置在“上面”吗? viewWillAppear 在您期望的时候被调用,但没有任何东西会为您重置视图的内容,因此如果您不更新box,它将继续显示上次视图出现时包含的任何内容。如果您隐藏 box 其他标签不会发生任何事情,您需要自己重新定位它们。这种界面的一个常见解决方案是让每个字段成为表格视图中的一个单元格,以便您可以调整哪些单元格出现并且它们将垂直堆叠。 那么最简单的解决方案是使用表格视图吗? cellForRowAtIndexPath 的一些伪代码会是什么?是否会在row 上使用开关,然后根据行显示不同的数据?

以上是关于iOS 根据对象 ivar 以编程方式构建视图的主要内容,如果未能解决你的问题,请参考以下文章

IOS在ViewController中以编程方式删除子视图的位置

iOS - 从 XIB 文件中引用和以编程方式移动视图

iOS 视图与视图层次结构(内容根据iOS编程)

以编程方式添加的视图对象未显示在情节提要中

iOS 数据驱动以编程方式设置视图和操作?寻求建议

CAGradientLayer:其他 UIObjects 没有出现