【问题标题】:Singleton not working as desired单身人士无法按预期工作
【发布时间】:2017-02-01 09:27:24
【问题描述】:

我有一个核心数据项目,我正在从多个来源检索数据。并不是所有的数据都会被保存,所以我创建了一个结构来在保存之前传递数据。

struct SearchResult {
    var myURL: String?
    var myHeadline: String?

    init() {}

    init(myURL: String, myHeadline: String) {
        self.myURL = myURL
        self.myHeadline = myHeadline
    }
}

因为我想在UITableView 中显示部分,所以我也为此创建了一个struct

struct ResultsObjects {
    var sectionName: String?
    var sectionObjects = [SearchResult]()

    init() {}

    init(sectionName: String) {
        self.sectionName = sectionName
    }
}

最后,我创建了一个singleton 来保留SearchResult 对象,然后再将它们保存到managedObjectContext

class SearchResultsArray {
    static let sharedInstance = SearchResultsArray()
    var resultsObjectsArray = Array<ResultsObjects>()
    fileprivate init() {}
}

我的目标是让SearchResultsArray 类可以通过多个类访问,并能够将ResultsObjects 转储到一个类中,并在另一个类中查看ResultsObjects

MyViewController 上,我将SearchResultsArray 实例化如下:

var resultsObjectsArray = SearchResultsArray.sharedInstance.resultsObjectsArray

我有一个UITableViewController,我使用resultsObjectsArray 来填充。

MyViewController 上,按钮调用一个方法,该方法使用MyParserClass 中的方法来解析网页。这也有效。

MyParserClass 以与MyViewController 相同的方式声明resultsObjectsArray

var resultsObjectsArray = SearchResultsArray.sharedInstance.resultsObjectsArray

MyParserClass 中,调用了一个方法来创建SearchResult 对象,将它们转储到ResultsObjects 并将它们附加到SearchResultsArray.resultsObjectsArray。这工作正常。我在创建ResultsObjects 的方法中添加了以下行,这些resultsObjectsArray 被转储到resultsObjectsArray

print("\(resultsObjectsArray.count) ResultsObjects in SearchResultsArray")
delegate.updateSearchResults()

我在MyViewControllerupdateSearchResults 委托方法中抛出了一个打印语句,它返回0,不管MyParserClass 在调用委托方法之前所说的内容。

应用程序没有崩溃,但我似乎遇到了单例问题。非常感谢任何建议:我做错了什么。

【问题讨论】:

  • 你看过这个帖子stackoverflow.com/questions/26742138/singleton-in-swift 吗?它表明我们都应该声明类final 以确保我们不会得到倍数——可能值得一试
  • 数组是swift中的值类型。您不能使用实例变量来引用数组。您必须始终使用SearchResultsArray.sharedinstance.resultsObjectsArray
  • @Paulw11 哇!我知道我错过了一些简单的东西,但是哇!非常感谢你的回复。非常感谢。
  • 既然这样,改变结构内部的值也是一个问题——我读到了一个名为lenses的模式。这很有趣。只是谷歌lenses swift或这个起点github.com/narfdotpl/lenso

标签: ios swift singleton


【解决方案1】:

数组是swift中的值类型;当您将一个数组分配给一个变量,然后将该变量分配给另一个变量时,第二个变量指的是原始数组的副本,而不是原始数组(从技术上讲,为了提高效率,数组是在修改时复制的,而不是在赋值时复制,而是结果相同),因此对原始数组所做的更改不会反映在第二个变量的数组中。

考虑

var someArray = [Int]()
var someOtherVariable = someArray
someArray.append(2)

someArray 将包含一个值,而someOtherVariable 仍将为空。

一种解决方案始终使用SearchResultsArray.sharedinstance.resultsObjectsArray 而不是局部变量/属性。

也许更好的方法是通过提供一些函数来将数组封装在单例类中。例如;

class SearchResultsArray {
    static let sharedInstance = SearchResultsArray()
    var resultsObjectsArray = Array<ResultsObjects>()

    public var results: [ResultsObjects] {
       get {
           return resultsObjectsArray
       }
    }


    public func add(results: ResultsObjects) {
        resultsObjectsArray.append(results)
    }


    fileprivate init() {}
}

由于results 现在是只读属性并且存在单独的add 函数,因此该类更清楚地定义了其语义。

【讨论】:

  • 当然可以。这只是一个示例,而不是完整的解决方案。
【解决方案2】:

我以非常相似的方式使用单例 - 但我对它的定义完全不同。

编辑 - 不同,现在被取代:-(

在我的情况下,在单例 DataModelInstance 中,我有这个

class DataModelInstance : NSObject, NSCoding
{
    // define all of the variables I need within the singleton

    class var sharedInstance : DataModelInstance
    {
        struct Singleton
        {
            static let instance = DataModelInstance()
        }
        return Singleton.instance
    }

    // everything else that I need in the class...
}

然后,在每个需要访问它的类中,我定义了一个变量

    var dataModel = DataModelInstance.sharedInstance

【讨论】:

  • 它在DataModelInstance里面?你能在周围添加一点 DataModelInstance 来更清楚地说明它是如何“在单例中”吗
  • 好的 - 我已经更新了答案。我没有包含任何 NSCoding 方法,或者我已经实现的任何数据级方法,但这应该足以让一个单例在我的所有 ViewControllers 上工作
  • @Russell:您定义单例的方式已被取代。现在您只需像 OP 在问题中所做的那样定义一个单例。
  • 为什么不这样呢? class DataModelInstance : NSObject, NSCoding { static let sharedInstance = DataModelInstance() }
  • 是的 - 看来我是今天学到了一些东西的人。我一直在使用相同的模式 - 因为在它被取代之前!
猜你喜欢
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-23
  • 2014-12-09
  • 2016-01-13
  • 2020-09-21
  • 2011-08-17
相关资源
最近更新 更多