在iOS应用程序中存储数据的最佳实践?

时间:2017-02-22 13:57:37

标签: ios

我已经查看了很多关于堆栈溢出的答案但是没有找到任何可以回答这个问题的答案。

我有一个应用程序,你可以在downloadVC中下载数据(还有很多其他的VC)。我希望能够在下载VC时访问downloadUser和下载的数据,而无需重新下载数据。

我到目前为止看到的选项是:

  • 制作一个包含我可以在应用程序的所有位置访问的数据的单身人士(感觉就像最简单的方法,但人们警告我单身人士并不好)。
  • 制作类var下载VC。 (这是我最不了解的解决方案,类var的范围是什么?它与制作单例一样吗?)
  • 传递它(这对我来说不适用,因为应用程序太大而无法在每个VC之间传递)
  • 将其保存为用户默认值,(访问用户默认值的速度有多快?)

请告诉我这些问题是否符合堆栈溢出规则?

4 个答案:

答案 0 :(得分:2)

单身人士通常使用静态变量来实现,所以你的第一个和第二个选项非常相似。

最近有一个“单身是邪恶的”教派在发展界非常直言不讳。

就个人而言,我认为他们有自己的位置,有时可以清理你的设计。我最近参与了一个项目,该项目由“Singletons is evil”邪教组织的成员设计,然后他们荒谬地将数据管理器对象传递给项目中的每个其他对象,导致大量开销和更多当物体掉落时,有一些虫子。

没有一个答案。您需要权衡应用程序的不同方法的优缺点。

我会警告不要过度使用UserDefaults。这是为了保存小块数据,如用户首选项设置,而不是大数据对象。

答案 1 :(得分:1)

简单的答案是,是的,你使用单身

这是完全正确的。

请注意,您是否使用

  • SQLite.swift,

  • 核心数据,

  • realm.io,

  • 写入文本文件

  • 像Firebase或Back4app(又名Parse)这样的baas,

  • 或字面上只是“将其保存在数组中”(“在内存中”),

是的,你的问题的答案是你将拥有单身,这是你“保持 - 访问”那些东西的地方。完全正确。

这似乎就是你在这里问的。

鉴于......

...如果你再问“最简单/最好/最现代的方式(在我的数据单身”中)在我的应用程序中本地存储数据“,2017年的实际答案是

realm.io

以前您使用过Apple的核心数据。这是(a)壮观(b)极其困难。但重要的是:realm.io和SQLite在 Android和iOS上同样可用;在很多情况下,在今天的实际项目中,这会消除核心数据的考虑。

然而。所有这一切都没有实际意义。别忘了......

我们现在住在“巴斯世界”

你不能这样。 “再获得iOS或Android编程工作”。你找到一份工作是因为你在Firebase,Parse,PubNub,Cloudbase或其他任何领域的优秀/专业领域。无论好坏,能够在Xcode,Studio中移动按钮和桌子都不再是真的了。 (有很多超级专业,如GPU编程,动态网格等,这是例外。)同样,说你是一个爱好者,制作自己的应用程序或启动:在这种情况下,它是完全和完全关于你使用的后端。 (这同样适用于游戏或商业/社交应用程序。)根本没有“本地,静态”应用程序。 (同样,同样适用于游戏或商业/社交应用。)

(请注意,realm.io,这是一种简单,明显的方式来保存应用程序上的数据 - 事实上,这些人已经/正在成为一个OCC云baas-paas-无论什么服务我们可能都会在一年内使用realm.io而不是Firebase。)

所以从某种意义上说,你的问题的答案就像Firebase或back4app。但是:然后在你的应用程序中,你将它集中到一个单身人士,确实(问题的第一部分)。

但请注意....................

在初学者级别,这种情况极不可能:只需将数据保存在数组中即可!这里的所有都是它的。好的,十亿年一旦用户碰巧重新启动设备或您的应用程序,该应用程序将重新加载数据。那是什么?

请注意,“获取此处数据”Singleton的通用名称是

本地

所以,

import Foundation
often .. import SQLite, Realm, Firebase or whatever

public let local = Local.shared

open class Local {
    static let shared = Local()

    fileprivate init() {
        print("'Local' singleton running AOK")
    }

    // could be this simple..
    var clients:[String:[Blah]] = [:]
    var stock:[String:String] = [:]
    func loadStockInfoFromWWW() { ... }
    func calculateQuantityInfoOrWhatever() { ... }

    // or it could be more like this..
    func reloadClientsFromParse() { ... }
    func sendNewDataToFirebaseParse() { ... }

    .... etc

然后您只需从应用中的任何地方访问

local.updateFromWeb()
height = local.stock["ladders"][idNumber].size.h

等等。

这就是它的全部内容。

(关于单身code style的一个词。)

答案 2 :(得分:1)

基本上,在视图控制器中添加任何网络逻辑是您可以犯的第一个大错误。因此,将其移至另一个只负责发送网络请求和处理响应的类。

然后,当你下载了数据时,你可能需要一些东西来管理缓存 - 无论是一组大文件还是几个小字符串,逻辑都是一样的 - 拥有全部此缓存由一个对象控制。这个缓存管理器可以将对象保存到本地文件,使用CoreData或只是将这些对象保存在内存中 - 这取决于您创建的应用程序类型。

现在,缓存管理器基本上可以作为视图控制器的端点,因为它会在请求成功后下载数据并将其返回给视图控制器,或立即返回。视图控制器根本不需要知道任何网络。

但是,视图控制器将如何找到缓存管理器

您可以传递对它的引用,但是您已经说过在您的应用中这是不可能的。所以基本上另一种解决方案是使用讨厌的单身模式。我个人认为这是一个糟糕的模式,但如果没有它你就无法创建任何应用程序,因为你总是必须至少有一个单例,即 AppDelegate

无论如何,一个好主意可能是创建一个单例类(或者甚至可能为此目的使用AppDelegate),它将负责处理负责网络的类之间的依赖关系, 缓存管理器,以及您可能需要在应用后面执行某些逻辑的任何其他类。这实际上是一种称为依赖注入容器的模式。它可以让你轻松地通过这个容器访问你的模型类,既没有大量的单例最终会让你感到困惑,也没有创建一些荒谬的逻辑来传递模型对象。

答案 3 :(得分:0)

这取决于文件的复杂性和尺寸。如果您不需要解析内容,或者它们很容易解析,但它的大小很大,那么我建议使用Documents文件夹并从那里检索它,如果它很小或涉及复杂的处理那么作为经理的singleton将是我的方法,因为它感觉合适。