Cómo detectar el inicio de la aplicación por primera vez en un iPhone

Respuestas:

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.
fuente
Recibo un error porque el método no devuelve un valor booleano. Si uso return 0; para matar el error falla.
mrEmpty
@mrEmpty 1. ??? Vuelve BOOL. 2. Entonces el error está en su código ... si devolver 0 hace que se bloquee, entonces algo está terriblemente mal, en otro lugar.
@ H2CO3: ¿no es NSUserDefaultsun lugar común? ¿Qué pasa si otra aplicación usa la misma "clave" que yo estoy usando?
Ziv Levy
66
@ZivLevy No, los valores predeterminados del usuario se almacenan en una lista de propiedades por caja de arena (= por aplicación).
2
Funcionará solo para nuevas aplicaciones que nunca antes se enviaron.
Elad
36

En Swift 3, 4 intente esto:

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

En Swift 2 intente esto,

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

ACTUALIZACIÓN: - Para OBJ-C utilizo esto,

+ (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
fuente
32

Escribí una pequeña biblioteca para este mismo propósito. Me permite saber si este es el primer lanzamiento, o solo para esta versión, y cualquier versión anterior que el usuario haya instalado. Está disponible en github como cocoapod bajo la licencia Apache 2: GBVersionTracking

Solo llamas a esto en application:didFinishLaunching:withOptions:

[GBVersionTracking track];

Y luego para verificar si este es el primer lanzamiento, simplemente llame a esto en cualquier lugar:

[GBVersionTracking isFirstLaunchEver];

Y de manera similar:

[GBVersionTracking isFirstLaunchForVersion];

[GBVersionTracking currentVersion];
[GBVersionTracking previousVersion];
[GBVersionTracking versionHistory];
lms
fuente
1
¡Esto es casi perfecto! Hubiera sido increíble sin la dependencia GBToolbox y un podspec.
Stian Høiland
44
@ StianHøiland La dependencia de GBToolbox desapareció y la biblioteca viene con un podspec (publicado en el repositorio de especificaciones de CocoaPods).
lms
9

para Swift 3.0 - Swift 5

agregar extensión

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

entonces en tu código

UIApplication.isFirstLaunch()
KIO
fuente
8

Otra idea para Xcode 7 y Swift 2.0 es usar extensiones

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

Ahora puedes escribir en cualquier lugar de tu aplicación

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

Personalmente prefiero una extensión de la aplicación UIA como esta:

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

Debido a que la llamada a la función es más descriptiva:

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

Puede implementarlo con el siguiente método estático:

+ (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
fuente
tenga en cuenta que debe bloquear este método si desea que sea seguro para subprocesos.
Mati Bot
9
Lo sé, pero este método no lo es. 2 subprocesos pueden alcanzar el if (! Flag) {cuando flag es NO. entrarán dentro de los bloques if. uno de ellos llegará al interior y establecerá los NSUserDefaults y el segundo pasará el "hasLaunchOnce" (porque el primer hilo lo declaró) y establecerá el resultado en NO. Eso significa que puede obtener el valor incorrecto.
Mati Bot
5

Debe guardar algo cuando lo inicie y luego verificar si existe. Si no, es la primera vez. "Algo" puede ser un archivo, una entrada de la base de datos, una configuración en los valores predeterminados del usuario ...

Phillip Mills
fuente
4

Es bastante simple hacer esto y solo requiere seis líneas de código.

Será útil agregar este código en las preferencias de inicio de su aplicación o en cualquier otro lugar donde necesite probar si es la primera vez que se ejecuta su aplicación.

//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);
}

PD : NO use bools en las preferencias. Solo manténgase en los enteros. Su valor predeterminado es cero cuando no está definido.

Además, la [theDefaults synchronize];línea no es necesaria, pero descubrí que cuando una aplicación se ejecuta cientos de veces en cientos de dispositivos, los resultados no siempre son confiables, además, es una mejor práctica.

Milo
fuente
Su ejemplo funciona, pero todo lo que el OP pregunta es si es el primer inicio o no. Un bool está perfectamente bien para esto. Su código tiene sentido si uno quiere saber cuántas veces el usuario abrió la aplicación.
tilo 12/0713
3

almacene una clave bool en NSUserDefaults la primera vez que sea no, la cambiará a sí y la mantendrá así hasta que la aplicación la elimine o vuelva a instalar será la primera vez.

Malek_Jundi
fuente
3

Función rápida y 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
fuente
3

Para Swift 2.0 en Xcode 7. En el archivo 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
fuente
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 los valores predeterminados al iniciar la aplicación:

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

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

        UserDefaults.standard.register(defaults: prefs)

Valor claro al finalizar la aplicación:

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

Comprobar valor:

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

En Swift, sugeriría usar una constante global que se puede hacer muy fácilmente fuera de cualquier alcance, como por ejemplo el delegado de la aplicación. Por lo tanto, se establecerá en el valor correcto mientras la aplicación no finalice. aún devolverá el mismo valor si la aplicación pasa a segundo plano más o menos. el valor cambiará solo si la aplicación se relanza por completo.

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

Pero, sinceramente, es mejor hacer un seguimiento del hecho de que la aplicación se ha enviado al fondo al menos una vez. En tal caso, prefiero usar una extensión en UIApplication y establecer el indicador en el 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()
        }
    }
}

y luego en su delegado de aplicación o delegado de escena

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

Swift 5 iOS 13.

Me gusta rápido y fácil por Chris Fremgen . Entonces lo actualicé.

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

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

}
usuario3069232
fuente
2

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

Entonces lo llamas como

UIApplication.isFirstLaunch()
Sasquatch
fuente
0

NSUserDefaults + Macro

El mejor enfoque es usar NSUserDefaultsy guardar una BOOLvariable. Como se mencionó anteriormente, el siguiente código funcionará bien:

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

También puede crear una macro como la siguiente para verificar fácilmente si es el primer lanzamiento o no

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

Entonces úsalo como tal,

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

Aquí hay una respuesta que funciona en swift 5.0. La mejora en comparación con la respuesta de @Zaid Pathan es que no hay un contrato oculto. Si no llama setFirstAppLaunch()exactamente una vez antes de llamar isFirstAppLaunch(), obtendrá un error de aserción (solo en modo de depuración).

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
}

Luego solo necesita llamar a la función setFirstAppLaunch()al inicio de su aplicación y isFirstAppLaunch()siempre que desee verificar si se ha llamado a su aplicación.

Eón
fuente