gpt4 book ai didi

ios - 重构iOS项目以不使用 Storyboard

转载 作者:行者123 更新时间:2023-11-29 02:57:07 25 4
gpt4 key购买 nike

随着我的项目变得越来越大和越来越复杂,我发现使用情节提要变得难以管理。我的情节提要文件越来越大,我对在应用程序中重用组件/整个视图的需求正在增长,并且从屏幕跳转到完全不同的屏幕的需求变得越来越困难,而整个情节提要中没有混乱的混乱局面。

我已经开始在像这样的代码中做简单的事情,例如push / pop / present模态视图控制器:

UIViewController *vc = [[UIViewController alloc] init]; // usually a custom subclass of uiviewcontroller
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:vc animated:YES completion:nil];


但我正在寻找有关如何进一步做到这一点的建议。

例如:我希望能够从一个选项卡切换到导航控制器堆栈中另一个选项卡的第三视图控制器。在情节提要中,我可以简单地在两个视图控制器之间拖动一个序列。没有情节提要,我可以在我的tabcontroller上设置选定的索引,然后将控制器推入新标签的选定索引中,直到我处于我想要的那个位置?就像是:

[self.tabBarController setSelectedIndex:2]; // then how do I get deep inside the new tab controller's view heirarchy?


确实,我只是在寻找有关如何将使用情节提要的大型项目重构为不使用情节提要的项目的文章/建议。我已经发现该项目更容易管理,更易于重用组件,并且在没有情节提要的情况下也更易于控制。只需更多建议/实践即可完成此过渡。

谢谢

最佳答案

为我最复杂的UI呈现情节提要...



这是我(当前)六个独立的UI选项卡所需要的,它具有“潜入”多个深度控制器的无限能力,以使用户能够找到他们要查找的数据。

警告警告警告
我担心用户可能会在此迷宫中迷路。请注意您的UI设计,以确保用户了解他们对数据查找野生动物园有多“深入”,或者至少为他们提供了一种“弹出”退出途径的简单方法。

我将我的VC / TVC按列对齐,以易于使用-事实证明-易于描述功能。

标签栏控制器和导航控制器不言自明。

在本练习中,我将忽略“特殊功能”控制器。

因此,让我们专注于:


“标准列表”类型的TVC,
“详细内容”类型的TVC,&
“选择”类型的TVC。


当用户选择一个选项卡时,“标准列表”类型的TVC将提供UI来向用户显示项目列表。添加按钮(导航栏项)提供了通过“详细内容”类型TVC手动将新项添加到列表的机会。

IB Segues从“标准列表”更改为“详细内容”类型的TVC

从“标准列表”中项目行开始的情节提要(创建的情节提要)触发针对“详细内容”类型TVC的事件,因此用户可以查看和/或编辑项目数据。

从“标准列表”中的“添加”按钮(导航栏项目)中选择一个情节提要(创建的情节提要)会触发对“详细内容”类型TVC中的空白或“新”项目的选择,因此用户可以添加一个新项目和相关数据。

IB Segues从“详细内容”到“选择”类型的TVC

从“详细内容”中项目行中选择的情节提要(创建的情节提要)会触发对TVC类型“选择”的选择,具体取决于该内容所需的数据类型。 (例如,“从...中选择”类型的TVC之一是嵌入在标准视图控制器中的UIDatePicker,它使用户能够轻松选择日期和/或时间。)

我到达了要开始从“选择”类型的TVC跳回到“详细内容”类型的TVC的地步。

我什至没有尝试手动执行此操作。我的强迫症要求我的情节提要尽可能保持原始和整洁-绝不疯狂地向后“倒退”以促进控制器的重用。

因此,终于有了一个答案-是的,谢谢您的支持-我认为序言是必要的。

对于与“选择方式”类型的TVC相关的每个类,我创建了一个自定义序列,嵌入到TVC实现文件的代码中。

随着我对自定义脚本的熟悉,我可能会将它们删除到一个单独的“ helper”类中。

但是直到那时,“选择”类型TVC的每个类实现文件顶部的代码...

////////////////////////////////////////////////////////////
/// Subclass of UIStoryboardSegue must override -perform ///
////////////////////////////////////////////////////////////
@interface Segue_YourCustomNameHere : UIStoryboardSegue

@end

@implementation Segue_YourCustomNameHere

- (void)perform {
ThisSelectFromClass *sourceViewController = self.sourceViewController;
[sourceViewController.navigationController pushViewController:self.destinationViewController animated:YES];
}

@end
////////////////////////////////////////////////////////////
/// END of subclass of UIStoryboardSegue ///
////////////////////////////////////////////////////////////


@interface ThisSelectFromClass ()

//private declarations

@end


@implementation ThisSelectFromClass

//implementation code

@end


容易,对!

下一步?通过“ Storyboard ID”提供要重用的控制器。

回到您的Interface Builder / Storyboard文件,然后选择要在代码中重用的控制器。

在身份检查器中的“身份”子标题下,键入“故事板ID”。我喜欢在故事板ID的前面加上“ id_”,如下面的示例图像所示。我将在下面的示例代码中使用此示例,因此请注意这一点。



下一步?如何触发自定义搜索???

返回该类的实现文件(上面的示例使用 ThisSelectFromClass

让我们建议,当用户点击特定的数据行时,需要进行序列检测。

代码...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *mainStoryboard = nil;
UIStoryboard *storyboard = nil;

UIViewController *destinationVC = nil;
Segue_YourCustomNameHere *segue = nil;

mainStoryboard = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIMainStoryboardFile"];
storyboard = [UIStoryboard storyboardWithName:mainStoryboard bundle:nil];

// I check the appropriate path depending on the title of my TVC
// You may need to determine another check method.

if ([self.title isEqualToString:<<the title string>>]) {
destinationVC = [storyboard instantiateViewControllerWithIdentifier:@"id_DetailContentVC"];
segue = [[Segue_YourCustomNameHere alloc] initWithIdentifier:@"segue_YourSegueIdentifierNameHere"
source:self
destination:destinationVC];
} else if ([self.title isEqualToString:<<another title string>>]) {
destinationVC = [storyboard instantiateViewControllerWithIdentifier:@"id_NextDetailContentVC"];
segue = [[Segue_YourCustomNameHere alloc] initWithIdentifier:@"segue_YourNextSegueIdentifierNameHere"
source:self
destination:destinationVC];
} else if... // as many iterations as necessary
// Repeat above
} else {
// Do other stuff - maybe error checking?
}

// And because I always incorporate a UISearchDisplayController and I'm too lazy to think about how I should remove it for this example...
id object = nil;
if (tableView == self.tableView) {
object = [self.fetchedResultsController objectAtIndexPath:indexPath];
} else {
object = [self.searchResults objectAtIndex:indexPath.row];
}

// Finally...
[self prepareForSegue:segue sender:object]; // optional
[segue perform];
}


而且,以防万一,您需要这样做并在上方添加 // optional行...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
id segueDestinationVC = segue.destinationViewController;

if ([segue.identifier isEqualToString:@"segue_YourSegueIdentifierNameHere"]) {
// These two lines of code are examples only...
[segueDestinationVC setTitle:[sender valueForKey:@"aSenderKey"]]; // example
[segueDestinationVC setObjectID:[sender objectID]]; // example

} else if ([segue.identifier isEqualToString:@"segue_YourNextSegueIdentifierNameHere"]) {
// These two lines of code are examples only...
[segueDestinationVC setTitle:[sender valueForKey:@"aSenderKey"]]; // example
[segueDestinationVC setObjectID:[sender objectID]]; // example

} else {
// Do other stuff - again maybe error checking?

}


希望这可以帮助。

关于ios - 重构iOS项目以不使用 Storyboard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23749298/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com