Closed kimaldis closed 7 years ago
I don’t understand how would the automatic case work. You have some kind of a collection of shortcuts that you display using a table, right? Now if the user changes a shortcut using MASShortcutView
, the contents of the collection change and you have to refresh the table. How could MASShortcut
help you when it knows nothing about the collection? MASShortcut
is an immutable class, there’s no event such as the key combination being changed. A different key combination requires a different MASShortcut
instance. Or did I get your question wrong? Could be, it’s Friday evening after all :–)
I'm relatively new to Swift and Apple dev and wholly unfamiliar with ObjectiveC so it's almost certainly me that has it wrong, any day of the week. You're more or less right on the table method but I'd assumed wrongly on how the shortcut class worked. I'll need to go back and get my head around it properly. Thanks for your input, though. It was useful.
OK, I'm nearly there, I think. One more question:
I'm using MASShortcutBinder to store my shortcuts in userdefaults. Initially creating a set of shortcuts when the app starts:
let msShortcut = MASShortcut(keyCode: , modifierFlags: )
MASShortcutBinder.shared().registerDefaultShortcuts([ userKey: msShortcut ])
MASShortcutBinder.shared().bindShortcut(withDefaultsKey: userKey ) { // code }
And for each key storing the key combination in a collection, along with other data, which is used to populate the table. All well and good. Over in my Viewcontroller I have my table with a separate tab view for editing shortcuts. My user selects a row then switches to the edit tab if he wants to change the shortcut. I have a single MSShortcutView in this tab to change key combinations for the shortcut selected in the table and I use MSShortcutView.shortcutValueChange to catch changes and, update my collection with the new key combination and reload my table. I use MASShortcutView.associatedUserDefaultsKey to associate the shortcut key, which is stored in my collection, to the shortcut view when the user selects a row.
This works fine; my table shows any changed key combinations and my app reloads with the changed key combinations on the shortcuts but there's still a problem with any shortcuts the user has changed when the app is subsequently launched because I'm populating my collection with the default key combinations rather than the ones picked up from the user defaults store.
I could iterate through my collection, calling associatedUserDefaultsKey for each shortcut, since this triggers shortcutValueChange, but this seems a bit messy and I wondered if there was a better way.
thanks.
Since you already use NSUserDefaults
for storage, can’t you also use it as the model, triggering all changes? In my app, all MASShortcutView
s are bound to user defaults, and so are all parts of the app that depend on the shortcuts. When user changes a shortcut though the view, the bindings update the value stored in user defaults, which in turn – again, through bindings – updates the shortcuts throughout the app.
You mean retrieve the shortcut description from user defaults, rather than storing myself in the collection?
If you store the description independently on the shortcut itself, you’re definitely asking for trouble, as it’s easily possible for the two to get out of sync. I would never separate the description from the shortcut – if something displays a shortcut, it should get a real MASShortcut
value and only convert it to the textual value at the last moment.
I do get that and I'm not. kind of.. I'm aware that my unfamiliarity with this might be causing some confusion so I'll have one more go before I stop annoying you. :-)
My app creates, registers and binds a set of shortcuts immediately it starts using MASShortcutBinder. My user is then presented with a table of shortcuts. I don't have a MASShortcutView associated with each shortcut, there will only ever be one and that's presented to my user when he double clicks on a table row. I'm assuming that normally there would be a MASShortcutview for each shortcut, my user would see the correct key combination in that and all would be fine. I only have one so that isn't working for me. I'm currently storing in a collection the shortcuts created back when the app first starts. This is obviously incorrect so what I'm asking is, is there a way to get the correct information to populate my collection?
Does that make sense?
Not annoying at all! Happy to help. Sorry for being daft.
Would it work for you to store not the shortcuts themselves in the collection, but their defaults keys? When displaying the collection you can then read the associated shortcut from defaults. A bit like this:
struct Item {
let shortcutKey: String
let userInfo1: …
let userInfo2: …
}
// The syntax is off, but you get the idea
func displayItem(item: Item) -> String? {
let defaults = UserDefaults.standard
let shortcut = defaults.object(forKey: item.shortcutKey) as? MASShortcut
return shortcut?.description
}
I'm getting nil from defaults.object but let me investigate at this end. It's probably my fault because it looks like what I want. Thanks.
It definitely returns nil. Are shortcuts stored as data rather than objects?.
My solution, however. It's roundabout but it works. I am the master of kludge.
struct Item {
let shortcutKey: String
let userInfo1: …
let userInfo2: …
}
@IBOutlet weak var ShortcutViewOutlet: MASShortcutView!
func displayItem(item: Item) -> String? {
ShortcutViewOutlet.associatedUserDefaultsKey = item.shortcutKey
shortcut = ShortcutViewOutlet.shortcutValue
return shortcut?.description
}
Thanks again for your help. I have a much clearer understanding of this now.
My eyes, my eyes! :goberserk: :–) A shortcut can’t be saved to user defaults directly, it has to be serialized somehow. Take a look at MASDictionaryTransformer
, it should be able to transform the value stored in user defaults back to a valid MASShortcut
.
It doesn't appear to be as simple as:
let defaults = UserDefaults.standard
let data = defaults.data(forKey: userKey )
let shortcut = MASDictionaryTransformer().reverseTransformedValue( data )
or is it?
It’s close! There are two ways to store an MASShortcut
in user defaults: NSData
or NSDictionary
. I like the dictionary approach better, since it makes the shortcut readable when accessing through the defaults
CLI client. If you have them stored as dictionaries, you have to read them as dictionaries:
let defaults = UserDefaults.standard
let serializedShortcut = defaults.dictionary(forKey: …)
let shortcut = MASDictionaryTransformer().transformedValue(serializedShortcut)
I think that should work. If it doesn’t, take a look what serializedShortcut
actually is.
Dictionarn() seemed to be the obvious place to start but it returns nil. data() wsa the only method that returned a non nil value.
In that case your shortcuts are serialized to NSData
(using NSCoding
) and you have to deserialize them using NSKeyedUnarchiver
:
let defaults = UserDefaults.standard
let serializedShortcut = defaults.data(forKey: …)
let shortcut = NSKeyedUnarchiver.unarchiveObject(with: serializedShortcut)
That did it. I'm good to go now. Many thanks for your help and patience.
Happy to help!
I have a table, one row for each of a list of shortcuts held in my app including, amongst other things, a string which is the key combination that calls the shortcut. I'm populating the table using an array of shortcuts which is built when the shortcuts are instantiated earlier in the app. I pull this string from MASShortcut.description and that's fine until the app user changes the key combination for a shortcut, using a MASShortcutView. The description property doesn't change when the key combinations are changed.
Is there a way to retrieve string for the changed key combination or am I going to have to watch for changes and deal with it myself.
Thanks.