Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to observe an array of NSObjects in swift?

I am new in swift language and my problem is about how to use observable/observer pattern in swift.

I want to make my array to be observable in my SocketManager class so it can be observed by my UIViewController class. I have used the Observable class written by Andrew J Wagner which I got from this link:

http://www.drewag.me/posts/swift-kvo-substitute-observable-variables

I have the array:

var marketIndexList: Array< MarketIndex > = []

which will get its data from a server. This list will be updated every time a new data received from server. After I got the values of my Array from server I want to make it of type Observable class which is implemented by the above link:

marketIndexList = Observable(marketIndexList)

But I got this error:

'MarketIndex' is not identical to 'AnyObject'

MarketIndex is a class of type NSObject which has some properties of type String.

This is the Observable class that I have used:

import Foundation


class Observable {
    typealias DidChangeHandler = (oldValue: Array<MarketIndex>?, newValue: Array<MarketIndex>) -> ()

    var value : Array<MarketIndex> = [] {
        didSet {
            for (owner, handlers) in self.observers {
                for handler in handlers {
                    handler(oldValue: oldValue, newValue: value)
                }
            }
        }
    }

    init(_ value: Array<MarketIndex>) {
        self.value = value
    }

    func addObserverForOwner(owner: IndexViewController, triggerImmediately: Bool, handler: DidChangeHandler) {

        if let index = self.indexOfOwner(owner) {
            // since the owner exists, add the handler to the existing array
            self.observers[index].handlers.append(handler)
        } else {
            // since the owner does not already exist, add a new tuple with the
            // owner and an array with the handler
            self.observers.append(owner: owner, handlers: [handler])
        }

        if (triggerImmediately) {
            // Trigger the handler immediately since it was requested
            handler(oldValue: nil, newValue: self.value)
        }
    }

    func removeObserversForOwner(owner: AnyObject) {
        if let index = self.indexOfOwner(owner) {
            self.observers.removeAtIndex(index)
        }
    }

    // #pragma mark - Private Properties

    var observers: [(owner: IndexViewController, handlers: [DidChangeHandler])] = []

    // #pragma mark - Private Methods

    func indexOfOwner(owner: AnyObject) -> Int? {
        var index : Int = 0
        for (possibleOwner, handlers) in self.observers {
            if possibleOwner === owner {
                return index
            }
            index++
        }
        return nil
    }
}

Can anyone tell me what the problem is?

Also does anyone know a way to observe an array of objects in swift?

I would appreciate any help.

Thanks in advance.

like image 682
user2366997 Avatar asked Mar 07 '15 11:03

user2366997


People also ask

How do I map an array in Swift?

We can use the map(_:) method to transform the elements of the array. I would like to create an array that contains the number of characters of each string in the array. We invoke map(_:) on strings and pass a closure to the map(_:)

How do you use an array in Swift?

Array in swift is written as **Array < Element > **, where Element is the type of values the array is allowed to store. The type of the emptyArray variable is inferred to be [String] from the type of the initializer. The groceryList variable is declared as “an array of string values”, written as [String].

What is array object in Swift?

Swift Array Initialization An array is a data type designed specifically to hold multiple values in a single ordered collection. An array, for example, could be created to store a list of String values. Strictly speaking, a single Swift based array is only able to store values that are of the same type.


1 Answers

The error is because marketIndexList is defined as Array<MarketIndex> but you assigned Observable instance. Perhaps you wanted to do something like this:

var observableList: Observable = Observable([])
var marketIndexList: Array<MarketIndex> = [MarketIndex(), MarketIndex()]
observableList.value = marketIndexList    

// Or maybe
observableList = Observable(marketIndexList)

By the way, you can also use Objective-C KVO from Swift. Just mark the property as dynamic and make sure the class inherits NSObject to make the property observable. For example:

class ObservableClass: NSObject {
    dynamic var value = [Int]()
}

This post is good to read for KVO in Swift in addition to what you referred to. https://medium.com/proto-venture-technology/the-state-of-kvo-in-swift-aa5cb1e05cba

like image 128
Yoichi Tagaya Avatar answered Oct 26 '22 23:10

Yoichi Tagaya