About the Using Swift defer

How can I deal with this situation?

static var current:AKXUserIdentity? {
            get {
                // I want use defer here
                func gotoStartInitPage() {
                    
                }
                
                guard let localID = UserDefaults.standard.string(forKey: localIDkey) else {
                    gotoStartInitPage()
                    return nil
                }
                
                guard let db =  AKXCommonDB.default else {
                    gotoStartInitPage()
                    return nil
                }
                
                let (userIdentity, error) = db.userIdentityTable
                    .queryUserIdentity(localID: Int(localID)!)
                
                if let error = error {
                    gotoStartInitPage()
                    return nil
                }else {
                    return userIdentity
                }
            }
        }

var successful = false
defer {
    if !successful {
        // do goStartInitPage here
    }
}

guard let localID = Whatever1 else { return nil }
guard let db = Whatever2 else { return nil }

let (userIdentity, error) = Whatever3
guard error == nil else { return nil }

successful = true
return userIdentity
1 Like

I believe this is more elegant

var goToStartInitPage: (() -> ())? = { ... }  // nil if you don't need to

defer {
    goToStartInitPage?()
}

// your code
1 Like

thanks for your Answer!

@cuikun It would probably be better if you used the dedicated like button rather than thanking everyone who replied to you. It'd help keep the thread cleaner.

1 Like

Personally I don't think that's an use case for defer, but in general I would just split computing the actual value and returning it, i.e.

func _get() -> AKXUserIdentity? {
  guard
    let localID = UserDefaults.standard.string(forKey: localIDkey),
    let db = AKXCommonDB.default
  else { return nil }
  let (userIdentity, error) = db.userIdentityTable
    .queryUserIdentity(localID: Int(localID)!)
  guard error == nil else { return nil }
  return userIdentity
}

guard let userIdentity = _get() else {
  gotoStartInitPage()
  return nil
}

Or, if your utility methods used throw instead or returning an Optional, you could manage this with a single catch ;)