0

我的问题是 iOS 6 选项卡式应用程序。我正在进行的工作有 5 个选项卡,其中几个选项卡是通往其他视图控制器的网关。大多数页面都需要访问模型对象,该对象包含以数组、字符串等形式存储的数据。在运行时填充一个基本模型,用户可以在整个应用程序生命周期中添加它。例如,下面列出的代码来自我的 AppDelegate 文件,它将指向准系统模型的指针传递给项目视图控制器。这很好用:选项卡应用程序使用导航控制器数组堆栈;因为我知道项目页面位于索引 2,所以我可以将模型发送给它。

我的问题与项目页面的子视图有关。例如,作为项目页面的子视图,有(或应该有)用户处理文件操作的 File_IO 页面。File_IO 页面也需要访问 Model 对象。但是当我尝试将模型指针从项目页面发送到 File_IO 页面时,我之前使用的技术(从 AppDelegate 到项目)不起作用。我指向 FileIO ViewController 中的一个空模型。

示例代码:这是在 AppDelegate 中,它工作正常:项目 ViewController 中的准系统模型填充了数据。

        //To the Project View Controller...
UINavigationController *project_NavigationController =
[[tabBarController viewControllers] objectAtIndex:2];
Project_ViewController *project_ViewController =
[[project_NavigationController viewControllers] objectAtIndex:0];
//This hides the navigation bar on the project page but it also removes the bar on any subsequent pages! They need to be programmmatically reset in ViewDidLoad.
[project_NavigationController setNavigationBarHidden:YES animated:YES];
project_ViewController.currentGeoModel = newGeoModel;

现在,我的 Project_ViewController 嵌入在 NavigationController 中,并且有 4 个子 ViweController。一个名为 FileIO_ViewController。我想将当前模型从 Project_ViewController 传递给 FileIO_ViewController。在 - (void)viewDidLoad 方法下,我尝试了很多方法,但都不起作用。例如,

UINavigationController *project_NavigationController = (UINavigationController *) self.presentedViewController;
FileIO_ViewController *fileIO_ViewController = [[project_NavigationController viewControllers] objectAtIndex:1];
fileIO_ViewController.currentModel = currentModel;

编译但是当我尝试访问 FileIO_ViewController 方法中的 currentModel 时,它是空的。

如果有人能花时间提供帮助,我将不胜感激。对我来说,最好的答案是显式代码示例的形式,展示如何将指针从 ViewController 传递到像我的模型这样的对象到另一个 ViewController,在该 ViewController 中您不明确知道子 VC 在堆栈中的位置。(在我的示例中,我使用了索引 1,但我实际上不知道 FileIO_ViewController 位于哪个索引,因为我在 Project_ViewController 下还有其他三个 ViewController。我尝试了几个整数但没有成功。)

如果您确实回答了这个问题,请在谈到 iOS 6 和 Objective C 时将我视为一个新人——攀登 Apple 山是一段漫长的旅程,而我还没有达到顶峰!

谢谢

挪威蒂姆雷德菲尔德

4

1 回答 1

-1

如果您的应用程序有一个共享的单个模型,则不应主动传递指针,您应该使模型从单个位置可用,并将其留给各个对象以在需要时访问同一模型。模型指针的一个好位置是在您的应用程序委托中。

在 appDelegate 的 .h 文件中,为您的模型声明一个属性:

  //appDelegate.h

  @property (nonatomic, strong) MyAppModel* appModel;

在 appDelegate 中实例化模型后,只需将其分配给属性:

   //appDelegate.m

  - (BOOL)application:(UIApplication *)application 
           didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.appModel  = [[MyAppModel alloc] init];
    //set up bare-bones appModel here
    return YES;

}

然后你可以从任何需要模型数据的 viewController 访问这个属性:

#import appDelegate.h;

AppDelegate* appDelegate = [UIApplication sharedApplication] delegate;
MyModel* model = appDelegate.model

(更好的是,将模型对象变成它自己的Singleton 对象,但使用 appDelegate 会让你开始)

如果您需要传递模型,那么您需要注意将它们传递给正确的对象。这是您现有的代码被破坏的地方。例如,您对 NavigationController 堆栈的结构做出了许多假设。但是,每当您通过从顶部弹出一个控制器来向下移动堆栈时,您就会完全失去该顶部控制器实例。当您通过在堆栈上前进而“返回”到该控制器时,实际上会创建一个新实例(除非您注意保持指针悬空并确保推送到该指针)。如果您在这方面需要更多帮助,您将需要准确描述您的应用程序的布局,以及您如何创建视图控制器、导航控制器堆栈等。

更新(根据您的评论)

如果您对模型的更改在整个应用程序中都有效,那么我不明白为什么您不能在需要时通过 appDelegate.model 从您碰巧在应用程序中的任何位置访问模型。如果您有模型的并发版本,您可以考虑制作一个单例数据管理器对象,该对象可以处理存储模型数组(或模型历史记录)并根据请求提供正确模型的详细信息。原理是一样的——与其主动将模型对象传递到您的视图控制器中,不如让它们根据需要从集中式源请求数据。

关于您的描述“现在,我的 Project_ViewController 嵌入在 NavigationController 中,并且有 4 个子 ViewControllers。”,我认为您还没有完全掌握类、情节提要场景和实例之间的区别。

您在故事板的一部分中有这样的安排:

UINavigationController
       |                    push                     push                     push
       |->UIViewController1 -----> UIViewController2 -----> UIViewController3 ----->
                            segue                    segue                    segue

您谈到通过访问 NavController 的堆栈将数据直接从 VC1(例如)传递到 VC3。

您需要考虑的是情节提要描述了一个模板,该模板显示实例在实例化时如何相互关联。它们不会因为故事板被加载而被实例化。当您到达 VC1 时,在模板中向您展示了切换到 VC2 和 VC3 的能力,但在您启动切换之前,VC2 和 VC3(作为实例)都不存在。segue 进程实例化了它的destinationViewController 因此将数据从VC1 直接传递到VC3 是没有意义的。当您在 VC1 时,navController 的堆栈仅包含一项(一个 VC1 实例);当您转到 VC2 时,它会包含 VC1 和 VC2 的实例,并且只有当您实际转到 VC3 时,才会创建实例并将其放入堆栈中。

单步执行您的代码:

UINavigationController *project_NavigationController = 
                            (UINavigationController *) self.presentedViewController;

presentedViewController属性适用于modalsegues,其中您有一个呈现和呈现的视图控制器。另一方面,NavControllers 与pushsegues 一起工作(因为它们将子 viewControllers 推送到它们的viewControllers堆栈中,您可以从中获取指向它们的指针)。

在这种情况下,self.presentedViewController是 nil,您将其分配给一个新变量。代码什么都不做,但编译器不会抱怨。

FileIO_ViewController *fileIO_ViewController = 
                    [[project_NavigationController viewControllers] objectAtIndex:1];

project_NavigationControlle是 nil,所以它的属性都是 nil。fileIO_ViewController为零。同样,在最后一行中,您正在向 nil 发送消息,这不是错误,而是略微多余。

于 2013-04-14T22:47:12.717 回答