重用Storyboard viewcontrollers

时间:2017-01-20 08:04:45

标签: ios objective-c uitableview storyboard

我正在重建一个我需要显示项目列表的应用程序。此列表使用API​​检索或从Core Data检索并显示在UITableViewController中。我遇到的问题是,已经存在七个不同的列表,其中存在小的差异。其中大部分只是不同的项目,但是一个列表中包含的搜索栏以及之前声明的一个列表将不会使用API​​加载,而是来自Core Data。

在我的Storyboard中,我添加了一个带有ItemsTableViewController类的UITableViewController,它有一个设计的UITableViewCell。我已经为此单元格添加了一个标识符,因此我可以在此视图控制器中重复使用它。从主屏幕到该视图控制器有一个segue。

这个想法是创建一个父对象(ItemsTableViewController)并添加多个子对象(SavedItemsTableViewController,LocalItemsTableViewController等),它们都将使用父对象的共享逻辑,只进行一些小的更改(API和一些自定义的东西)。

我目前的工作是什么,但没有子对象:

- (void)offlineButtonPressed {
    [self performSegueWithIdentifier:@"openItemsTableViewController" sender:@(ItemListOffline)];
    //[[self navigationController] pushViewController:[[OfflineItemsTableViewController alloc] init] animated:YES];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"openItemsTableViewController"]) {
        switch((ItemList)[sender unsignedIntegerValue]) {
            case ItemListOffline: { [(ItemsTableViewController *)[segue destinationViewController] retrieveOfflineDocuments]; break; }
            case ItemListSearch: {
                [(ItemsTableViewController *)[segue destinationViewController] retrieveDocumentsWithQuery:@""];
                [(ItemsTableViewController *)[segue destinationViewController] addSearchBar];
                break;
            }
            // Loop through all the list...
            default: { NSAssert(NO, @"Unhandled type of document list."); break; }
        }
    }
}

因此应用程序只调用处理请求的父对象的函数。但是你可能会感觉到,对象的可维护性会降低。在评论中我推动了子视图控制器,但由于它不包括故事板视图,我需要从头开始重新创建单元格,这感觉不太好。此外,由于重用标识符,它无法正常工作,因为它无法使用tableView:cellForRowAtIndexPath:方法中设置的标识符对单元格进行出列。

现在我想知道最佳做法是什么?看来我不能从故事板中为多个子类使用save UITableViewController,可以吗?但是在故事板中创建七个(可能是未来甚至更多)控制器,我需要将单元格复制到每个控制器并且只是给它们不同的类似乎不是这样做的。并向父级添加一个方法,其中列表将被不同地检索,并且更改某些内容(如添加搜索栏)正在运行,但也不是最好的方式。

更新:ItemsTableViewController中的逻辑非常简单。在委托和数据源中,我处理的文档几乎相同。执行每个列表类型检索的方法类似于:

- (void)retrieveOfflineItems {
    [self startLoading];

    [[APIManager instance] getOfflineItems:^(NSArray<ItemList *> *list, NSError *error) {
        [self setDocuments:list];
        [[self tableView] reloadData];
    }];
}

但还有更多的东西,比如搜索必须添加一个搜索栏(一旦加载了视图)。因此在执行segue时需要调用多个方法。

2 个答案:

答案 0 :(得分:1)

您可以拥有一个UITableViewController,其中包含所有您可能的表格单元格,并且作为prepareForSegue调用的一部分,您应该为其设置类型标识符控制器和数据 - 无论数据来自何处。

UITableViewController类中,您可以隐藏/显示此数据类型所需的功能(例如搜索栏),并在tableView方法中选择所需的数据源。

这样,你需要维护的一个UITableViewController类比一个专用类稍微复杂一点,但是比7个或更多的类要复杂得多!

假设你已经设置了一个变量dataType来识别你需要的数据类型,你可以为numberOfRowsInSection提供类似的东西,然后对其他tableView方法也类似

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    switch self.dataType {
    case dataType.MyFirstDataType:
        return myFirstDataTypeArray.count

    case dataType.MySecondDataType:
        return mySecondDataTypeArray.count

    case dataType.TheCoreDataType:
        return myCoreDataArray.count

    default:
        break
    }
}

答案 1 :(得分:0)

使用所有子视图和单元格(包括searchController)创建父UITableViewController。初始化它并根据条件添加/删除视图和单元格