使用AppDelegate共享数据

时间:2012-08-20 22:24:02

标签: iphone objective-c ios model-view-controller delegates

我找到了几个解释如何使用AppDelegate在iOS应用程序中的对象之间共享数据的资源。我已经非常轻松地实现了它,在我的情况下它看起来是一个很好的方法。考虑使用AppDelegate可以完成什么,我想知道应该在哪里画线。

显然,share data across view controllers还有其他方法,使用Singleton objectsNSUserDefaults何时使用AppDelegate共享数据?在我目前的情况下,我使用这种方法存储用于推送通知的appleDeviceToken。当用户登录或注销应用程序时,我会使用该令牌。


在MyAppDelegate.h中,我声明了属性:

@property (nonatomic, retain) NSString *appleDeviceToken;

在MyAppDelegate.m中,我合成了appleDeviceToken,然后设置它:

@synthesize appleDeviceToken;    

------------------------------------------------------

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
  NSString *devToken = [[[[deviceToken description]
                          stringByReplacingOccurrencesOfString:@"<"withString:@""]
                         stringByReplacingOccurrencesOfString:@">" withString:@""]
                        stringByReplacingOccurrencesOfString: @" " withString: @""];
  appleDeviceToken = devToken;
}

然后,在我的LoginViewController.m中,我检索它并将其发布到我的服务器:

  NSString *urlForDeviceTokenPost = [NSString stringWithFormat: @"/api/users/%i/appleDeviceToken", userId];

  MyAppDelegate *appDelegate = (MyAppDelegate*) [UIApplication sharedApplication].delegate;
  NSString *appleDeviceTokenStr = appDelegate.appleDeviceToken;

  AppleDeviceToken *appleDeviceToken = [[AppleDeviceToken alloc] init];
  appleDeviceToken.deviceToken = appleDeviceTokenStr;

  [[RKObjectManager sharedManager] postObject:appleDeviceToken delegate:self];

到目前为止效果很好,但这是理想的方法吗?我还应该知道什么?

4 个答案:

答案 0 :(得分:7)

当数据和对象真正全局和/或无法在图表中向下推进时。通常不需要在此高水平存储。同样,您的实现通常应该对应用程序委托知之甚少 - 什么比单身人士更糟糕? God-Singleton :)如果应用代表很复杂,那就出问题了。如果应用程序委托的界面对于您的许多实现是可见的(通过#import),或者他们直接向其发送消息,那么就会出现问题。

不需要(惯用的ObjC)单例 - 有一个app委托实例。

NSUserDefaults用于保持较小的值(顾名思义) - 共享的能力是副作用。

由于在这种情况下UIKit已将数据发送到app委托,因此可能是存储数据或对象表示的好地方。您还可以考虑将这些消息转发到适当的处理程序。重要的一点 - 在大多数情况下,您希望初始化流向对象图,并从最低点流出(例如,与引用回应用委托的许多对象相反)。因此,您可能会看到应用程序委托设置了顶级视图控制器的模型,但视图控制器可以设置它推动的视图控制器的模型。通过这种方式,您将减少依赖关系和控制流,更容易跟踪因果关系,并且您将能够更轻松地进行测试 - 无需大规模全局状态的上下文。

答案 1 :(得分:5)

以下行总是表明你做错了什么:

MyAppDelegate *appDelegate = (MyAppDelegate*) [UIApplication sharedApplication].delegate;

应用程序委托是UIApplication的委托。它被称为有原因。它不称为ApplicationDataStore甚至ApplicationCoordinator。事实上,您正在向应用程序询问其delegate,然后将其视为id<UIApplicationDelegate>之外的其他内容,这意味着您已要求它执行不执行任务的操作。它的任务是管理UIApplication需求(这并不意味着“应用程序”需要的所有内容)。

您似乎已经建立了一个存储此信息的地方:RKObjectManager。我会让应用程序委托在那里传递令牌,我会让登录视图控制器注意到是时候推送了它。我甚至不会将字符串@"/api/users/%i/appleDeviceToken"放在视图控制器中。这与显示视图无关。那是你网络堆栈的东西(你似乎已经在RKObjectManager)。 “ViewController”表示“用于帮助显示视图的控制器”而不是“视图所代表的操作的处理器”。

答案 2 :(得分:1)

这似乎是一个合适的用途。应用程序委托很容易被滥用,因为它是一个易于访问的对象,已经存在于每个应用程序中。但是,它有一个真正的目的,正如其标题所示,它为应用程序对象做出决策,就像表视图委托对其表视图对象所做的那样。

在这种情况下,您将存储从应用程序本身传递给委托的信息。我会说那是画线的地方。

存储此令牌似乎与app委托的目的一致,除非您有另一个控制器对象专注于处理远程通知。在这种情况下,您可能只是将令牌直接传递给该控制器。

答案 3 :(得分:0)

我更务实。由于我的应用程序中的appDelegate知道如何填充tabBarController,以及所有导航控制器,我有几个方法让一些任意类与其他类通信 - 通常这些是一些类的单个实例(但不是单例)。也就是说,如果你想放在那里没有令人信服的理由进入appDelegate,那么,它可能不属于那里!