【问题标题】:iPhone App : How to get default value from root.plist?iPhone App:如何从 root.plist 获取默认值?
【发布时间】:2010-11-28 16:54:23
【问题描述】:

我正在开发一个 iPhone 应用程序

我像这样从 root.plist 中读取了一个密钥:

NSString *Key1Var = [[NSUserDefaults standardUserDefaults] stringForKey:@"Key1"];

("Key1" 是一个PSMultiValueSpecifier 已经在root.plist 中设置了默认字符串值)

一旦用户进行设置,就可以正常工作。 但是,如果用户在进行任何设置之前运行应用程序,他将获得“Key1”的nil。 在这种情况下,我期待我为“Key1”设置的默认值。 我需要做什么, 让用户不用做设置,让应用程序第一次运行?

问候, 哈里什

【问题讨论】:

标签: iphone objective-c xcode


【解决方案1】:

请参阅this question 以获得完整的解决方案。

您实际上想在访问设置之前运行此代码:

- (void)registerDefaultsFromSettingsBundle {
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    if(!settingsBundle) {
        NSLog(@"Could not find Settings.bundle");
        return;
    }

    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];

    NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
    for(NSDictionary *prefSpecification in preferences) {
        NSString *key = [prefSpecification objectForKey:@"Key"];
        if(key) {
            [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
        }
    }

    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    [defaultsToRegister release];
}

这会将默认值加载到 standardUserDefaults 对象中,因此您将不再返回 nil 值,并且您不必在代码中复制默认设置。

【讨论】:

  • 不幸的是,这段代码在 Xcode 7.3 上的 Swift 2.2 中不起作用,我收到关于 stringByAppendingPathComponent 不可用的错误。
【解决方案2】:

我会在发布后尽早执行此操作,然后再尝试获取我的设置:

    userDefaultsValuesPath=[[NSBundle mainBundle] pathForResource:@"UserDefaults"
                                                           ofType:@"plist"];
    userDefaultsValuesDict=[NSDictionary dictionaryWithContentsOfFile:userDefaultsValuesPath];

    // set them in the standard user defaults
    [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict];

    if (![[NSUserDefaults standardUserDefaults] synchronize])
        NSLog(@"not successful in writing the default prefs");

【讨论】:

  • 但是如果你的路径是 settings.bundle 中的默认“root.plist”呢?
  • Joe:然后您会获得对该捆绑包的引用并将其发送到-pathForResource:。如果由于某种原因您不能这样做,您可以将 plist 复制到您的应用程序包的资源以及设置包的资源中。
【解决方案3】:

如果有人需要的话,基于Mike Weller's 原始解决方案的 Swift 3 版本:

static func registerDefaultsFromSettingsBundle() {

    guard let settingsBundle = Bundle.main.url(forResource: "Settings", withExtension: "bundle") else {
        print("Could not find Settings.bundle")
        return
    }
    guard let settings = NSDictionary(contentsOf: settingsBundle.appendingPathComponent("Root.plist")) else {
        print("Couldn't find Root.plist in settings bundle")
        return
    }

    guard let preferences = settings.object(forKey: "PreferenceSpecifiers") as? [[String: AnyObject]] else {
        print("Root.plist has an invalid format")
        return
    }

    var defaultsToRegister = [String: AnyObject]()
    for var p in preferences {
        if let k = p["Key"] as? String, let v = p["DefaultValue"] {
            print("Registering " + v.debugDescription + " for key " + k)
            defaultsToRegister[k] = v as AnyObject
        }
    }

    UserDefaults.standard.register(defaults: defaultsToRegister)
}

【讨论】:

    【解决方案4】:

    这是我在 iOS 7 中使用的代码,很大程度上基于上面Mike Weller 的代码。

    将此方法放在您的 AppDelegate.m 中:

    - (void)registerDefaultsFromSettingsBundleWithPlist:(NSString *)plist {
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    if(!settingsBundle) {
        NSLog(@"Could not find Settings.bundle");
        return;
    }
    NSString *bundle = [NSString stringWithFormat:@"%@.plist",plist];
    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:bundle]];
    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
    
    NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
    for(NSDictionary *prefSpecification in preferences) {
        NSString *key = [prefSpecification objectForKey:@"Key"];
        if(key) {
            [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
        }
    }
    
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    //[defaultsToRegister release];
    }
    

    然后从代码早期的某个位置(例如 didFinishLaunchingWithOptions)为您正在使用的每个设置文件(用于嵌套设置)调用它:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //register default settings into NSUserDefaults
        @try {
            [self registerDefaultsFromSettingsBundleWithPlist:@"Root"];
            [self registerDefaultsFromSettingsBundleWithPlist:@"Chat"];
            [self registerDefaultsFromSettingsBundleWithPlist:@"IVR"];
            [self registerDefaultsFromSettingsBundleWithPlist:@"Video"];
        }
        @catch (NSException * e) {
            NSLog(@"Exception: %@", e);
            NSLog(@"Try adding the Default Value field to each preference item in the Settings.bundle plist files.");
        }
        @finally {
    
        }
        ...
    

    【讨论】:

      【解决方案5】:

      我已将Mike Weller 的解决方案翻译成 Swift 2.0/iOS 9 并使其适用于我的应用程序:

      func registerDefaultsFromSettingsBundle() {
          guard let settingsBundle = NSBundle.mainBundle().URLForResource("Settings", withExtension:"bundle") else {
              NSLog("Could not find Settings.bundle")
              return;
          }
      
          guard let settings = NSDictionary(contentsOfURL: settingsBundle.URLByAppendingPathComponent("Root.plist")) else {
              NSLog("Could not find Root.plist in settings bundle")
              return
          }
      
          guard let preferences = settings.objectForKey("PreferenceSpecifiers") as? [[String: AnyObject]] else {
              NSLog("Root.plist has invalid format")
              return
          }
      
          var defaultsToRegister = [String: AnyObject]()
          for var p in preferences {
              if let k = p["Key"] as? String, v = p["DefaultValue"] {
                  NSLog("%@", "registering \(v) for key \(k)")
                  defaultsToRegister[k] = v
              }
          }
      
          NSUserDefaults.standardUserDefaults().registerDefaults(defaultsToRegister)
      }
      

      【讨论】:

        【解决方案6】:

        在我的应用程序委托中,我重写了+initialize 方法并注册了新的应用程序默认首选项。

        例如:

        + (void) initialize {
            if ([self class] == [MyAppDelegate class]) {        
                // initialize user defaults dictionary
                BOOL isFirstTimeRun = YES;
                BOOL isKeychainTurnedOn = NO;
                BOOL isSSLTurnedOn = YES;
                NSString *testURLString = @"http://stackoverflow.com";
                NSMutableDictionary *resourceDict = [NSMutableDictionary dictionary];
                [resourceDict setObject:[NSNumber numberWithBool:isFirstTimeRun] forKey:kIsFirstTimeRunKey];
                [resourceDict setObject:[NSNumber numberWithBool:isKeychainTurnedOn] forKey:kIsKeychainTurnedOnKey];
                [resourceDict setObject:[NSNumber numberWithBool:isSSLTurnedOn] forKey:kIsSSLTurnedOnKey];
                [resourceDict setObject:testURLString forKey:kTestURLString];
                [[NSUserDefaults standardUserDefaults] registerDefaults:resourceDict];
            }
        }
        

        【讨论】:

        • 如果您有实际的 settings.bundle 和 root.plist 资源怎么办?
        • @jowie 遗憾的是,即使您有 Settings.bundle 和 Root.plist,这也是必需的。在用户打开您的设置窗格之前,此处指定的“默认值”将被忽略。全新安装您的应用程序后,在打开设置窗格之前,所有键都将返回 nil,除非您手动调用“registerDefaults”。
        【解决方案7】:
        NSBundle* mainBundle = [NSBundle mainBundle]; 
        

         

        // Reads the value of the custom key I added to the Info.plist
        NSString *value = [mainBundle objectForInfoDictionaryKey:@"key"];
        
        //Log the value
        NSLog(@"Value = %@", value);
        

        // Get the value for the "Bundle version" from the Info.plist
        [mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
        
        // Get the bundle identifier
        [mainBundle bundleIdentifier];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-08
          • 2017-11-16
          • 2013-11-21
          • 2012-07-31
          • 2012-03-16
          • 2019-09-26
          • 2012-02-18
          相关资源
          最近更新 更多