I am using AWS AppSync
for creating my iOS application. I want to leverage the offline mutation as well as query caching provided by AppSync
. But when I am turning my internet off, I am not getting any response. Rather its showing an error as "The Internet connection appears to be offline.". This seems to be rather an Alamofire
exception than an AppSync
exception. This is because the query is not getting cached inside my device. Following is my code snippet to initialize the client.
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)
}
I am caching the token in the UserDefaults
at the time of fetching the session, and then whenever the AppSyncClient
is called, it fetches the latest token by calling the getLatestAuthToken()
method of my MyCognitoUserPoolsAuthProvider: AWSCognitoUserPoolsAuthProvider
. This is returning the token stored in the 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!
}
My query pattern is the following
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")
}
}
I have used all the 4 CachePolicy objects provided by AppSync, i.e,
CachePolicy.returnCacheDataElseFetch
CachePolicy.fetchIgnoringCacheData
CachePolicy.returnCacheDataDontFetch
CachePolicy.returnCacheDataAndFetch.
Can someone help me in implementing the cache properly for my iOS app so that I can do queries without the internet also?
Okay so I found the answer myself. The databaseUrl is an optional argument. It does not come in the suggestions when we are initializing the AWSAppSyncClientConfiguration object.
So the new way in which I initialized the client is the following
Hope it helps.