ImportSource = CustomType.... possible? #100

Closed
opened 2025-12-29 15:24:38 +01:00 by adam · 7 comments
Owner

Originally created by @DarrenAndes on GitHub (Nov 24, 2016).

I am trying to use the "importUniqueObjects" and I would like to use a custom type as the ImportSource, however everything but [String: AnyObject] gives me the "Value of type 'AsynchronousDataTransaction' has no member 'Element'" error.

I've even tried ImportSource = AnyObject (same error message)

Is there any way to use an ImportSource = CustomType so it is easier to access properties instead of source["id"] as? String inside "didInsertFromImportSource"

Is a custom object converted to a Dictionary the only acceptable solution? I am using ObjectMapper to do a lot of transforms to the JSON, however nested objects are not supported with the toJSON() function so it would be easier and more performant to pass around the actual Mappable type.

Thanks in advance.. really want to migrate to CoreStore (seems great), but this has me stuck.

Originally created by @DarrenAndes on GitHub (Nov 24, 2016). I am trying to use the "importUniqueObjects" and I would like to use a custom type as the ImportSource, however everything but [String: AnyObject] gives me the "Value of type 'AsynchronousDataTransaction' has no member 'Element'" error. I've even tried ImportSource = AnyObject (same error message) Is there any way to use an ImportSource = CustomType so it is easier to access properties instead of source["id"] as? String inside "didInsertFromImportSource" Is a custom object converted to a Dictionary the only acceptable solution? I am using ObjectMapper to do a lot of transforms to the JSON, however nested objects are not supported with the toJSON() function so it would be easier and more performant to pass around the actual Mappable type. Thanks in advance.. really want to migrate to CoreStore (seems great), but this has me stuck.
adam closed this issue 2025-12-29 15:24:39 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Nov 24, 2016):

@DarrenAndes Have you checked https://github.com/JohnEstropia/CoreStore/issues/24 ?

There is no type constraint on ImportSource so you should be able to set it to any type you wish, but, how you call importObjects(...) or importUniqueObjects() matter. Those methods expect [ImportSource] (array of ImportSource). Can you show how you are calling the transaction.import*() methods?

@JohnEstropia commented on GitHub (Nov 24, 2016): @DarrenAndes Have you checked https://github.com/JohnEstropia/CoreStore/issues/24 ? There is no type constraint on `ImportSource` so you should be able to set it to any type you wish, but, how you call `importObjects(...)` or `importUniqueObjects()` matter. Those methods expect `[ImportSource]` (array of `ImportSource`). Can you show how you are calling the `transaction.import*()` methods?
Author
Owner

@DarrenAndes commented on GitHub (Nov 24, 2016):

@JohnEstropia thank you so much for your speedy response... Yes, I previously looked at #24 and it did provide some clarity into my problem.. I am now getting a different error now after moving all my code around (I used separate targets in my project) - 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable'. However, error message are deceiving in Swift (sometime they are not clear on the real problem).

I have tried ImportSource = BaseObjectMappable and the way the code is below using a protocol and I get the same type of error message:
'Error 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable'

Here is the simplified code which I am trying in Swift 2.3:

// MARK: - ObjectMapper Code

public protocol BaseObjectMappableProtocol: class {
     var id: String? { get set }
}

public class BaseObjectMappable: Mappable, BaseObjectMappableProtocol {
     public var id: String?
}

public class JobTierMappable: BaseObjectMappable {

}
// MARK: - Core Data Code

public class BaseManagedObject: NSManagedObject, ImportableUniqueObject {
    @NSManaged public var id: String?
        
    // MARK: - ImportableObject
    
    public typealias ImportSource = BaseObjectMappableProtocol
    
    public static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
        return shouldUpdateFromImportSource(source, inTransaction: transaction)
    }

    public func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
    }

    // MARK: ImportableUniqueObject
    
    public typealias UniqueIDType = NSString
    
    public static var uniqueIDKeyPath: String { return "id" }
    
    public var uniqueIDValue: NSString {
        get {
            guard let ID = id else { return "" }
            return ID
        }
        set { id = newValue as String }
    }
    
    public static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
        return true
    }
    
    public static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSString? {
        return source.id ?? nil
    }
    
    public func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {

    }
}

@objc(JobTier)
public final class JobTier: BaseManagedObject {

}
// MARK: - CoreStore code

function testImportUniqueObjects(for jobTiers: JobTierMappable?) {
    guard let jobTiers = jobTiers as? [BaseManagedObject.ImportSource] else { // ERROR: 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable'
         completion(error: nil)
         return
    }

    CoreStore.beginAsynchronous { (transaction) in
         if let successIds = try? transaction.importUniqueObjects(Into(JobTier), sourceArray: jobTiers) {
              transaction.commit()
         }
    }
}

// This works without any Errors
function testImportUniqueObject(for jobTiers: JobTierMappable?) {
    guard let jobTier = jobTiers?.first else {
        completion(error: nil)
        return
    }
            
    CoreStore.beginAsynchronous { (transaction) in
        if let successIds = try? transaction.importUniqueObject(Into(JobTier), source: jobTier) {
            transaction.commit()
        }
    }
}
@DarrenAndes commented on GitHub (Nov 24, 2016): @JohnEstropia thank you so much for your speedy response... Yes, I previously looked at #24 and it did provide some clarity into my problem.. I am now getting a different error now after moving all my code around (I used separate targets in my project) - 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable'. However, error message are deceiving in Swift (sometime they are not clear on the real problem). I have tried ImportSource = BaseObjectMappable and the way the code is below using a protocol and I get the same type of error message: 'Error 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable' Here is the simplified code which I am trying in Swift 2.3: ``` // MARK: - ObjectMapper Code public protocol BaseObjectMappableProtocol: class { var id: String? { get set } } public class BaseObjectMappable: Mappable, BaseObjectMappableProtocol { public var id: String? } public class JobTierMappable: BaseObjectMappable { } ``` ``` // MARK: - Core Data Code public class BaseManagedObject: NSManagedObject, ImportableUniqueObject { @NSManaged public var id: String? // MARK: - ImportableObject public typealias ImportSource = BaseObjectMappableProtocol public static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { return shouldUpdateFromImportSource(source, inTransaction: transaction) } public func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { } // MARK: ImportableUniqueObject public typealias UniqueIDType = NSString public static var uniqueIDKeyPath: String { return "id" } public var uniqueIDValue: NSString { get { guard let ID = id else { return "" } return ID } set { id = newValue as String } } public static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool { return true } public static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSString? { return source.id ?? nil } public func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { } } @objc(JobTier) public final class JobTier: BaseManagedObject { } ``` ``` // MARK: - CoreStore code function testImportUniqueObjects(for jobTiers: JobTierMappable?) { guard let jobTiers = jobTiers as? [BaseManagedObject.ImportSource] else { // ERROR: 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable' completion(error: nil) return } CoreStore.beginAsynchronous { (transaction) in if let successIds = try? transaction.importUniqueObjects(Into(JobTier), sourceArray: jobTiers) { transaction.commit() } } } // This works without any Errors function testImportUniqueObject(for jobTiers: JobTierMappable?) { guard let jobTier = jobTiers?.first else { completion(error: nil) return } CoreStore.beginAsynchronous { (transaction) in if let successIds = try? transaction.importUniqueObject(Into(JobTier), source: jobTier) { transaction.commit() } } } ```
Author
Owner

@JohnEstropia commented on GitHub (Nov 24, 2016):

@DarrenAndes What is JobTierMappable? It looks like Swift is having a hard time casting it to [BaseObjectMappableProtocol].

Can you show the declaration for the JobTierMappable type?

@JohnEstropia commented on GitHub (Nov 24, 2016): @DarrenAndes What is `JobTierMappable`? It looks like Swift is having a hard time casting it to `[BaseObjectMappableProtocol]`. Can you show the declaration for the `JobTierMappable` type?
Author
Owner

@DarrenAndes commented on GitHub (Nov 24, 2016):

@JohnEstropia It is a subclass which eventually subclasses ObjectMapper's (Mappable) class

Sorry made a mistake in my own code, I'm back to the original error (AsynchronousDataTransaction' has no member 'Element).

public class JobTierMappable: BaseObjectMappable {

}

public protocol BaseObjectMappableProtocol: class {
     var id: String? { get set }
}

public class BaseObjectMappable: Mappable, BaseObjectMappableProtocol {
     public var id: String?
}

// MARK - ObjectMapper Objects

public protocol Mappable: BaseMappable {
}

public protocol BaseMappable {
}

Here is the correct func I was already passing an Array

function testImportUniqueObjects(for jobTiers: [JobTierMappable]?) {
guard let jobTiersUnwrapped = jobTiers as? BaseManagedObject.ImportSource else {
     completion(error: nil)
     return
}
            
CoreStore.beginAsynchronous { (transaction) in
    // ERROR: 'AsynchronousDataTransaction' has no member 'Element'
     if let successIds = try? transaction.importUniqueObjects(Into(JobTier), sourceArray: jobTiersUnwrapped) {
          transaction.commit()
     }
}
@DarrenAndes commented on GitHub (Nov 24, 2016): @JohnEstropia It is a subclass which eventually subclasses ObjectMapper's (Mappable) class Sorry made a mistake in my own code, I'm back to the original error (AsynchronousDataTransaction' has no member 'Element). ``` public class JobTierMappable: BaseObjectMappable { } public protocol BaseObjectMappableProtocol: class { var id: String? { get set } } public class BaseObjectMappable: Mappable, BaseObjectMappableProtocol { public var id: String? } // MARK - ObjectMapper Objects public protocol Mappable: BaseMappable { } public protocol BaseMappable { } ``` Here is the correct func I was already passing an Array ``` function testImportUniqueObjects(for jobTiers: [JobTierMappable]?) { guard let jobTiersUnwrapped = jobTiers as? BaseManagedObject.ImportSource else { completion(error: nil) return } CoreStore.beginAsynchronous { (transaction) in // ERROR: 'AsynchronousDataTransaction' has no member 'Element' if let successIds = try? transaction.importUniqueObjects(Into(JobTier), sourceArray: jobTiersUnwrapped) { transaction.commit() } } ```
Author
Owner

@JohnEstropia commented on GitHub (Nov 24, 2016):

Try changing

guard let jobTiersUnwrapped = jobTiers as? BaseManagedObject.ImportSource else {

to

guard let jobTiersUnwrapped = jobTiers as? [BaseManagedObject.ImportSource] else {
@JohnEstropia commented on GitHub (Nov 24, 2016): Try changing ```swift guard let jobTiersUnwrapped = jobTiers as? BaseManagedObject.ImportSource else { ``` to ```swift guard let jobTiersUnwrapped = jobTiers as? [BaseManagedObject.ImportSource] else { ```
Author
Owner

@DarrenAndes commented on GitHub (Nov 25, 2016):

That code gives the error:
'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable'

I tried a long shot and made the conversion to [BaseObjectMappableProtocol] before passing into the func and that worked (it compiled)... Then there was a Swift casting issue. (fatal error: array cannot be bridged from Objective-C)... clearly the real cause of my problems.

I then did this extra step to help Swift along with the casting:

let jobTiersCasted: [BaseObjectMappableProtocol]? = jobTiers?.flatMap({ $0 as BaseObjectMappableProtocol })

And it finally all worked... @JohnEstropia have wonderful Thanksgiving... I know I'm thankful for all your help and CoreStore itself (thanks for an excellent project)... It's replacing MagicalRecord :)

@DarrenAndes commented on GitHub (Nov 25, 2016): That code gives the error: 'ImportSource (aka BaseObjectMappableProtocol') is not a subtype of 'JobTierMappable' I tried a long shot and made the conversion to [BaseObjectMappableProtocol] before passing into the func and that worked (it compiled)... Then there was a Swift casting issue. (fatal error: array cannot be bridged from Objective-C)... clearly the real cause of my problems. I then did this extra step to help Swift along with the casting: ``` let jobTiersCasted: [BaseObjectMappableProtocol]? = jobTiers?.flatMap({ $0 as BaseObjectMappableProtocol }) ``` And it finally all worked... @JohnEstropia have wonderful Thanksgiving... I know I'm thankful for all your help and CoreStore itself (thanks for an excellent project)... It's replacing MagicalRecord :)
Author
Owner

@JohnEstropia commented on GitHub (Nov 25, 2016):

Glad it worked out :)

@JohnEstropia commented on GitHub (Nov 25, 2016): Glad it worked out :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#100