Jak wykryć pierwsze uruchomienie aplikacji na iPhonie

Odpowiedzi:

386
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (![[NSUserDefaults standardUserDefaults] boolForKey:@"HasLaunchedOnce"])
    {
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HasLaunchedOnce"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    return YES;
}
Sameera R.
źródło
Pojawia się błąd, ponieważ metoda nie zwraca wartości logicznej. Jeśli użyję return 0; zabić błąd, który się nie powiedzie
mrEmpty
@mrEmpty 1. ??? Wraca BOOL. 2. Wtedy błąd jest w twoim kodzie ... jeśli zwrócenie 0 powoduje awarię, to coś jest strasznie nie tak - gdzie indziej.
@ H2CO3 - czy to nie NSUserDefaultsjest powszechne miejsce? co się stanie, jeśli inna aplikacja używa tego samego „klucza”, którego ja używam?
Ziv Levy
6
@ZivLevy Nie, wartości domyślne użytkownika są przechowywane na liście właściwości dla poszczególnych piaskownic (= aplikacji).
2
Będzie działać tylko w przypadku nowych aplikacji, które nigdy wcześniej nie zostały przesłane.
Elad,
36

W Swift 3, 4 spróbuj tego:

func isAppAlreadyLaunchedOnce()->Bool{
        let defaults = UserDefaults.standard

        if let isAppAlreadyLaunchedOnce = defaults.string(forKey: "isAppAlreadyLaunchedOnce"){
            print("App already launched : \(isAppAlreadyLaunchedOnce)")
            return true
        }else{
            defaults.set(true, forKey: "isAppAlreadyLaunchedOnce")
            print("App launched first time")
            return false
        }
    }

W Swift 2 spróbuj tego,

func isAppAlreadyLaunchedOnce()->Bool{
    let defaults = NSUserDefaults.standardUserDefaults()

    if let isAppAlreadyLaunchedOnce = defaults.stringForKey("isAppAlreadyLaunchedOnce"){
        print("App already launched : \(isAppAlreadyLaunchedOnce)")
        return true
    }else{
        defaults.setBool(true, forKey: "isAppAlreadyLaunchedOnce")
        print("App launched first time")
        return false
    }
}

AKTUALIZACJA: - W przypadku OBJ-C używam tego,

+ (BOOL)isAppAlreadyLaunchedOnce {
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"isAppAlreadyLaunchedOnce"])
    {
        return true;
    }
    else
    {
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isAppAlreadyLaunchedOnce"];
        [[NSUserDefaults standardUserDefaults] synchronize];
        return false;
    }
}

Odniesienie do OBJ-C: https://stackoverflow.com/a/9964400/3411787

Mohammad Zaid Pathan
źródło
32

Właśnie w tym celu napisałem małą bibliotekę. Daje mi znać, czy jest to pierwsze uruchomienie w historii, czy tylko dla tej wersji i wszelkich wcześniejszych wersji zainstalowanych przez użytkownika. Jest dostępny na github jako cocoapod na licencji Apache 2: GBVersionTracking

Po prostu zadzwoń application:didFinishLaunching:withOptions:

[GBVersionTracking track];

A następnie, aby sprawdzić, czy to pierwsze uruchomienie, po prostu wywołaj to w dowolnym miejscu:

[GBVersionTracking isFirstLaunchEver];

I podobnie:

[GBVersionTracking isFirstLaunchForVersion];

[GBVersionTracking currentVersion];
[GBVersionTracking previousVersion];
[GBVersionTracking versionHistory];
lms
źródło
1
To jest prawie idealne! Byłoby wspaniale bez zależności GBToolbox i podspec.
Stian Høiland
4
Zależność @ StianHøiland GBToolbox zniknęła, a biblioteka zawiera podspec (opublikowany w repozytorium specyfikacji CocoaPods).
lms
9

dla Swift 3.0 - Swift 5

Dodaj rozszerzenie

    extension UIApplication {
        class func isFirstLaunch() -> Bool {
            if !UserDefaults.standard.bool(forKey: "hasBeenLaunchedBeforeFlag") {
                UserDefaults.standard.set(true, forKey: "hasBeenLaunchedBeforeFlag")
                UserDefaults.standard.synchronize()
                return true
            }
            return false
        }
    }

następnie w swoim kodzie

UIApplication.isFirstLaunch()
KIO
źródło
8

Innym pomysłem na Xcode 7 i Swift 2.0 jest użycie rozszerzeń

extension NSUserDefaults {
    func isFirstLaunch() -> Bool {
        if !NSUserDefaults.standardUserDefaults().boolForKey("HasAtLeastLaunchedOnce") {
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "HasAtLeastLaunchedOnce")
            NSUserDefaults.standardUserDefaults().synchronize()
            return true
        }
        return false
    }
}

Teraz możesz pisać w dowolnym miejscu w swojej aplikacji

if NSUserDefaults.standardUserDefaults().isFirstLaunch() {
    // do something on first launch
}

Osobiście wolę takie rozszerzenie UIApplication:

extension UIApplication {
    class func isFirstLaunch() -> Bool {
        if !NSUserDefaults.standardUserDefaults().boolForKey("HasAtLeastLaunchedOnce") {
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "HasAtLeastLaunchedOnce")
            NSUserDefaults.standardUserDefaults().synchronize()
            return true
        }
        return false
    }
}

Ponieważ wywołanie funkcji jest bardziej opisowe:

if UIApplication.isFirstLaunch() {
    // do something on first launch
}
dennis-tra
źródło
8

Możesz to zaimplementować za pomocą metody statycznej poniżej:

+ (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;
}
Mati Bot
źródło
pamiętaj, że musisz zablokować tę metodę, jeśli chcesz, aby była bezpieczna dla wątków.
Mati Bot
9
Wiem, ale ta metoda nie jest. 2 Wątki mogą dotrzeć do flagi if (!) {, Gdy flaga jest NIE. dostaną się do bloków if. jeden z nich dostanie się do wewnętrznego else i ustawi NSUserDefaults, a drugi przekaże "hasLaunchOnce" (ponieważ zadeklarował to pierwszy wątek) i ustawi wynik na NIE. Oznacza to, że możesz uzyskać niewłaściwą wartość.
Mati Bot
5

Musisz coś zapisać podczas uruchamiania, a następnie sprawdzić, czy istnieje. Jeśli nie, to pierwszy raz. „Coś” może być plikiem, wpisem w bazie danych, ustawieniem domyślnym użytkownika ....

Phillip Mills
źródło
4

Jest to dość proste i wymaga tylko sześciu wierszy kodu.

Przydatne będzie dodanie tego kodu w preferencjach uruchamiania aplikacji lub w dowolnym innym miejscu, w którym może być konieczne sprawdzenie, czy jest to pierwsze uruchomienie aplikacji.

//These next six lines of code are the only ones required! The rest is just running      code when it's the first time.
//Declare an integer and a default.
NSUserDefaults *theDefaults;
int  launchCount;
//Set up the properties for the integer and default.
theDefaults = [NSUserDefaults standardUserDefaults];
launchCount = [theDefaults integerForKey:@"hasRun"] + 1;
[theDefaults setInteger:launchCount forKey:@"hasRun"];
[theDefaults synchronize];

//Log the amount of times the application has been run
NSLog(@"This application has been run %d amount of times", launchCount);

//Test if application is the first time running
if(launchCount == 1) {
    //Run your first launch code (Bring user to info/setup screen, etc.)
    NSLog(@"This is the first time this application has been run";
}

//Test if it has been run before
if(launchCount >= 2) {
    //Run new code if they have opened the app before (Bring user to home screen etc.
    NSLog(@"This application has been run before);
}

PS NIE używaj znaków bools w preferencjach Po prostu trzymaj się liczb całkowitych. Domyślnie mają wartość zero, gdy są niezdefiniowane.

Ponadto [theDefaults synchronize];linia nie jest wymagana, ale odkryłem, że gdy aplikacja jest uruchamiana setki razy na setkach urządzeń, wyniki nie zawsze są wiarygodne, poza tym jest to lepsza praktyka.

Milo
źródło
Twój przykład działa, ale PO pyta tylko o to, czy jest to pierwszy start, czy nie. Do tego idealnie nadaje się bool. Twój kod ma sens, jeśli chcesz wiedzieć, ile razy użytkownik otworzył aplikację.
tilo,
3

zapisz klucz bool w NSUserDefaults za pierwszym razem, gdy będzie to nie, zmienisz go na tak i zachowasz go tak, aż aplikacja usunie lub ponownie zainstaluje ją ponownie za pierwszym razem.

Malek_Jundi
źródło
3

Szybka i łatwa funkcja

- (BOOL) isFirstTimeOpening {
    NSUserDefaults *theDefaults = [NSUserDefaults standardUserDefaults];
    if([theDefaults integerForKey:@"hasRun"] == 0) {
        [theDefaults setInteger:1 forKey:@"hasRun"];
        [theDefaults synchronize];
        return true;
    }
    return false;
}
Chris Fremgen
źródło
3

Dla Swift 2.0 w Xcode 7. W pliku AppDelegate.swift:

import UIKit

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, willFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
    return true
}


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    didFinishLaunchingOnce()
    return true
}

func didFinishLaunchingOnce() -> Bool
{
    let defaults = NSUserDefaults.standardUserDefaults()

    if let hasBeenLauncherBefore = defaults.stringForKey("hasAppBeenLaunchedBefore")
    {
        //print(" N-th time app launched ")
        return true
    }
    else
    {
        //print(" First time app launched ")
        defaults.setBool(true, forKey: "hasAppBeenLaunchedBefore")
        return false
    }
}

}
MB_iOSDeveloper
źródło
2

szybki

struct Pref {
    static let keyFirstRun = "PrefFirstRun"
    static var isFirstRun: Bool {
        get {
            return UserDefaults.standard.bool(forKey: keyFirstRun)
        }
        set {
            UserDefaults.standard.set(newValue, forKey: keyFirstRun)
        }
    }
}

Zarejestruj wartości domyślne podczas uruchamiania aplikacji:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let prefs: [String:Any] = [
            Pref.keyFirstRun: true
            ...
        ]

        UserDefaults.standard.register(defaults: prefs)

Wyczyść wartość po zamknięciu aplikacji:

func applicationWillTerminate(_ application: UIApplication) {
        Pref.isFirstRun = false

Wartość czeku:

 if Pref.isFirstRun {
    ... do whatever 
Prcela
źródło
2

W szybkim tempie sugerowałbym użycie stałej globalnej, którą można bardzo łatwo wykonać poza jakimkolwiek zakresem, na przykład powyżej delegata aplikacji. W związku z tym będzie ustawiona właściwa wartość, dopóki aplikacja nie zostanie zakończona. nadal będzie zwracać tę samą wartość, jeśli aplikacja przejdzie w tryb w tle. wartość zmieni się tylko wtedy, gdy aplikacja zostanie ponownie uruchomiona.

let isFirstLaunch: Bool = {
    if !UserDefaults.standard.bool(forKey: "hasBeenLaunchedBeforeFlag") {
        UserDefaults.standard.set(true, forKey: "hasBeenLaunchedBeforeFlag")
        UserDefaults.standard.synchronize()
        return true
    }
    return false
}()

Ale szczerze mówiąc, lepiej jest śledzić fakt, że aplikacja została przynajmniej raz wysłana do tła. W takim przypadku wolę użyć rozszerzenia na UIApplication i ustawić flagę w metodzie applicationDidEnterBackground tak, że:

extension UIApplication {
    private static let isFirstLaunchKey = "isFirstLaunchKey"
    static var isFirstLaunch: Bool {
        return !UserDefaults.standard.bool(forKey: isFirstLaunchKey)
    }
    static func didEnterBackground() {
        if isFirstLaunch {
            UserDefaults.standard.set(true, forKey: isFirstLaunchKey)
            UserDefaults.standard.synchronize()
        }
    }
}

a następnie w delegacie aplikacji lub delegacie sceny

func sceneDidEnterBackground(_ scene: UIScene) {
        UIApplication.didEnterBackground()
    }
Nicolas Manzini
źródło
2

Swift 5 iOS 13.

Lubię szybkie i łatwe Chris Fremgen . Więc zaktualizowałem to.

func isFirstTimeOpening() -> Bool {
  let defaults = UserDefaults.standard

  if(defaults.integer(forKey: "hasRun") == 0) {
      defaults.set(1, forKey: "hasRun")
      return true
  }
  return false

}
user3069232
źródło
2

Zaktualizowano dla XCode 11 , Swift 5

extension UIApplication {
  func isFirstLaunch() -> Bool {
    if !UserDefaults.standard.bool(forKey: "HasLaunched") {
      UserDefaults.standard.set(true, forKey: "HasLaunched")
      UserDefaults.standard.synchronize()
      return true
  }
  return false
}

Następnie nazywasz to jako

UIApplication.isFirstLaunch()
sasquatch
źródło
0

NSUserDefaults + Macro

Najlepszym podejściem jest użycie NSUserDefaultsi zapisanie BOOLzmiennej. Jak wspomniano powyżej, następujący kod będzie dobrze:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:[NSNumber numberWithBool:true] forKey:@"~applicationHasLaunchedBefore"];
[userDefaults synchronize];

Możesz również utworzyć makro jak poniżej, aby łatwo sprawdzić, czy jest to pierwsze uruchomienie, czy nie

#define kApplicationHasLaunchedBefore [[NSUserDefaults standardUserDefaults] objectForKey:@"~applicationHasLaunchedBefore"]

Następnie użyj go jako takiego,

if (kApplicationHasLaunchedBefore) {
    //App has previously launched
} else {
    //App has not previously launched
}
Fernando Cervantes
źródło
0

Oto odpowiedź działająca w Swift 5.0. Poprawa w porównaniu z odpowiedzią @Zaid Pathan polega na tym, że nie ma ukrytej umowy. Jeśli nie zadzwonisz setFirstAppLaunch()dokładnie raz przed wywołaniem isFirstAppLaunch(), otrzymasz błąd potwierdzenia (tylko w trybie debugowania).

fileprivate struct _firstAppLaunchStaticData {
    static var alreadyCalled = false
    static var isFirstAppLaunch = true
    static let appAlreadyLaunchedString = "__private__appAlreadyLaunchedOnce"
}

func setFirstAppLaunch() {
    assert(_firstAppLaunchStaticData.alreadyCalled == false, "[Error] You called setFirstAppLaunch more than once")
    _firstAppLaunchStaticData.alreadyCalled = true
    let defaults = UserDefaults.standard

    if defaults.string(forKey: _firstAppLaunchStaticData.appAlreadyLaunchedString) != nil {
        _firstAppLaunchStaticData.isFirstAppLaunch = false
    }
    defaults.set(true, forKey: _firstAppLaunchStaticData.appAlreadyLaunchedString)
}

func isFirstAppLaunch() -> Bool {
    assert(_firstAppLaunchStaticData.alreadyCalled == true, "[Error] Function setFirstAppLaunch wasn't called")
    return _firstAppLaunchStaticData.isFirstAppLaunch
}

Następnie wystarczy wywołać funkcję setFirstAppLaunch()na początku aplikacji i isFirstAppLaunch()za każdym razem, gdy chcesz sprawdzić, czy Twoja aplikacja została wywołana.

eon
źródło