2016-09-27 5 views
1

В Swift 2.x, у меня были миленькая установка, которая позволила мне хранить и извлекать словарные значения с помощью членов перечислений:Swift 3 Generic расширение Аргументов

public enum UserDefaultsKey : String { 
    case mainWindowFrame 
    case selectedTabIndex 
    case recentSearches 
} 

extension Dictionary where Key : String { 
    public subscript(key: UserDefaultsKey) -> Value? { 
     get { return self[key.rawValue] } 
     set { self[key.rawValue] = newValue } 
    } 
} 

Это позволило мне получить доступ к значениям, как это:

let dict = userDefaults.dictionaryForKey("SearchPrefs") 
if let recentSearches = dict?[.recentSearches] as? [String] { 
    // Populate "Recent" menu items 
} 

... вместо того, доступ к значениям, как это:

let dict = userDefaults.dictionaryForKey("SearchPrefs") 
if let recentSearches = dict?[UserDefaultsKey.recentSearches.rawValue] as? [String] { 
    // Populate "Recent" menu items 
} 

Примечание: Использование строкового литерала для доступа к словарю от NSUserDefaults предназначено, например, только для целей. Я бы на самом деле не собирался использовать перечисление для клавиш словаря, только для использования строкового литерала для доступа к самому словарю. :-)


Во всяком случае, это работало отлично подходит для моих потребностей, и это сделало чтение и сохранение кода с участием NSUserDefaults намного более приятным.

Поскольку мигрирующие мой проект Swift 3, однако, я получаю следующее сообщение об ошибке:

extension Dictionary where Key: String { 
    public subscript(key: UserDefaultsKey) -> Value? { <---- Use of undeclared type 'Value' 
               ~~~~~~ 
     get { 
      return self[key.rawValue] 
     } 
     set { 
      self[key.rawValue] = newValue 
     } 
    } 
} 

Я смотрел на сгенерированных заголовки для Dictionary, а общие Key и Value аргументы все еще присутствуют в Generic Argument Clause структуры Dictionary, поэтому я не уверен, в чем проблема.

Нужно ли переписать статью where, чтобы соответствовать новой грамматике Swift 3, о которой я не знаю? Или ... можно ли больше не обращаться к общим типам заполнителей в расширениях?

Я просто не знаю, что делать!

В моем проекте осталось всего 28 ошибок миграции. Я настолько близок к тому, что фактически использовал Swift 3, поэтому мне бы понравились любые указатели (если они не Unsafe и/или Raw).

Спасибо!

+0

Это не должно работал в Swift 2 ... ... К сожалению, общий параметр конкретного типа не может быть ограничен конкретным типом. –

+0

@TimVermeulen Хотя я согласен с вами, я прибегал к этой «хакерской» работе в нескольких местах, и она все еще работает в других расширениях (не цитируйте меня). Как можно переписывать его, чтобы он работал, оставаясь «родовым»? Я помню, как пробовал всевозможные забавные вещи, например, если 'String' соответствовал некоторому пустым протоколу StringLike и использовал это как общее ограничение, но в итоге он не работал по той или иной причине. Думаю, моя проблема сводится к «правильному» внедрению ориентированных на протокол шаблонов проектирования. –

+0

Связанный (и возможный дубликат?): [Подстрочный индекс: доступ к значениям словаря с перечислением String] (http://stackoverflow.com/questions/39499137/subscript-access-my-dictionary-values-with-a-string- перечисление) – Hamish

ответ

6

Общий параметр конкретного типа в настоящее время не может быть ограничен конкретным типом. Это означает, что что-то вроде

extension Dictionary where Key == String 

не компилируется. Это ограничение системы дженериков, и, надеюсь, не будет проблемой в Swift 4.

Существует обходной путь, хотя, но это немного Hacky:

protocol StringConvertible { 
    init(_ string: String) 
} 

extension String: StringConvertible {} 

extension Dictionary where Key: StringConvertible { 

    subscript(key: UserDefaultsKey) -> Value? { 
     get { return self[Key(key.rawValue)] } 
     set { self[Key(key.rawValue)] = newValue } 
    } 

} 
+0

Ничего себе, ха-ха, я думаю, великие умы думают одинаково. Это то, что я придумал прямо перед публикацией: {{Почти точно такой же код пропущен из-за ограничений форматирования. }} И ... пока, так хорошо. Я дам вам галочку! Спасибо, Тим! –

+0

'как! Key' не будет вызывать инициализатор, хотя, так что это не работает :) –

+0

Touché. Он работал на моей игровой площадке, но я сделаю ваше предложение безопасным. Опять же, спасибо за помощь в этом. Осталось всего 27 ошибок! –

Смежные вопросы