如何使用SWRevealViewController在两个视图之间传递数组?

时间:2014-01-30 19:30:15

标签: ios iphone objective-c cocoa-touch xcode5

快速背景:

我有一个应用程序,在可搜索的标签界面(a.k.a。“干杯视图控制器”)中显示歌曲列表。有两个标签,每个标签对应我的欢呼。我有一个侧边栏,允许您选择菜单选项,其中一个称为“我的收藏夹”。它使用SWReveal控制器(a.k.a。“Sidebar”)。我试图允许用户在游戏时间之前标记喜欢的欢呼,然后使用侧边栏导航在他们在防空洞中时快速参考他们喜欢的歌曲列表。

我的应用程序的初始视图控制器是Reveal View Controller。

正面视图(sw_front)是标签栏控制器,可在应用首次启动时显示干杯视图控制器。数据从干杯视图控制器的ViewDidLoad中的CSV文件加载到数组中。

后控制器(sw_rear)是侧栏,它定义了我的应用程序的菜单选项。我的补充工具栏上的其中一个菜单选项称为我的收藏夹。正是这个侧边栏在概念上抛弃了我。请参阅下面的故事板相关区域的快照。

STORYBOARD SNAPSHOT: 事实证明,作为一个新用户,我无法发布图像。 :(

目标

我正在尝试从我的收藏夹视图控制器访问干杯视图控制器中最喜欢的欢呼数组。目前干杯视图控制器 我的收藏夹 没有segue ,似乎在概念上定义一个segue是错误的。

我不想使用单例或其他一些工作,我宁愿以正确的方式构建我的应用程序。一个简单的解决方案是将我的收藏夹移动到选项卡栏控制器的另一个选项卡。虽然我可以改变设计并且事情可能会更容易,但我觉得我在这里缺少一个可以在以后的应用程序中使用的有价值的概念。

我意识到关于将数据从一个控制器传递到另一个控制器的主题已经有很多帖子。我已经阅读了我认为的全部内容,但我还未能成功地将解决方案整合到SWRevealController实现中。很明显,我对机制或概念(或两者)感到困惑。我读过的大多数帖子涉及两个控制器之间的segues或传递字段,这些控制器具有某种段或关系。

机械问题:

我目前在 Main Tabbed Interface 中的表视图控制器的ViewDidLoad中准备了favorites数组。在使用CSV文件中的所有歌曲加载主阵列后,我立即执行了此操作。我想我可以以某种方式将其传递给我的收藏夹表视图控制器,或者从我的收藏夹表视图控制器访问它。

//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 ,然后点击我的收藏夹时:

补充工具栏的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;
    }


}

概念问题我喜欢评论:

  1. 什么是最好的(最好的,我的意思是实现现实和学术纯度之间的平衡方法)方法,当没有屠宰OO概念/设计定义segue时,使阵列可用于另一个视图控制器?< / p>

  2. 后视图控制器(侧栏)未在应用启动时加载 - 而是在第一次显示时加载。因此我是第一次在干杯视图控制器中加载数据是正确的(即我可以在应用启动时加载侧边栏,但这似乎在概念上也是错误的,因为用户可能永远不会访问边栏)?

  3. 当应用首次在干杯视图控制器中启动时,或仅在首次查看我的收藏夹时,最好准备我的收藏夹阵列吗?该列表相当小,但从技术上讲,如果用户从未点击侧边栏查看他们的收藏夹,那么我将不必要地加载一个额外的阵列 - 可能是因为阵列很小但我很好奇。

  4. 是否正确加载我目前所拥有的数据?

  5. 在我看来,一个代表在概念上没有意义,因为干杯视图控制器并不需要知道用户查看他/她的最爱。我所做的只是尝试查询一组主数据。我是这样想的吗?

1 个答案:

答案 0 :(得分:0)

以下是这些问题的解决方法。他们工作 - 至于他们是否是最好的,我会告诉你,因为我了解更多。 笑容

问题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

正如您所了解的那样,您可能会发现行数较少的行数优于JSON文件,并且在保存数据更改(如果您的应用程序)时需要更轻松(个人意见)来处理允许那样)。

问题2:从学术角度来看,在应用启动时加载补充工具栏在概念上是错误的。它应该只在首次使用时加载。

问题3:与问题2类似,最好将收藏夹数组传递给第一次请求时需要它的视图控制器(即用户按下选项卡&#34;收藏夹&#34;。从技术上来说,收藏夹是只是我正在加载的主数据子集的特定视图,我相信这是正确的。

问题4:我将它从第一个视图控制器移动到App Delegate,如上所示。这使我更灵活地传递数据(从概念上讲,从父视图到子视图控制器),而不是跨越(从子视图到子视图控制器)。这简化了我的代码。

问题5:我不相信代表是适合我所面临挑战的答案。

随意发表评论!