• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Property in class mirrored to user defaults
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Property in class mirrored to user defaults


  • Subject: Re: Property in class mirrored to user defaults
  • From: Jonathan Taylor <email@hidden>
  • Date: Fri, 16 Jun 2017 17:49:21 +0100

Thankyou Charles and Keary for your replies. I somehow hadn't thought of using
NSDefaults as backing for the properties. There are a lot of properties
involved, but with a macro or something I should be able to set it up without a
massive code bloat. Will give that a go.
Cheers
Jonny

On 12 Jun 2017, at 16:01, Charles Srstka <email@hidden> wrote:

>> On Jun 12, 2017, at 4:04 AM, Jonathan Taylor <email@hidden>
>> wrote:
>>
>> Hi all,
>>
>> This feels like a very basic question, but one that I have not had any luck
>> searching for (maybe I am using the wrong terms?).
>>
>> At the moment I have properties in a (singleton) class that are bound to UI
>> elements. At the moment they have the same automatic values every time the
>> app is launched, although the user can change them while it is running. What
>> I would like is for the user's previous choice to be remembered when the app
>> is next launched. Obviously this would seem to be a job for NSUserDefaults.
>> I am not sure quite what the right way to structure things is, though.
>>
>> All the simple examples I have seen bind to NSUserDefaults and then if the
>> program actually wants to know what the value is, it simply accesses the
>> values directly on NSUserDefaults. I would prefer not to do that, though
>> (see below).
>>
>> What I ~think~ I would like is to still be able to access the values as
>> properties of my class. That seems to me like the natural way, and it would
>> seem odd to have two categories of value, some accessed through properties
>> on the class, and some accessed some other way via NSUserDefaults. However,
>> if I bind the UI elements to the shared user defaults object, is that not
>> what will happen? Or is there some way that I can "link" my class and the
>> user defaults object, so that the properties are saved in user defaults but
>> I can still access them in a fairly seamless way from my class? I do like
>> the idea of having the properties (and their types) explicitly declared as
>> part of my class, rather than being mysterious objects that only exist in
>> the user defaults.
>>
>> Does anyone have any advice on how I can achieve this, or on how I should be
>> thinking about all this differently?
>> Thanks
>> Jonny
>
> If performance isn’t an issue, as it usually isn’t for properties linked to
> UI elements, and you don’t want to bind the UI elements directly to an
> NSUserDefaultsController, you can just use UserDefaults as the backing for a
> property, like this:
>
> class MyClass: NSObject {
>       // this is a property only so we can make key paths that will go
> through it
>       @objc private let userDefaults: UserDefaults
>       private static let fooDefaultsKey = "Foo"
>
>       @objc private static let keyPathsForValuesAffectingFoo: Set<String> =
> ["\(#keyPath(userDefaults)).\(MyClass.fooDefaultsKey)"]
>       @objc dynamic var foo: String {
>               get { return UserDefaults.standard.string(forKey:
> MyClass.fooDefaultsKey) ?? "" }
>               set { UserDefaults.standard.set(newValue, forKey:
> MyClass.fooDefaultsKey) }
>       }
>
>       override init() {
>               self.userDefaults = UserDefaults.standard
>
>               super.init()
>       }
> }
>
> This is pretty cool; on recent releases of macOS, it’ll respond to changes in
> the defaults even if they come from outside the process. So, if you observe
> the “foo” property, and then manually use /usr/bin/defaults to change the
> defaults, your notifications in the app will fire.
>
> Alternately, you can just set up the property at init time and then update
> the defaults whenever it changes, like this. You won’t get the cool
> observation behavior, though, unless you use KVO’s infamously ugly
> observation APIs (the slick new closure-based one won’t work here, since
> we’re stuck with using string keys for this).
>
> class MyClass: NSObject {
>       private static let fooDefaultsKey = "Foo"
>
>       @objc dynamic var foo: String {
>               didSet { UserDefaults.standard.set(self.foo, forKey:
> MyClass.fooDefaultsKey) }
>       }
>
>       override init() {
>               self.foo = UserDefaults.standard.string(forKey:
> MyClass.fooDefaultsKey) ?? ""
>
>               super.init()
>       }
> }
>
> Charles
>

_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

References: 
 >Property in class mirrored to user defaults (From: Jonathan Taylor <email@hidden>)
 >Re: Property in class mirrored to user defaults (From: Charles Srstka <email@hidden>)

  • Prev by Date: Re: Deep linking from 1 tvOS app to another
  • Next by Date: Re: Deep linking from 1 tvOS app to another
  • Previous by thread: Re: Property in class mirrored to user defaults
  • Next by thread: Re: Property in class mirrored to user defaults
  • Index(es):
    • Date
    • Thread