7

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

显然还有其他方法可以跨视图控制器共享数据,使用Singleton 对象NSUserDefaults何时适合使用 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

4 回答 4

7

当数据和对象真正是全局的和/或不能被推到图的下方时。通常不需要这种高级别的存储。同样,您的实现通常应该对应用程序委托几乎一无所知——比单例更糟糕的是什么?The God-Singleton :) 如果应用程序委托很复杂,那就是出了问题。如果应用程序委托的界面对您的许多实现是可见的(通过#import),或者他们直接向它发送消息,那么就有问题了。

不需要(惯用的 ObjC)单例——有一个应用程序委托的实例。

NSUserDefaults 用于小值的持久性(顾名思义)——共享的能力是一个副作用。

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

于 2012-08-20T23:35:04.417 回答
5

以下行始终表明您做错了什么:

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

应用程序委托是UIApplication. 它被称为是有原因的。它不称为 ,ApplicationDataStore甚至不称为ApplicationCoordinator。您向应用程序索要它delegate然后将其视为其他东西这一事实id<UIApplicationDelegate>意味着您已要求它做一些它不负责做的事情。它的任务是管理事物UIApplication需求(这并不意味着“'应用'需要的一切)。

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

于 2012-08-21T03:18:05.723 回答
1

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

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

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

于 2012-08-20T22:32:49.790 回答
0

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

于 2012-08-21T01:30:59.367 回答