2016-03-27 6 views
5

Я добавил в свой набор настройки приложение и в Xcode он появляется в корне моего представления дерева проектов.Параметры набора параметров, возвращающие нуль

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>PSGroupSpecifier</string> 
      <key>Title</key> 
      <string>Service</string> 
     </dict> 
     <dict> 
      <key>Type</key> 
      <string>PSTextFieldSpecifier</string> 
      <key>Title</key> 
      <string>Hostname</string> 
      <key>Key</key> 
      <string>service_hostname</string> 
    <!-- and so on --> 

Когда я открываю приложение Настройки прошивки появится запись в нижней части, и я могу показать и редактировать мои настройки прекрасно.

Однако я не могу получить эти значения из кода. Вот мой код:

static func loadSettings() { 

    let ud = NSUserDefaults.standardUserDefaults() 
    ud.synchronize() 

    Settings.hostName = ud.stringForKey("service_hostname") 
    // etc 
} 

Я также попытался ud.objectForKey и ud.valueForKey - оба возвращают nil, а также.

После установки Settings.hostName отладчик Xcode сообщает, что он имеет значение nil, несмотря на то, что я устанавливаю явное значение в приложении «Настройки».

Я видел эту тему (iPhone App : How to get default value from root.plist?), где кто-то разместил фрагмент кода Objective-C, который вручную загружает файл Root.plist непосредственно в NSMutableDictionary и вызывает NSUserDefaults.standardUserDefaults().registerDefaults, но который, кажется, как взломать (и я не могу заставить его работать в Swift, потому что компилятор говорит, что stringByAppendingPathComponent больше не существует)

Почему нет NSUserDefaults, чтобы получить настройки из приложения «Настройки»?

ответ

7

Видимо, причина в том, что, если мои настройки в plist имеют значения по умолчанию, определенные и пользователь явно не установлено значение, то значение, отображаемое в настройках приложения будут по умолчанию из файла plist, однако NSUserDefaults API будет все еще возврат nil.

К сожалению, это означает, что если значение по умолчанию имеет значение (например, по умолчанию адрес веб-службы URI: с «http://www.example.com») он должен существовать дважды в моем проекте: по умолчанию в plist и в моем программном коде:

Root.plist:

<dict> 
     <key>Key</key>   <string>mySettingKey</string> 
     <key>Title</key>  <string>Some address</string> 
     <key>Type</key>   <string>PSTextFieldSpecifier</string> 
     <key>DefaultValue</key> <string>http://www.example.com</string> 
     <key>IsSecure</key>  <false /> 
     <key>KeyboardType</key> <string>Alphabet</string> 
    </dict> 

Program.swift:

let ud = NSUserDefaults.standardUserDefaults() 
ud.synchronize() 

var mySettingValue = ud.stringForKey("mySettingKey") 
if mySettingValue == nil { 
    mySettingValue = "http://www.example.com" 
} 

Это удивительно.

+0

Я думаю, что сошел с ума. Искал решение в течение длительного времени! Почему это происходит? Кто-нибудь знает? –

+0

@ Дай это не работает для меня, оно дает нулевое значение .. я чего-то не хватает? – mm24

+0

@ mm24 «это дает значение nil» - вот о чем идет мое сообщение, и почему решение должно проверять значения nil и предоставлять значение по умолчанию в коде. – Dai

7

Вы должны зарегистрировать свои значения по умолчанию, чтобы они синхронизировались. source from here

// Swift 3 
var appDefaults = Dictionary<String, AnyObject>() 
appDefaults["mySettingKey"] = "http://www.example.com" // Default Value 

UserDefaults.standard.register(appDefaults) 
UserDefaults.standard.synchronize() 

let mySettingValue = UserDefaults.standard.string(forKey: "mySettingKey") 

Имейте в виду, что вы должны также использовать registerDefaults: если ваше приложение использует настройки Bundle. Поскольку вы уже указали значения по умолчанию внутри plust набора параметров, вы можете ожидать, что ваше приложение автоматически их подберет. Однако это не так. Информация, содержащаяся в комплекте с настройками, считывается только iOS Settings.app и никогда не поддерживается вашим приложением. Чтобы ваше приложение использовало те же настройки по умолчанию, что и в файле Settings.app, вы должны вручную скопировать ключи по умолчанию пользователя и их значения по умолчанию в отдельный файл plist и зарегистрировать его с базой данных по умолчанию, как показано выше.

+0

Интересно, что когда я зарегистрировал и синхронизировал свои значения, сразу же обернулся и спросил их значения, которые у меня ничего не получилось ... вместо этого нужно было использовать старинный «setObject: forKey:». – BonanzaDriver

+0

Вызов 'synchronize' здесь бессмысленен. 1. Вызов 'register' на самом деле ничего не меняет, поэтому синхронизировать нечего. 2. Вызов 'synchronize' никогда не нужен. – rmaddy

7

Значения по умолчанию могут быть взяты из Settings.bundle и добавлены в UserDefaults.Следующая функция может быть вызвана в AppDelegate.swift от didFinishLaunchingWithOptions.

func setDefaultsFromSettingsBundle() { 
    //Read PreferenceSpecifiers from Root.plist in Settings.Bundle 
    if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"), 
     let settingsPlist = NSDictionary(contentsOf: settingsURL), 
     let preferences = settingsPlist["PreferenceSpecifiers"] as? [NSDictionary] { 

     for prefSpecification in preferences { 

      if let key = prefSpecification["Key"] as? String, let value = prefSpecification["DefaultValue"] { 

       //If key doesn't exists in userDefaults then register it, else keep original value 
       if UserDefaults.standard.value(forKey: key) == nil { 

        UserDefaults.standard.set(value, forKey: key) 
        NSLog("registerDefaultsFromSettingsBundle: Set following to UserDefaults - (key: \(key), value: \(value), type: \(type(of: value)))") 
       } 
      } 
     } 
    } else { 
     NSLog("registerDefaultsFromSettingsBundle: Could not find Settings.bundle") 
    } 
} 
+0

Спасибо, Томик, этот код мне нужен сейчас :) –

+0

Здесь гораздо лучше использовать. Как только вы получите 'preferences', используйте его с' UserDefaults register'. Это намного лучше, чем цикл и явное определение каждого значения. – rmaddy

+0

@rmaddy Здесь я проверяю, содержит ли UserDefaults определенный ключ, и я не устанавливаю в этом случае. Не уверен, как UserDefaults.register (:) будет работать в этом случае –

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