Reputation: 16715
I have a Core Data project where I'm retrieving data from multiple sources. Not all the data will be saved, so I created a struct to pass the data around before it's saved.
struct SearchResult {
var myURL: String?
var myHeadline: String?
init() {}
init(myURL: String, myHeadline: String) {
self.myURL = myURL
self.myHeadline = myHeadline
}
}
Since I want to display sections in a UITableView
, I created a struct
for that, as well:
struct ResultsObjects {
var sectionName: String?
var sectionObjects = [SearchResult]()
init() {}
init(sectionName: String) {
self.sectionName = sectionName
}
}
Lastly, I created a singleton
to keep hold SearchResult
objects prior to saving them in the managedObjectContext
.
class SearchResultsArray {
static let sharedInstance = SearchResultsArray()
var resultsObjectsArray = Array<ResultsObjects>()
fileprivate init() {}
}
My objective is to have the SearchResultsArray
class accessible via multiple classes and be able to dump ResultsObjects
into it in one class and see ResultsObjects
in another.
On MyViewController
, I'm instantiating the SearchResultsArray
as follows:
var resultsObjectsArray = SearchResultsArray.sharedInstance.resultsObjectsArray
I have a UITableViewController
that I use resultsObjectsArray
to populate.
On MyViewController
, a button calls a method that uses a method in MyParserClass
to parse web pages. This works, too.
MyParserClass
declares a resultsObjectsArray
in the same manner as MyViewController
:
var resultsObjectsArray = SearchResultsArray.sharedInstance.resultsObjectsArray
In MyParserClass
, a method is called that creates SearchResult
objects, dumps them into ResultsObjects
and appends them to SearchResultsArray.resultsObjectsArray
. This works fine. I threw in the following line in the method that creates ResultsObjects
that are dumped into resultsObjectsArray
:
print("\(resultsObjectsArray.count) ResultsObjects in SearchResultsArray")
delegate.updateSearchResults()
I threw a print statement in MyViewController
's updateSearchResults
delegate method and it returns 0, regardless of what MyParserClass
says was in there just prior to calling the delegate method.
The app doesn't crash, but it seems like I've got a problem with the singleton. Any suggestions re: what I'm doing wrong are greatly appreciated.
Upvotes: 1
Views: 329
Reputation: 114846
Arrays are value types in swift; when you assign an array to a variable and then assign that variable to another, the second variable refers to a copy of the original array, not the original array (technically, for efficiency, the array is copied on modify, not on assignment but the result is the same), so changes made to the original array will not be reflected in the second variable's array.
Consider
var someArray = [Int]()
var someOtherVariable = someArray
someArray.append(2)
someArray
will contain a single value while someOtherVariable
will still be empty.
One solution always use the SearchResultsArray.sharedinstance.resultsObjectsArray
rather than local variable/properties.
Perhaps a better approach would be to encapsulate the array in your singleton class by providing some functions to manipulate it. For example;
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() {}
}
Since results
is now a read-only property and a separate add
function exists, the class more clearly defines its semantics.
Upvotes: 1
Reputation: 5554
I use a singleton in a very similar way - but I define it quite differently.
EDIT - differently, and now superseded :-(
Within the singleton DataModelInstance
in my case, I have this
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...
}
and then, in every class that needs to access it, I define a variable
var dataModel = DataModelInstance.sharedInstance
Upvotes: 0