【问题标题】:Best way to check if an iPhone app is running for the first time检查 iPhone 应用程序是否首次运行的最佳方法
【发布时间】:2010-12-12 11:01:51
【问题描述】:

我想检查我的 iPhone 应用程序是否第一次运行。我可以在文档文件夹中创建一个文件并检查该文件以查看这是否是应用程序第一次运行,但我想知道是否有更好的方法来执行此操作。

【问题讨论】:

    标签: iphone iphone-sdk-3.0


    【解决方案1】:

    我喜欢使用 NSUserDefaults 来存储第一次运行的指示。

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  
    if (![defaults objectForKey:@"firstRun"])
      [defaults setObject:[NSDate date] forKey:@"firstRun"];
    
    [[NSUserDefaults standardUserDefaults] synchronize];
    

    您可以稍后对其进行测试...

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];        
    if([defaults objectForKey:@"firstRun"])           
    {
      // do something or not...
    }
    

    【讨论】:

    • 在哪里测试??在应用程序中没有完成启动方法??
    • 你能把这个放在applicationDidFinishLaunchingWithOptions吗?
    • @paulthenerd 避免使用速记!在这种情况下。即使具有键 firstRun 的对象存在并且具有布尔值 NO,它也会失败。如果对象不存在,则返回 nil,因此如果 ([] != nil) 将在此处使用。
    • 如果用户更新应用然后启动应用会怎样?
    【解决方案2】:

    好吧,是什么让我对用户默认设置感到困惑。

    它们存储在哪里?

    • 你不在乎它因 iOS/Mac 而异。
    • 您只需按 KEY 获取VALUE
    • 通过 KEY 设置VALUE + 同步
    • 其余的工作由 iOS/Mac 完成。

    这是常见的用例: 检查值是否存在,例如 firstRun。 第一次它不会存在,所以通常在设置值之后。 第二次运行 - 在下一个循环中它确实存在并且其他用例/else stmt 被触发

    ---- .h

    @interface MyAppDelegate : UIResponder <UIApplicationDelegate>
    
    //flag to denote if this is first time the app is run
    @property(nonatomic) BOOL firstRun;
    

    -----.m

    @implementation MyAppDelegate
    
    @synthesize firstRun = _firstRun;
    

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    
        //============== 
        //Check to see if this is first time app is run by checking flag we set in the defaults
    
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  
    
        if (![defaults objectForKey:@"firstRun"]){
            //flag doesnt exist then this IS the first run
            self.firstRun = TRUE;
            //store the flag so it exists the next time the app starts
            [defaults setObject:[NSDate date] forKey:@"firstRun"];
        }else{
            //flag does exist so this ISNT the first run
            self.firstRun = FALSE; 
        }        
        //call synchronize to save default - where its saved is managed by iOS - varies by device and iOS/Mac
        [[NSUserDefaults standardUserDefaults] synchronize];
        //TO TEST: delete the app on the device/simulator
        //run it - should be the first run
        //close it - make sure you kill it and its not just in the background else didFinishLaunchingWithOptions wont be called
        //just applicationDidBecomeActive
        //2nd run it should  self.firstRun = FALSE;
        //=============
    

    //如果您的 ROOTVIEWCONTROLLER 检查 appDelegate.firstRun 则请务必在此处设置 self.window.rootViewController 之前进行上述检查

    self.window.rootViewController = self.navController;
    
    
        [self.window makeKeyAndVisible];
        return YES;
    }
    

    ---- 使用标志

    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
    
    if (appDelegate.firstRun){
        NSLog(@"IS FIRST RUN - Do something: e.g. set up password");
    
    }else {
         NSLog(@"FPMyMusicScreenViewController: IS NOT FIRST RUN - Prompt for password");
    }
    

    上面的例子让我有点困惑,因为它们第一次展示了如何检查它,但随后在同一评论中提到了如何“稍后检查”。 问题是当我们发现它不存在时,我们立即创建它并同步。 因此,延迟检查实际上意味着您重新启动应用程序时与第一次运行不同。

    【讨论】:

    • 从 iPhone 模拟器中清除存储(这些“默认值”)的正确方法是什么?
    • 默认情况下,boolForKey 将返回 false,字符串将为 nil 等。如果要初始化用户默认值,只需使用 registerDefaults,以及要使用的键和值。如果你想初始化一个日期,可以使用 [NSDate distinctFuture]
    【解决方案3】:

    在您的应用委托中注册一个默认值:

    NSDictionary *defaultsDict = 
    [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"FirstLaunch", nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDict];
    [defaultsDict release];
    

    然后你要检查的地方:

    NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
    if ([sharedDefaults boolForKey:@"FirstLaunch"]) {
      //Do the stuff you want to do on first launch
      [sharedDefaults setBool:NO forKey:@"FirstLaunch"];
      [sharedDefaults synchronize];
    }
    

    【讨论】:

    • 您是否应该在 if..stmt 中将 FirstLaunch 设置为 NO,这样它就不会在下一次应用迭代时运行?
    • @brian.clear,仅当您不需要确认用户看到了您要显示的内容,没有初始化要做/确认等时。例如,在我的在第一次运行的情况下,我希望用户确认他们看到了教程或选择跳过它,而不是点击打开,然后锁定他们的手机,最终我的应用程序被挤出内存。可能听起来不常见,但我在某处排队时下载新应用程序时已经做了很多次,第一次启动应用程序,然后立即锁定我的手机 b/c 轮到我排队了。所以,取决于用例。有意义吗?
    【解决方案4】:

    您可以使用下面的静态方法来实现它。我认为这更好,因为您可以根据需要多次调用此方法,这与其他解决方案不同。享受:(请记住,它不是线程安全的)

    + (BOOL)isFirstTime{
        static BOOL flag=NO;
        static BOOL result;
        if(!flag){
            if ([[NSUserDefaults standardUserDefaults] boolForKey:@"hasLaunchedOnce"])
            {
                result=NO;
            } else
            {
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"hasLaunchedOnce"];
                [[NSUserDefaults standardUserDefaults] synchronize];
                result=YES;
            }
    
        flag=YES;
        }
        return result;
    }
    

    【讨论】:

      【解决方案5】:

      您可以将自定义类别方法 isFirstLaunch 与 UIViewController+FirstLaunch 结合使用。

      - (BOOL)isFirstLaunch
      {
          if ([[NSUserDefaults standardUserDefaults] boolForKey:@"kFirstLaunch"]) {
              return YES;
          }
          else {
              [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kFirstLaunch"];
              [[NSUserDefaults standardUserDefaults] synchronize];
              return NO;
          }
      }
      

      当你需要在控制器中使用它时

      BOOL launched = [self isFirstLaunch];
      
      if (launched) {
      //if launched
      }
      else {
      //if not launched
      }
      

      【讨论】:

        【解决方案6】:

        使用 NSUserDefaults。如果 sharedDefault 具有您的应用程序的密钥,则它会在之前运行。当然,您必须让应用程序在第一次运行时创建至少一个默认条目。

        【讨论】:

          【解决方案7】:

          斯威夫特:

          var isFirstLaunch: Bool {
              get {
                  if (NSUserDefaults.standardUserDefaults().objectForKey("firstLaunchDate") == nil) {
                      NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: "firstLaunchDate")
                      NSUserDefaults.standardUserDefaults().synchronize()
                      return true
                  }
                  return false
              }
          }
          

          另一个提示:

          使用 NSUserDefaults 时,如果应用被删除,这些设置将被清除。如果出于某种原因您需要这些设置仍然存在,您可以将它们存储在钥匙串中。

          【讨论】:

            猜你喜欢
            • 2011-11-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多