0

I want to create a unique identifier associated with each launch of my iOS app. I'm thinking about doing something like:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?
    var uuid: String?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    return true
}

func applicationDidBecomeActive(_ application: UIApplication) {

    self.uuid = UUID().uuidString
}

And then whenever I want to use it throughout my app I'd do:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        AppDelegate.uuid
    }
}

Is there a better place to put this session uuid other than the App Delegate?

Apollo
  • 8,874
  • 32
  • 104
  • 192
  • Create a singleton would be better – Tj3n Feb 14 '17 at 04:05
  • I'd probably use an accessor on my `AppDelegate` sub-class, but other than that, this seems reasonable. Note that in your example, `AppDelegate.uuid` should actually be `appDelegate.uuid` – David Berry Feb 14 '17 at 05:05

2 Answers2

1

You should not use the AppDelegate as something to save properties etc. You should also avoid singletons as much as possible.

You have 2 good options for this kind of stuff:

1: Use iOS Keychain, this is rather advanced, but there are many good wrappers with MIT-License for it on GitHub. I have not checked into any Swift one.

2: Easy method, use NSUserDefault

UserDefaults.standard.setValue(token, forKey: "user_auth_token")
print("\(UserDefaults.standard.value(forKey: "user_auth_token")!)")

Example Taken from here:

SIDENOTE:

Remember to clean/remove the Key on each launch of the app in your AppDelegate methods. If you want to clear the UUID that is. Or you can just overwrite it simply without cleaning it.

Also, as mentioned below in the comment by @DaveWeston , if you are going to access this key many times over and over, it is best to keep it in memory, but creating a singleton for this purpose only, is not clean in my taste, however if you already have one use it.

Update: Regarding the comments about memory and bad practices of NSUserDefaults.

Lets go to the Apple Documentation and read what it says:

At runtime, you use an NSUserDefaults object to read the defaults that your application uses from a user’s defaults database. NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. The synchronize() method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.

Also, NSUserDefaults is actually a singleton.

Community
  • 1
  • 1
  • 1
    Those are good options for a more permanent identifier, but not for a single session. It's much easier to just keep it in memory and recreate it every time the app launches. – Dave Weston Feb 14 '17 at 04:12
  • @DaveWeston Some stuff are easier, some stuff are **cleaner**. This answer is in my taste cleaner than saving properties in your AppDelegate, you could create a Property in your UIViewController and save the string to memory and load it once only if you are going to access this many times from the same UIViewController. However, using it across the app here and there, this method is more clean than creating a singleton for this single purpose, unless you already have a singleton that you are using. I will upvote your answer however, and edited my answer. –  Feb 14 '17 at 04:16
  • 1
    I generally agree with you about singletons, but an app session seems like a pretty obvious case where a singleton makes sense. Which doesn't mean you have to reach for a singleton **pattern**. An extension on `UIViewController` that hands you back a static session might be a good way to go. – Dave Weston Feb 14 '17 at 04:21
  • 1
    @DaveWeston I definitely agree with you too! It all depends on what the intentions and use of the property is for the OP, and I suspect in time he will store more than a single UUID property, then a singleton session is the way to go. –  Feb 14 '17 at 04:23
  • Note that the OP specifically wants a UUID that's reset on each launch, so neither of these is really an appropriate solution. – David Berry Feb 14 '17 at 05:03
  • @DavidBerry You are more than welcome to provide your own answer with MVC and object injections for a single NSString property to give the community more options. Go ahead and post it. –  Feb 14 '17 at 05:06
  • As I pointed out in the question comments, I don't really see any major issues with what they're doing. Perhaps an auto-initializing singleton, and/or adding an accessor. – David Berry Feb 14 '17 at 05:09
  • @DavidBerry Read my updated answer from the apple documentation, that might Give you some new insight. –  Feb 14 '17 at 05:12
  • That doesn't actually change anything Sneak. UserDefaults is still a persistent solution for a case where they explicitly want a non-persistent (changing each launch) solution. – David Berry Feb 14 '17 at 05:14
  • @DavidBerry It actually changes something, regarding the comment "It's much easier to just keep it in memory and recreate it every time the app launches " . NSUserDefaults is a singleton, and it caches everything in memory for you, and does not affect performance as long as you don't call 'synchronize' method. As for the other part, I still agree with DaveWeston iit differs from use-case to use-case. However, in this case, it's a single NSString property. No need to create a fuzz about it. For othercases, a singleton is the better way, which I use myself. That's it im out. –  Feb 14 '17 at 05:21
1

If you're really looking for a non-persisted solution, one that's different for each iteration of the application, I'd probably just go with a category on UUID (or String):

extension UUID {
    public static let sessionUUID : String = UUID().description
}

use it as UUID.sessionUUID

David Berry
  • 40,941
  • 12
  • 84
  • 95
  • Note that since static initializers are guaranteed to be lazy and thread-safe, this also deals with the eventuality that you may need it before the AppDelegate is initialized, and that it won't be executed until actually needed. – David Berry Feb 14 '17 at 05:24