Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for KeyValueStore for use with iCloud. #3

Open
KC-2001MS opened this issue Sep 27, 2023 · 2 comments
Open

Support for KeyValueStore for use with iCloud. #3

KC-2001MS opened this issue Sep 27, 2023 · 2 comments

Comments

@KC-2001MS
Copy link

First of all, please note that I am not very good at English and am using machine translation.
It is great to see that this repository and UserDefaults can be handled easily. I know this is not the purpose of this repository, but I would like to request KeyValueStore support.
For example, we hope to be able to work like this.

  • Specify a default storage location for the entire Class.
  • Option to save only certain properties locally.
@KVSModel(.cloud)
class Settings {
    @LocalSaveProperty(originalName: "otherValue_1")
    var value_1: Bool = false
    var value_2: Bool = false
    var value_3: Bool = false
    @CloudSaveProperty(originalName: "otherValue_2")
    var value_4: Bool = false
}

After deploying @KVSModel

class Settings {
    @LocalSaveProperty(originalName: "otherValue_1")
    var value_1: Bool = false
    @CloudSaveProperty
    var value_2: Bool = false
    @CloudSaveProperty
    var value_3: Bool = false
    @CloudSaveProperty(originalName: "otherValue_2")
    var value_4: Bool = false

     private let userDefaults: UserDefaults
     private let keyValuseStore: NSUbiquitousKeyValueStore
     internal init(userDefaults: UserDefaults = .standard, keyValueStore: NSUbiquitousKeyValueStore = .default) {
           self.userDefaults = userDefaults
           self.keyValuseStore = keyValuseStore
     }
}

Final output code.

class Settings {
    var value_1: Bool = false {
        get {
            userDefaults.bool(forKey: "otherValue_1")
        }
        set {
            userDefaults.set(newValue, forKey: "otherValue_1")
        }
    }
    var value_2: Bool = false {
        get {
            keyValuseStore.bool(forKey: "value_2")
        }
        set {
            keyValuseStore.set(newValue, forKey: "value_2")
        }
    }
    var value_3: Bool = false {
        get {
           keyValuseStore.bool(forKey: "value_3")
        }
        set {
           keyValuseStore.set(newValue, forKey: "value_3")
        }
    }
    var value_4: Bool = false {
        get {
            keyValuseStore.bool(forKey: "otherValue_2")
        }
        set {
            keyValuseStore.set(newValue, forKey: "otherValue_2")
        }
    }

     private let userDefaults: UserDefaults
     private let keyValuseStore: NSUbiquitousKeyValueStore
     internal init(userDefaults: UserDefaults = .standard, keyValueStore: NSUbiquitousKeyValueStore = .default) {
           self.userDefaults = userDefaults
           self.keyValuseStore = keyValuseStore
     }
}

Please note that this was written lightly and any errors are to be expected. Also, default values need to be considered.

@maniramezan
Copy link
Owner

Hi,

Thanks for the feedback, as you mentioned, the request for supporting iCloud or custom key value storage is different than the purpose of this repo. However, one feature that can be added to this repo is ability to mark properties that you want the macro skips and doesn't mark as @UserDefaultRecord when the entity is annotated by @UserDefaultDataStore

@KC-2001MS
Copy link
Author

KC-2001MS commented Oct 8, 2023

Sorry for the delay in contacting you.
I understand about KeyValueStore. If I have time, I may create it here based on this repository.
I wonder if the function to skip marks, which was mentioned as a feature that could be added, could be implemented as follows. In this example, if @LocalSaveProperty is originally attached, the process of giving @LocalSaveProperty is skipped. By applying this technique, you can prevent @LocalSaveProperty from being granted by granting a macro to the property you do not want to save in UserDefaults in advance.

@available(swift 5.9)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public struct SwiftKVSMacro: MemberAttributeMacro {
    public static func expansion(
        of node: SwiftSyntax.AttributeSyntax,
        attachedTo declaration: some SwiftSyntax.DeclGroupSyntax,
        providingAttributesFor member: some SwiftSyntax.DeclSyntaxProtocol,
        in context: some SwiftSyntaxMacros.MacroExpansionContext
    ) throws -> [SwiftSyntax.AttributeSyntax] {
        let variableDeclSyntax = member.as(VariableDeclSyntax.self)
        
        if let property = variableDeclSyntax {

           ...

            //Do not process if property wrapper LocalSaveProperty is already attached
            if property
                .attributes.first(where: { element in element.as(AttributeSyntax.self)?
                        .attributeName.as(IdentifierTypeSyntax.self)?
                        .description == "LocalSaveProperty"
                }) != nil{
                
                return []
            }

            ...

            //The following is the process of adding a macro
            let identifierTypeSyntax = IdentifierTypeSyntax(name: .identifier("LocalSaveProperty"))
            let attributeSyntax = AttributeSyntax(attributeName: identifierTypeSyntax)
            return [
                attributeSyntax
                    .with(\.leadingTrivia, [.newlines(1), .spaces(2)])
            ]
        } else {
            return []
        }
    }
}

I am not familiar with the English text and apologize if this is the wrong response.
That is all I can offer. I hope this helps. Please contact me if you have any questions that you would like to check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants