iOS:如何在Tab Bar Controller的不同视图之间共享数据

时间:2014-08-09 17:47:57

标签: ios objective-c uitableview ios7

我的应用有两个由标签栏控制器管理的视图。其中一个视图是Google Map(使用他们的SDK的GMSMapView),另一个是显示相同数据列表的TableView。地图上的标记与TableView中的数据相同(只是相同数据的替代显示)。

我从NSURLSessionDataTask获取数据。我想知道在两个视图之间共享数据的最佳方式是什么。显然,我不想为每个视图获取两次数据。但我不确定在两个视图之间使共享数据可用/同步的最佳做法是什么。

提出了类似的问题,但没有回答here

4 个答案:

答案 0 :(得分:2)

您可以创建一个模型类,它将数据/字典/自定义类对象中的地图相关数据保存在一起。您可以将此模型类设置为单例(只能初始化一次)。两个视图控制器(即地图和表视图)都可以引用此模型来立即在不同视图中填充日期。

Model Class
-----------

@property (strong, nonatomic) MyCustomDataRepresentationObj  *data;

+ (id)sharedModel {
    static MyModelClass *sharedModel = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedModel = [[self alloc] init];
    });
    return sharedModel;
}

-(void)fetchMapDataWithCompletionBlock:(void(^)(id response, NSError *error)onComplete
{
    // Check if data is available.
    // Note: You can add a refresh data method which will fetch data from remote servers again.
    if (!data) {
    __weak MyModelClass *weakSelf = self;
    // Make HTTP calls here, assume obj is returned value.
    // Convert network response to your data structure
    MyCustomDataRepresentationObj *objData = [MyCustomDataRepresentationObj alloc] initWith:obj];
    // Now hold on to that obj in a property
    weakSelf.data = objData;
    // Return back the data
    onComplete(objData, error);
    } else {
    onComplete(objData, nil); // Return pre fetched data;
    }
}

现在在视图控制器中,您必须调用模型类方法,该方法将进行网络调用(如果需要)并在完成块中返回数据。

View Controller 1
-----------------

-(void)viewDidLoad
{
    // This is where the trick is, it returns the same object everytime.
    // Hence your data is temporarily saved while your app is running.
    // Another trick is that this can be accessed from other places too !
    // Like in next view controller.
    MyModel *myModelObj = [MyModel sharedModel];
    // You can call where ever data is needed.
    [myModelObj fetchMapDataWithCompletionBlock:^(id response, NSError *error){
        if (!error) {
            // No Error ! do whats needed to populate view
        }
    }];
}

在其他视图控制器中执行相同操作。

View Controller 2
-----------------

-(void)viewDidLoad
{
    // Gets the same instance which was used by previous view controller.
    // Hence gets the same data.
    MyModel *myModelObj = [MyModel sharedModel];
    // Call where ever data is needed.
    [myModelObj fetchMapDataWithCompletionBlock:^(id response, NSError *error){
        if (!error) {
            // No Error ! do whats needed to populate view
        }
    }];
}

注意:我刚刚在这里记下了这些代码行,可能存在语法错误。它只是为了得到基本的想法。

答案 1 :(得分:1)

UITabBarController充当容器。 因此,从您的2个子ViewControllers,您可以使用属性parentViewController访问TabBarViewController。

因此,如果您想与2个子ViewControllers共享相同的数据,则可以在UITabBarController中获取和存储数据。而且,从你的UIViewControllers,你可以像这样访问它

MyCustomTabBarController *tabBar = (MyCustomTabBarController*)self.parentViewController;
id data = tabBar.myCustomData;

答案 2 :(得分:0)

使用单例模式创建单例类并在AppDelegate.m中初始化单例实例,这样您就可以使用

从AppDelegate访问单例类实例

答案 3 :(得分:0)

数据提取对象怎么样?创建一个新的类,它会对您的数据位进行请求并在内部存储结果。

然后,您可以使用多种不同的方法将数据导入ViewController:

直接引用在Tab键控制器上设置viewControllers属性之前,将此对象与ViewControllers上的每个ViewController相关联。

这个新类的接口可能包括一组获取的结果,以及一个方法(当请求完成时带回调),告诉对象获取更多结果。

通知中心您的对象可以在有更多数据时发布通知,并且只包含一种方法来开始请求更多数据。

委托+注册您可以为想要了解数据集更改的对象创建协议,确保所有必需的ViewControllers符合要求,并在数据上具有委托NSArray属性获取对象。这比Notification Center更加手动,但如果您需要一个非常强大的界面,它会稍微容易一些。

毋庸置疑,有很多方法可以解决这个问题,但它们都是从指定一个类开始执行获取/存储数据的特定任务开始的。