为 AWS AppSync 客户端 iOS Swift 启用缓存

Posted

技术标签:

【中文标题】为 AWS AppSync 客户端 iOS Swift 启用缓存【英文标题】:Enabling cache for AWS AppSync Client iOS Swift 【发布时间】:2019-02-21 19:46:27 【问题描述】:

我正在使用AWS AppSync 创建我的 ios 应用程序。我想利用AppSync 提供的离线突变和查询缓存。但是当我关闭我的互联网时,我没有得到任何回应。而是将错误显示为“Internet 连接似乎已脱机。”。这似乎是Alamofire 异常而不是AppSync 异常。这是因为查询没有缓存在我的设备中。以下是我的代码 sn-p 来初始化客户端。

do 
    let appSyncClientConfig = try AWSAppSyncClientConfiguration.init(url: AWSConstants.APP_SYNC_ENDPOINT, serviceRegion: AWSConstants.AWS_REGION, userPoolsAuthProvider: MyCognitoUserPoolsAuthProvider())
    AppSyncHelper.shared.appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncClientConfig)
    AppSyncHelper.shared.appSyncClient?.apolloClient?.cacheKeyForObject =  $0["id"] 
 catch 
    print("Error in initializing the AppSync Client")
    print("Error: \(error)")
    UserDefaults.standard.set(nil, forKey: DeviceConstants.ID_TOKEN)

我在获取会话时将令牌缓存在UserDefaults 中,然后每当调用AppSyncClient 时,它都会通过调用我的MyCognitoUserPoolsAuthProvider: AWSCognitoUserPoolsAuthProvidergetLatestAuthToken() 方法来获取最新的令牌。这将返回存储在UserDefaults 中的令牌 -

// background thread - asynchronous
func getLatestAuthToken() -> String 
    print("Inside getLatestAuthToken")
    var token: String? = nil
    if let tokenString = UserDefaults.standard.string(forKey: DeviceConstants.ID_TOKEN) 
        token = tokenString
        return token!
    
    return token!

我的查询模式如下

public func getUserProfile(userId: String, success: @escaping (ProfileModel) -> Void, failure: @escaping (NSError) -> Void) 
    let getQuery = GetUserProfileQuery(id: userId)
    print("getQuery.id: \(getQuery.id)")
    if appSyncClient != nil 
        print("AppSyncClient is not nil")
        appSyncClient?.fetch(query: getQuery, cachePolicy: CachePolicy.returnCacheDataElseFetch, queue: DispatchQueue.global(qos: .background), resultHandler:  (result, error) in
            if error != nil 
                failure(error! as NSError)
             else 
                var profileModel = ProfileModel()
                print("result: \(result)")
                if let data = result?.data 
                    print("data: \(data)")
                    if let userProfile = data.snapshot["getUserProfile"] as? [String: Any?] 
                        profileModel = ProfileModel(id: UserDefaults.standard.string(forKey: DeviceConstants.USER_ID), username: userProfile["username"] as? String, mobileNumber: userProfile["mobileNumber"] as? String, name: userProfile["name"] as? String, gender: (userProfile["gender"] as? Gender).map  $0.rawValue , dob: userProfile["dob"] as? String, profilePicUrl: userProfile["profilePicUrl"] as? String)
                     else 
                        print("data snapshot is nil")
                    
                
                success(profileModel)
            
        )
     else 
        APPUtilites.displayErrorSnackbar(message: "Error in the user session. Please login again")
    

AppSync提供的4个CachePolicy对象我都用过了,即

CachePolicy.returnCacheDataElseFetch
CachePolicy.fetchIgnoringCacheData
CachePolicy.returnCacheDataDontFetch
CachePolicy.returnCacheDataAndFetch.

有人可以帮助我为我的 iOS 应用正确实现缓存,以便我也可以在没有互联网的情况下进行查询吗?

【问题讨论】:

【参考方案1】:

好的,我自己找到了答案。 databaseUrl 是一个可选参数。当我们初始化 AWSAppSyncClientConfiguration 对象时,它不会出现在建议中。

所以我初始化客户端的新方法如下

let databaseURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(AWSConstants.DATABASE_NAME, isDirectory: false)
    do 
        let appSyncClientConfig = try AWSAppSyncClientConfiguration.init(url: AWSConstants.APP_SYNC_ENDPOINT,
                           serviceRegion: AWSConstants.AWS_REGION,
                           userPoolsAuthProvider: MyCognitoUserPoolsAuthProvider(),
                           urlSessionConfiguration: URLSessionConfiguration.default,
                           databaseURL: databaseURL)
        AppSyncHelper.shared.appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncClientConfig)

        AppSyncHelper.shared.appSyncClient?.apolloClient?.cacheKeyForObject =  $0["id"] 
     catch 
        print("Error in initializing the AppSync Client")
        print("Error: \(error)")
    

希望对你有帮助。

【讨论】:

我已经集成了 appsync。缓存运行良好。但是数据没有保存到离线数据库中。正在创建数据库。但是如果网络不可用,它将不会获取数据,因为 db 中没有数据。

以上是关于为 AWS AppSync 客户端 iOS Swift 启用缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 客户端中传递 AWS AppSync 自定义请求标头?

在 IOS 上使用 AWS AppSync 将图像上传到 S3

是否可以使用 AWS AppSync 构建离线优先的移动应用程序?

带有 apollo-angular 客户端的 Aws-appsync 订阅

如何设置 AWS Appsync 请求超时限制 || AWSAppSync 客户端未提供回调

验证 Apollo 客户端以使 AppSync 与 @aws_subscribe 一起使用