4

我是 iOS 和 Cocoa 的新手。我的问题不是关于如何让某件事情发挥作用,而是更多关于改进用户体验和性能的设计。

我正在向现有应用程序添加功能。目前,该应用程序有一个类“RootViewController”(RVC),负责发出服务器请求。RVC 调用服务器以获取 json 响应。这个 json 响应被解析,解析后的响应被一个名为“array”的 NSArray 对象引用。服务器提供给“array”的数据必须定期更新,因为它代表了其他客户可以购买的实时库存。

我需要在应用程序生命周期的不同时间在其他类中使用对“数组”的引用。我不想每次想使用或更新“数组”时都调用服务器。在我自己的设备上测试这个应用程序时,调用服务器似乎很慢 -> 会损害应用程序的性能。

我考虑过创建一个可以充当委托的类来保持对 NSArray 的引用 - 有点像全局变量。我会向服务器发出一个异步请求,并跟上这个委托类中的响应。我不确定如何确定这种方法是否有效或是否考虑最佳实践(考虑到 MVC)。

我正在寻找存储“数组”的最佳位置,以便其他类可以快速使用它,而不会过多地依赖网络或内存使用情况。“阵列”必须能够偶尔从服务器更新(因为“模型”可能会因库存变化而改变)。根据我的研究,iOS 的 CoreData 似乎是最好的起点,但如果应用程序不活跃,我不确定如何定期更新 CoreData。换句话说,如果 CoreData 中的数据最近没有更新,我不想向用户呈现陈旧的数据。

json 响应大小约为 20KB - 45KB。

存放轻量级对象以便定期更新的最佳/替代位置在哪里?我倾向于会话样式变量,但我不知道是否有更好的方法来做到这一点。

4

3 回答 3

2

根据 MVC 来看这个,你有两个部分:

  • 一个数组——这是模型
  • 从服务器获取库存的代码——这是控制器

这个控制器代码实际上是模型控制器,而不是视图控制器。我不会把它放在视图控制器类中。如果代码非常简单,您可以将它放在您的应用程序委托中,但我建议将它完全放在它自己的类中。

-applicationDidFinishLaunching中:

[[InventoryController sharedInstance] reloadContent];
[[InventoryController sharedInstance] scheduleUpdates];

库存控制器.h

@interface InventoryController

@property (retain) NSArray *inventory;
@property (retain) NSTimer *reloadTimer;

+ (InventoryController *) sharedInstance;
- (void) reloadContent;
- (void) scheduleUpdates;

@end

库存控制器.m

@implmentation InventoryController

- (void) reloadContent {
    ...
}

+ (InventoryController *) sharedInstance {
    static InventoryController * singleton;
    if (!singleton)
        singleton = [[self.class alloc] init];
    return singleton;
}

- (void) scheduleUpdates {
    self.reloadTimer = ...;
}

@end

其他地方:

NSArray *inventory = [[InventoryController sharedInstance] inventory];

-reloadContent中,您应该从服务器中提取内容。在-scheduleUpdates中,您应该设置一个作用于控制器的计时器,使其定期重新加载数据。如果您的视图控制器需要在数据陈旧时调整其行为,请在数组旁边存储一个 NSDate,添加一个-isStale检查日期的方法,然后首先调用它。

请记住在后台加载 URL。您不应该在处理事件或操作时停止并重新加载数据,因此本质上,您的视图控制器需要在等待数据时从操作方法返回,并在您获取数据时调整其显示。

如果视图控制器需要在数据刷新后做出响应,让视图控制器注册一个通知,您可以在库存控制器完成更新其内容时发布该通知:

    [[NSNotificationCenter defaultCenter]
    postNotificationName:InventoryControllerDidReloadContent
                  object:self];

如果您想在设备上缓存库存数据,以便在应用程序进入后台时将其从内存中删除,您可以通过将数组写入属性列表来实现,但如果陈旧数据没有用处,您可能不会想打扰。

您可以使用 Core Data 代替数组和属性列表,但它不会消除对从服务器加载数据并将其加载到上下文中的控制器的需要。您可能会有一个托管对象上下文和一个获取的结果控制器,而不是一个数组。如果您不在应用程序中编辑该内容,我怀疑 Core Data 是否会比数组和属性列表提供任何好处。

于 2012-11-16T22:42:42.460 回答
0

如果这个“数组”有有趣的结构,CoreData 是一个不错的选择。在这种情况下,我猜测 CoreData 和 plist 的速度将彼此一样快。使用看起来最简单的那个,如果太慢,试试另一个。

尽量不要在应用程序未运行时更新数据。将上次更新时间与您的缓存数据一起存储。如果它“太旧”,则显示“请稍候”占位符并更新它。如果它是“旧但不太旧”,则显示您拥有的内容并在非主线程中更新它。或者尝试该 UI 的其他变体(“太旧”== 通知 + 只读模式)。

如果您确实发现在后台更新的技巧通过应用程序审核,请仔细考虑这将消耗多少用户的电池。添加一种禁用它的方法。或者默认禁用它并添加一种启用它的方法。或者干脆不做。:-)

于 2012-11-16T22:22:50.027 回答
0

我建议将其存储在您的应用程序委托中。它可以很好地存储数组,并且可以从应用程序中的任何类访问。

于 2012-11-16T22:15:12.760 回答