Получение строки из UserDefaults не работает

Я создал простое приложение на Swift, которое содержит WebViewControl. Благодаря SettingsBundle пользователь может указать URL-адрес, который затем открывается в WebView. Root.plist выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Type</key>
            <string>PSTextFieldSpecifier</string>
            <key>Title</key>
            <string>URL</string>
            <key>Key</key>
            <string>app_url</string>
            <key>DefaultValue</key>
            <string>https://myurl.com</string>
            <key>IsSecure</key>
            <false/>
            <key>KeyboardType</key>
            <string>URL</string>
            <key>AutocapitalizationType</key>
            <string>None</string>
            <key>AutocorrectionType</key>
            <string>No</string>
        </dict>
    </array>
</dict>
</plist>

Это нормально работает. Однако при попытке получить app_url в Swift у меня возникает проблема.

override func viewDidLoad() {
    super.viewDidLoad()

    registerSettingsBundle()

    print("retrieving key")
    if let appUrl = UserDefaults.standard.string(forKey: "app_url") {
        print("got it " + appUrl)
    }
}

func registerSettingsBundle(){
    let appDefaults = [String:AnyObject]()
    UserDefaults.standard.register(defaults: appDefaults)
}

Это выводит на консоль retrieving key, но не выводит второй оператор печати.

Некоторое время назад он работал, но недавнее обновление сломало его. Что я делаю неправильно? API как-то изменился? Я прочитал документацию Apple по UserDefaults, но пока мне это не помогло .

Редактировать в отношении marked as duplicate. Очень важно, чтобы пользователь мог изменять app_url с помощью приложения "Настройки" в iOS. Недостаточно просто прочитать файл plist как dict. Извините, я впервые экспериментирую с приложениями для iOS.


person dislick    schedule 10.10.2018    source источник
comment
Как URL-адрес попадает в UserDefaults из вашего .plist файла?   -  person Dávid Pásztor    schedule 10.10.2018
comment
Root.plist! = UserDefaults. Для чтения из списка: stackoverflow.com/questions/24045570/   -  person Larme    schedule 10.10.2018
comment
@ DávidPásztor Пожалуйста, посмотрите мою редакцию.   -  person dislick    schedule 10.10.2018
comment
@dislick, почему вы регистрируете значения приложения по умолчанию, поскольку вы можете получить значение из sharedDefaults пакета приложений.   -  person Harjot Singh    schedule 10.10.2018
comment
@vadian Спасибо. Я полностью удалил функцию registerSettingsBundle, но все еще не могу получить URL-адрес. Есть другие идеи?   -  person dislick    schedule 10.10.2018
comment
Я обновил свой ответ, вы можете сначала попробовать object(forKey проверить, есть ли вообще значение.   -  person vadian    schedule 10.10.2018
comment
К сожалению, @vadian if let appUrl = UserDefaults.standard.object(forKey: "app_url") { print("got it") } не печатает got it.   -  person dislick    schedule 10.10.2018
comment
Значение отображается в настройках приложения на устройстве? Если да, вы также сможете прочитать его через UserDefaults.   -  person vadian    schedule 10.10.2018
comment
@vadian Да, это отображается в приложении настроек на устройстве. Я даже могу изменить значение в списке, пересобрать приложение, и новое значение появится в приложении настроек.   -  person dislick    schedule 10.10.2018


Ответы (2)


Я повторно открыл вопрос, потому что это не дубликат. В любом случае settings plist не следует открывать в коде.

Проблема в registerSettingsBundle. После вызова этого метода словарь по умолчанию пуст, и получение каких-либо данных не удастся. Не вызывайте registerSettingsBundle, поскольку вы указали значение по умолчанию в наборе настроек.

registerSettingsBundle()

И поскольку тип URL, используйте url(forKey

person vadian    schedule 10.10.2018

Вы пытаетесь получить данные от plist, поэтому вам нужно сделать это

if let path = Bundle.main.path(forResource: "SettingsBundle", ofType: "plist") {

    //plist contain root as Array
    if let arrayData = NSArray(contentsOfFile: path) as? [[String: Any]] {

    }

    //Or plist contain root as Dictionary
    if let dictData = NSDictionary(contentsOfFile: path) as? [String: Any] {

    }
}

Если вы хотите изменить данные plist, используйте это:

var dictionaryPath = NSBundle.mainBundle().pathForResource("SettingsBundle", ofType: "plist")

var dictionary = NSMutableDictionary(contentsOfFile: dictionaryPath!)

var array = dictionary?.objectForKey("key")? as NSMutableArray

//this is a label I have called player1Name
array[0] = ""

playersDictionary?.writeToFile(dictionaryPath!, atomically: true)
person Jogendar Choudhary    schedule 10.10.2018
comment
Спасибо. Но я думаю, это не позволит пользователю изменить URL-адрес в Settings.app? - person dislick; 10.10.2018
comment
@dislick: вы можете изменить значения - person Jogendar Choudhary; 10.10.2018
comment
Пожалуйста, не предлагайте NS(Mutable)... типов коллекций в Swift. Всегда используйте PropertyListSerialization для чтения файлов plist. И в любом случае вы никогда не получите изменяемый массив с типом, приведенным к NSMutableArray. - person vadian; 10.10.2018
comment
@vadian: Спасибо, да, конечно. я буду иметь ввиду - person Jogendar Choudhary; 10.10.2018