Value of type 'AsynchronousDataTransaction' has no member 'Element' #20

Closed
opened 2025-12-29 15:22:11 +01:00 by adam · 8 comments
Owner

Originally created by @ScottWallace on GitHub (Nov 21, 2015).

I'm getting a build error of "Value of type 'AsynchronousDataTransaction' has no member 'Element'" on the use of importUniqueObjects, in the code below on the transaction.importUniqueObjects line:

func saveSites(sites: NSArray) {

    CoreStore.beginAsynchronous { (transaction) -> Void in

        try! transaction.importUniqueObjects(
            Into(SiteEntity),
            sourceArray: sites
        )

    }

}

The parameter sites: NSArray is the output from an Alamofire download, and is a mutable array of NSDictionary objects.

SiteEntity is, of course, an NSManagedObject, and is defined:

extension SiteEntity {

    @NSManaged var id: NSNumber?
    @NSManaged var name: String?
    @NSManaged var websiteUrl: String?
    @NSManaged var subscribed: NSNumber?

}

The SiteEntity is extended with the ImportableUniqueObject protocol as such:

extension SiteEntity : ImportableUniqueObject {

    // ImportableObject

    typealias ImportSource = NSDictionary

    func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
        return true
    }


    // ImportableUniqueObject


    typealias UniqueIDType = NSNumber

    class var uniqueIDKeyPath: String {
        return "id"
    }

    var uniqueIDValue: NSNumber {
        get { return self.id! }
        set { self.id = newValue }
    }

    func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
        return true
    }

    class func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? {
        return source["id"] as? NSNumber
    }

    func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {

        self.id = source["id"] as? NSNumber
        self.name = source["name"] as? String
        self.subscribed = source["subscribed"] as? NSNumber
        self.websiteUrl = source["websiteUrl"] as? String

    }


}

I've scoured the source, but can't find any relevant line that would point to the problem. I'm using the latest OS X, XCode, Swift, CoreStore - everything's brand new, including the app I'm creating.

There's a great deal of power with importUniqueObjects, and I'm anxious to take advantage of it. Any help you could provide would be terrific. I'm happy to try a test build, provide additional information, whatever is needed.

Thanks for your help.

Originally created by @ScottWallace on GitHub (Nov 21, 2015). I'm getting a build error of "Value of type 'AsynchronousDataTransaction' has no member 'Element'" on the use of importUniqueObjects, in the code below on the transaction.importUniqueObjects line: ``` func saveSites(sites: NSArray) { CoreStore.beginAsynchronous { (transaction) -> Void in try! transaction.importUniqueObjects( Into(SiteEntity), sourceArray: sites ) } } ``` The parameter sites: NSArray is the output from an Alamofire download, and is a mutable array of NSDictionary objects. SiteEntity is, of course, an NSManagedObject, and is defined: ``` extension SiteEntity { @NSManaged var id: NSNumber? @NSManaged var name: String? @NSManaged var websiteUrl: String? @NSManaged var subscribed: NSNumber? } ``` The SiteEntity is extended with the ImportableUniqueObject protocol as such: ``` extension SiteEntity : ImportableUniqueObject { // ImportableObject typealias ImportSource = NSDictionary func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { return true } // ImportableUniqueObject typealias UniqueIDType = NSNumber class var uniqueIDKeyPath: String { return "id" } var uniqueIDValue: NSNumber { get { return self.id! } set { self.id = newValue } } func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { return true } class func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? { return source["id"] as? NSNumber } func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { self.id = source["id"] as? NSNumber self.name = source["name"] as? String self.subscribed = source["subscribed"] as? NSNumber self.websiteUrl = source["websiteUrl"] as? String } } ``` I've scoured the source, but can't find any relevant line that would point to the problem. I'm using the latest OS X, XCode, Swift, CoreStore - everything's brand new, including the app I'm creating. There's a great deal of power with importUniqueObjects, and I'm anxious to take advantage of it. Any help you could provide would be terrific. I'm happy to try a test build, provide additional information, whatever is needed. Thanks for your help.
adam closed this issue 2025-12-29 15:22:12 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Nov 21, 2015):

@ScottWallace
The error message seems to hide the real cause, but I think it's because you have declared

typealias ImportSource = NSDictionary

but you are passing sites which is an NSArray to the sourceArray argument. Since ImportSource is declared as a dictionary, all you have to do is cast sites as so:

try! transaction.importUniqueObjects(
    Into(SiteEntity), 
    sourceArray: sites as! [NSDictionary]
)
@JohnEstropia commented on GitHub (Nov 21, 2015): @ScottWallace The error message seems to hide the real cause, but I think it's because you have declared ``` typealias ImportSource = NSDictionary ``` but you are passing `sites` which is an `NSArray` to the `sourceArray` argument. Since `ImportSource` is declared as a dictionary, all you have to do is cast `sites` as so: ``` try! transaction.importUniqueObjects( Into(SiteEntity), sourceArray: sites as! [NSDictionary] ) ```
Author
Owner

@ScottWallace commented on GitHub (Nov 21, 2015):

That fixed it. Man, was that obscure. It's sure to come up for someone else, so I'm glad it's documented here.

Thanks for the quick response, and for such a great tool.

@ScottWallace commented on GitHub (Nov 21, 2015): That fixed it. Man, was that obscure. It's sure to come up for someone else, so I'm glad it's documented here. Thanks for the quick response, and for such a great tool.
Author
Owner

@ablair08 commented on GitHub (Jan 5, 2016):

Hi there, I am trying to implement CoreStore and have encountered the same issue. However the fix above does not appear to work. Is it possible a change has occurred to stop to working. I am using the most update versions of all software.

i have also tried swiftyjson as used here (https://developers.eure.jp/ios/couples-powered-by-corestore-en/). Would anyone have an example

Many thanks

@ablair08 commented on GitHub (Jan 5, 2016): Hi there, I am trying to implement CoreStore and have encountered the same issue. However the fix above does not appear to work. Is it possible a change has occurred to stop to working. I am using the most update versions of all software. i have also tried swiftyjson as used here (https://developers.eure.jp/ios/couples-powered-by-corestore-en/). Would anyone have an example Many thanks
Author
Owner

@JoeMatt commented on GitHub (Jan 5, 2016):

Personally, I would avoid declaring variables as 'NSArray' or 'NSDictionary' in Swift code unless absolutely necessary.
If you really need a completely generic container you can use '[AnyObject]' or '[String:AnyObject]' respectively for NSArray and NSDictionary.

If you want to use the NS* methods on the Swift primitive storage types you can still do so eg;

let swiftArray : [MyType] = [objects ...]

let anotherArray = (swiftArray as NSArray).filteredArrayUsingPredicatite(predicate)

They'll bridge to Objective-C as long as the 'MyType' is an NSObject subclass

// Bridge header
NSArray<MyObject*>* swiftArray;

You'll avoid these type of obscure errors when declaring initially as the built in Swift types as apposed to the NS* storage classes directly. Just my $.02

@JoeMatt commented on GitHub (Jan 5, 2016): Personally, I would avoid declaring variables as 'NSArray' or 'NSDictionary' in Swift code unless absolutely necessary. If you really need a completely generic container you can use '[AnyObject]' or '[String:AnyObject]' respectively for NSArray and NSDictionary. If you want to use the NS\* methods on the Swift primitive storage types you can still do so eg; ``` let swiftArray : [MyType] = [objects ...] let anotherArray = (swiftArray as NSArray).filteredArrayUsingPredicatite(predicate) ``` They'll bridge to Objective-C as long as the 'MyType' is an NSObject subclass ``` // Bridge header NSArray<MyObject*>* swiftArray; ``` You'll avoid these type of obscure errors when declaring initially as the built in Swift types as apposed to the NS\* storage classes directly. Just my $.02
Author
Owner

@ScottWallace commented on GitHub (Jan 5, 2016):

I'm using the latest 1.4.1 release, and it's still working correctly for me. I'll expand the example a bit to include the portion where I make the call to .saveSites, which is passed the JSON output from AlamoFire.

func RefreshSites() -> Promise<AnyObject> {

    return Promise{ fulfill, reject in

    print("DownloadManager RefreshSites start")

        Alamofire.request(.GET, urlSites).responseJSON
            { response in switch response.result {
            case .Success(let JSON):

                print("DownloadManager RefreshSites Success")

                self.databaseManager.saveSites(JSON as! NSArray)
                fulfill("")

                print("DownloadManager RefreshSites saveSites complete")


            case .Failure(let error):
                print("Request failed with error: \(error)")
                    reject(error)
                }
        }

    }

}

Don't know what else to say except it's working using this example. It's probably silly of me to cast as NSArray then later as [NSDictionary], but there's some legacy stuff here, so it is what it is.

@ScottWallace commented on GitHub (Jan 5, 2016): I'm using the latest 1.4.1 release, and it's still working correctly for me. I'll expand the example a bit to include the portion where I make the call to .saveSites, which is passed the JSON output from AlamoFire. ``` func RefreshSites() -> Promise<AnyObject> { return Promise{ fulfill, reject in print("DownloadManager RefreshSites start") Alamofire.request(.GET, urlSites).responseJSON { response in switch response.result { case .Success(let JSON): print("DownloadManager RefreshSites Success") self.databaseManager.saveSites(JSON as! NSArray) fulfill("") print("DownloadManager RefreshSites saveSites complete") case .Failure(let error): print("Request failed with error: \(error)") reject(error) } } } } ``` Don't know what else to say except it's working using this example. It's probably silly of me to cast as NSArray then later as [NSDictionary], but there's some legacy stuff here, so it is what it is.
Author
Owner

@ScottWallace commented on GitHub (Jan 5, 2016):

@JohnEstropia Just wanted to add this, if you create a "Apps Using CoreStore" section to readme.md, it's now in production use for the 4.0.0 release of 63red.

https://itunes.apple.com/us/app/63red-conservative-news-reader/id972910669?mt=8

It greatly increased the speed of merging in new data, and has added greater stability to the app. I'd previously been using MDMCoreData, and this is a million miles better. Thanks for helping my customers by creating a great tool!

@ScottWallace commented on GitHub (Jan 5, 2016): @JohnEstropia Just wanted to add this, if you create a "Apps Using CoreStore" section to readme.md, it's now in production use for the 4.0.0 release of 63red. https://itunes.apple.com/us/app/63red-conservative-news-reader/id972910669?mt=8 It greatly increased the speed of merging in new data, and has added greater stability to the app. I'd previously been using MDMCoreData, and this is a million miles better. Thanks for helping my customers by creating a great tool!
Author
Owner

@JohnEstropia commented on GitHub (Jan 6, 2016):

@ablair08 Are you declaring your ImportSource as

typealias ImportSource = JSON

?
If so, you need to call the .arrayValue property of the JSON value when passing to sourceArray:

try! transaction.importUniqueObjects(
    Into(MyEntity), 
    sourceArray: json["key"].arrayValue // sourceArray expects type [ImportSource], in this case, [JSON]
)
@JohnEstropia commented on GitHub (Jan 6, 2016): @ablair08 Are you declaring your `ImportSource` as ``` swift typealias ImportSource = JSON ``` ? If so, you need to call the `.arrayValue` property of the `JSON` value when passing to `sourceArray`: ``` swift try! transaction.importUniqueObjects( Into(MyEntity), sourceArray: json["key"].arrayValue // sourceArray expects type [ImportSource], in this case, [JSON] ) ```
Author
Owner

@JohnEstropia commented on GitHub (Jan 6, 2016):

@ScottWallace Thanks for the feedback! Glad to hear CoreStore helped you :)
I'll think about adding an "Apps Using ..." section. If I do, I'll include 63red. Thanks again!

@JohnEstropia commented on GitHub (Jan 6, 2016): @ScottWallace Thanks for the feedback! Glad to hear CoreStore helped you :) I'll think about adding an "Apps Using ..." section. If I do, I'll include 63red. Thanks again!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#20