如何使用 SWRevealViewController 在两个视图之间传递数组?
Posted
技术标签:
【中文标题】如何使用 SWRevealViewController 在两个视图之间传递数组?【英文标题】:How do I Pass An Array Between Two Views Using the SWRevealViewController? 【发布时间】:2014-01-30 19:30:15 【问题描述】:快速背景:
我有一个应用程序,它在可搜索的选项卡式界面(又名“Cheers View Controller”)中显示歌曲列表。有两个标签,一个用于我的欢呼的每个类别。我有一个侧边栏,可让您选择菜单选项,其中之一称为“我的收藏夹”。它使用 SWReveal 控制器(又名“侧边栏”)。我试图让用户在比赛开始前标记最喜欢的欢呼声,然后在他们在休息室时使用侧边栏导航快速参考他们最喜欢的歌曲列表。
我的应用程序的初始视图控制器是一个显示视图控制器。
前视图 (sw_front) 是标签栏控制器,在应用首次启动时显示 Cheers 视图控制器。数据被加载到 Cheers View Controller 的 ViewDidLoad 中的 CSV 文件的数组中。
后部控制器 (sw_rear) 是 Sidebar,它定义了我的应用程序的菜单选项。我的侧边栏上的菜单选项之一称为我的收藏夹。正是这个侧边栏在概念上让我大吃一惊。请参阅下面的故事板相关区域的快照。
故事板快照: 事实证明,作为新用户,我无法发布图像。 :(
目标
我正在尝试从 My Favorites 视图控制器访问 Cheers 视图控制器 中最喜欢的欢呼数组。目前从 Cheers View Controller 到 My Favorites 之间没有转场,似乎在这里定义转场在概念上是错误的。
我不想使用单例或其他一些解决方法,我宁愿以正确的方式构建我的应用程序。一个简单的解决方案是将我的收藏夹移到选项卡栏控制器的另一个选项卡上。虽然我可以更改设计并且事情可能会更容易,但感觉我在这里错过了一个可以在以后的应用程序中使用的有价值的概念。
我意识到已经有很多关于将数据从一个控制器传递到另一个控制器的帖子。我已经阅读了我认为的全部内容,但我还没有能够成功地将这些解决方案整合到 SWRevealController 实现中。很明显,我对机制或概念(或两者)感到困惑。我读过的大多数帖子都涉及到 segues 或在两个具有 segues 或某种关系的控制器之间传递字段。
力学问题:
我目前在主选项卡式界面的表视图控制器的 ViewDidLoad 中准备了收藏夹数组。我在用 CSV 文件中的所有歌曲加载主数组后立即执行此操作。我在想我可以以某种方式将其传递给 My Favorites 表视图控制器或从 My Favorites 表视图控制器访问它。
//Copy favorite cheers into array
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.favorite contains[c] %@",@"Yes"];
NSArray *tempArray = [self.cheersArray filteredArrayUsingPredicate:predicate];
self.myFavoriteCheersArray = [NSMutableArray arrayWithArray:tempArray];
这对我来说很棘手 - 当用户单击按钮以显示 SideBar,然后单击 我的收藏夹:
Sidebar 的 prepareForSegue 将执行以下操作:
- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
// Get the selected row and identify the destination controller you are sending to
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
// Set the title of navigation bar by using the menu items
destViewController.title = [[_menuItems objectAtIndex:indexPath.row] capitalizedString];
if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] )
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc)
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: @[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
;
我试图将其添加到 prepareForSegue 的末尾,以某种方式允许我的收藏夹访问数组...但是我无法从侧边栏识别 Cheers View Controller 中的属性...
if([segue.identifier isEqualToString:@"myFavorites"])
//Get the Favorites View Controller (which has a navigation controller)
MyFavoritesViewController *myFavoritesViewController = [[MyFavoritesViewController alloc] init];
myFavoritesViewController = (MyFavoritesViewController*)destViewController.topViewController;
//THIS BELOW PART IS SHAKEY AT BEST
//Get the Cheers View Controller (which is part of a tabbed view controller)
SWRevealViewController *frontViewController = [[SWRevealViewController alloc] init];
CheersViewController *cheersViewController = (CheersViewController*)frontViewController.frontViewController;
//Pass the Favorites Array -- The below code gives me an error that the property I set on the CheersViewController is not found.
rankingViewController.favoriteCheers = CheersViewController.myFavoriteCheersArray;
我喜欢评论的概念问题:
什么是最好的(最好的,我的意思是实现现实和学术纯度之间的平衡方法)在没有定义 OO 概念/设计的情况下未定义 segue 时,使数组可用于另一个视图控制器的最佳方法是什么?
后视图控制器(侧边栏)不会在应用启动时加载 - 而是在第一次显示时加载。因此,我第一次在 Cheers View Controller 中加载数据是否正确(即我可以在应用启动时加载侧边栏,但这在概念上似乎也是错误的,因为用户可能永远不会访问侧边栏)?
最好在 Cheers 视图控制器 中首次启动应用程序时准备 my favorites 数组,还是仅在第一次查看 My Favorites 时准备好?该列表相当小,但从技术上讲,如果用户从未点击侧边栏查看他们的收藏夹,那么我将不必要地加载一个额外的数组 - 可能是一个 nit,因为数组很小但我很好奇。
在我目前拥有的地方加载数据是否合适?
在我看来,委托在概念上是没有意义的,因为 Cheers View Controller 并不真正需要知道用户正在查看他/她的收藏夹。我真正要做的就是尝试查询一组主数据。我这样想对吗?
【问题讨论】:
我正在寻找的许多答案都可以在这里找到:***.com/questions/569940/… 【参考方案1】:这些是如何解决的。他们工作 - 至于他们是否是最好的,我会在我了解更多信息时告诉你。 咧嘴一笑
问题 1:从 AppDelegate didFinishLaunchingWithOptions 中的 plist、CSV 或任何其他源文件加载一组初始数据。例如:
//Read in from JSON file
NSError *error;
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Cheers" ofType:@"json"]];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
self.cheersArray = json[@"cheers"];
此数组可以是不可变的(即 NSArray),您可以将其强制转换为视图控制器,如果需要,该控制器可以将其作为 NSMutableArray 进行操作。例如:
//Instantiate initial view controller
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
CMViewController *cmViewController = [storyboard instantiateInitialViewController];
//Pass array of data into a table view controller
cmViewController.tableData = (NSArray *)self.tableData;
这假设您的 View Controller 具有可用于将数据传递到的属性。
如果您有一个 JSON 文件并且需要将其作为 PLIST,则可以通过 Mac 上的终端提供一个很棒的实用程序
plutil -convert xml1 InputFileName.json -o OutputFileName.plist
当您像我一样学习时,您可能会意识到行数较少的 plist 优于 JSON 文件,并且在保存数据更改时更容易处理(个人意见)(如果您的应用允许)。
问题 2:从学术角度来看,在应用启动时加载侧边栏在概念上是错误的。它应该只在第一次使用时加载。
问题 3:类似于问题 2,最好在第一次请求时将收藏夹数组传递给需要它的视图控制器(即用户按下“收藏夹”选项卡。因为从技术上讲,收藏夹只是我正在加载的主数据的子集,我相信这是正确的。
问题 4:我将它从第一个视图控制器移动到 App Delegate,如上所示。这给了我更大的灵活性来传递数据(从概念上讲从父视图控制器到子视图控制器)而不是跨(从子视图控制器到子视图控制器)。这简化了我的代码。
问题 5:我认为代表不适合回答我所面临的挑战。
欢迎评论!
【讨论】:
请注意,如果您愿意,也可以在初始视图控制器中加载数据。这个视图控制器可以是应用程序的父视图控制器。我只是不确定哪个地方是“最佳实践”,或者它是否更符合情境/个人偏好。以上是关于如何使用 SWRevealViewController 在两个视图之间传递数组?的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]