Como detectar a primeira inicialização do aplicativo em um iPhone

Respostas:

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.
fonte
Eu recebo um erro porque o método não está retornando um valor booleano. Se eu usar return 0; para matar o erro, ele falha.
mrEmpty
@mrEmpty 1. ??? Retorna BOOL. 2. Então o erro está no seu código ... se o retorno de 0 causar esta falha, algo está terrivelmente errado - em outro lugar.
@ H2CO3 - não é NSUserDefaultsum lugar comum? e se outro aplicativo usar a mesma "chave" que estou usando?
Ziv Levy
6
@ZivLevy Não, os padrões do usuário são armazenados em uma lista de propriedades por sandbox (= por aplicativo).
2
Funcionará apenas para novos aplicativos que nunca foram enviados antes.
Elad
36

No Swift 3, 4, tente o seguinte:

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
        }
    }

No Swift 2, tente isso,

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
    }
}

UPDATE: - Para OBJ-C eu uso isso,

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

Ref para OBJ-C: https://stackoverflow.com/a/9964400/3411787

Mohammad Zaid Pathan
fonte
32

Eu escrevi uma pequena biblioteca para esse propósito. Ele me informa se esse é o primeiro lançamento de todos os tempos, ou apenas para esta versão, e se há versões anteriores que o usuário instalou. Está disponível no github como um cocoapod sob a licença Apache 2: GBVersionTracking

Você acabou de chamar isso application:didFinishLaunching:withOptions:

[GBVersionTracking track];

E então, para verificar se este é o primeiro lançamento, basta ligar para este local:

[GBVersionTracking isFirstLaunchEver];

E da mesma forma:

[GBVersionTracking isFirstLaunchForVersion];

[GBVersionTracking currentVersion];
[GBVersionTracking previousVersion];
[GBVersionTracking versionHistory];
lms
fonte
1
Isso é quase perfeito! Teria sido incrível sem a dependência do GBToolbox e um podspec.
Stian Høiland
4
@ A dependência do StianHøiland GBToolbox se foi, e a biblioteca vem com um podspec (publicado no repositório de especificações do CocoaPods).
lms
9

para Swift 3.0 - Swift 5

adicionar extensão

    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
        }
    }

então no seu código

UIApplication.isFirstLaunch()
KIO
fonte
8

Outra idéia para o Xcode 7 e o Swift 2.0 é usar extensões

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

Agora você pode escrever em qualquer lugar do seu aplicativo

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

Pessoalmente, prefiro uma extensão do UIApplication assim:

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

Como a chamada de função é mais descritiva:

if UIApplication.isFirstLaunch() {
    // do something on first launch
}
dennis-tra
fonte
8

Você pode implementá-lo com o método estático abaixo:

+ (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
fonte
lembre-se de que você precisa bloquear esse método se quiser que ele seja seguro para threads.
Mati Bot
9
Eu sei, mas esse método não é. 2 Threads podem alcançar o if (! Flag) {quando o flag é NO. eles entrarão nos blocos if. um deles chegará ao interior e definirá o NSUserDefaults e o segundo passará o "hasLaunchOnce" (porque o primeiro thread o declarou) e definirá o resultado como NO. Isso significa que você pode obter o valor errado.
Mati Bot
5

Você precisa salvar algo ao iniciar e, em seguida, verifique se ele existe. Caso contrário, é a primeira vez. "Algo" pode ser um arquivo, uma entrada no banco de dados, uma configuração nos padrões do usuário ....

Phillip Mills
fonte
4

É bem simples de fazer isso e requer apenas seis linhas de código.

Será útil adicionar esse código nas preferências de inicialização do aplicativo ou em qualquer outro lugar em que você precise testar se é a primeira vez que o aplicativo é executado.

//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: Não use bools nas preferências. Basta usar números inteiros. Eles assumem o valor zero quando indefinidos.

Além disso, a [theDefaults synchronize];linha não é necessária, mas descobri que quando um aplicativo é executado centenas de vezes em centenas de dispositivos, os resultados nem sempre são confiáveis, além disso, é uma prática recomendada.

Milo
fonte
Seu exemplo funciona, mas tudo o que o OP pede é se é o primeiro início ou não. Um bool é perfeitamente adequado para isso. Seu código faz sentido se alguém quiser saber quantas vezes o usuário abriu o aplicativo.
tilo 12/07/2013
3

armazenar uma chave bool no NSUserDefaults pela primeira vez, será não, você a alterará para yes e a manterá assim até que o aplicativo exclua ou reinstale-a novamente.

Malek_Jundi
fonte
3

Função rápida e fácil

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

Para Swift 2.0 no Xcode 7. No arquivo 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
fonte
2

rápido

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

Registre os valores padrão na inicialização do aplicativo:

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

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

        UserDefaults.standard.register(defaults: prefs)

Valor claro no encerramento do aplicativo:

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

Verifique o valor:

 if Pref.isFirstRun {
    ... do whatever 
Prcela
fonte
2

Em breve, sugiro usar uma constante global que possa ser feita com muita facilidade fora de qualquer escopo, como acima do delegado do aplicativo. Portanto, ele será definido com o valor certo enquanto o aplicativo não for finalizado. ainda retornará o mesmo valor se o aplicativo for para segundo plano ou algo assim. o valor será alterado apenas se o aplicativo for reiniciado completamente.

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

Mas, honestamente, é melhor acompanhar o fato de que o aplicativo foi enviado para segundo plano pelo menos uma vez. Nesse caso, prefiro usar uma extensão no UIApplication e definir o sinalizador no método applicationDidEnterBackground, de modo que:

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()
        }
    }
}

e, em seguida, no delegado do seu aplicativo ou delegado da cena

func sceneDidEnterBackground(_ scene: UIScene) {
        UIApplication.didEnterBackground()
    }
Nicolas Manzini
fonte
2

Swift 5 iOS 13.

Gosto rápido e fácil de Chris Fremgen . Então eu atualizei.

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

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

}
user3069232
fonte
2

Atualizado para o 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
}

Então você o chama como

UIApplication.isFirstLaunch()
sasquatch
fonte
0

NSUserDefaults + Macro

A melhor abordagem é usar NSUserDefaultse salvar uma BOOLvariável. Como mencionado acima, o código a seguir funcionará perfeitamente:

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

Você também pode criar uma macro como abaixo para verificar facilmente se é o primeiro lançamento ou não

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

Em seguida, use-o como tal,

if (kApplicationHasLaunchedBefore) {
    //App has previously launched
} else {
    //App has not previously launched
}
Fernando Cervantes
fonte
0

Aqui está uma resposta trabalhando no swift 5.0. A melhoria em comparação com a resposta de @Zaid Pathan é que não há contrato oculto. Se você não ligar setFirstAppLaunch()exatamente uma vez antes de ligar, isFirstAppLaunch()receberá um erro de asserção (apenas no modo de depuração).

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
}

Depois, basta chamar a função setFirstAppLaunch()no início do seu aplicativo e isFirstAppLaunch()sempre que desejar verificar se o aplicativo foi chamado.

aeon
fonte