iOS应用使用AWS Amplify DataStore无法与DynamoDB后端同步
iOS Amplify DataStore无法同步至AppSync/DynamoDB排查
我开发的iOS应用采用AWS Cognito完成用户认证,功能正常;同时通过AWS Amplify的DataStore存储数据,使用Swift Package Manager引入amplify-ios包,版本范围设置为1.0.0 < 2.0.0。目前数据仅能保存至本地DataStore,无法同步至AppSync及后端DynamoDB——AWS控制台中对应的DynamoDB表已存在但始终为空。我已多次排查网络连接、重新搭建项目,均未解决问题。请问:
- 我哪里操作有误?
- 该Amplify库是否兼容AppSync?若不兼容,应使用何种替代方案?
相关代码
ToDoStore.swift
import Foundation import Combine import SwiftUI import Amplify class ToDoStore: ObservableObject { @Published private(set) var todos: [Todo] = [] init() { self.getAllTodosFromDataStore() } func getAllTodosFromDataStore() { Amplify.DataStore.query(Todo.self) { (result) in switch result { case .success(let todos): DispatchQueue.main.async { print("Got \(todos.count) Todos from DataStore initially") self.todos = todos } case .failure(let error): print("Error getting Todos from DataStore: \(error.localizedDescription)") } } } func deleteTodoFromDataStore(for indexSet: IndexSet) { let todosToDelete = indexSet.map { self.todos[$0] } self.todos.remove(atOffsets: indexSet) for todo in todosToDelete { Amplify.DataStore.delete(todo) { (result) in switch result { case .success(): print("Deleted Todo from DataStore") case .failure(let error): print("Error deleting Todo From DataStore: \(error)") } } } } private func addTodoToArray(_ todo: Todo) { if !self.todos.contains(todo) { self.todos.append(todo) } } private func deleteTodoFromArray(_ todo: Todo) { if let index = self.todos.firstIndex(of: todo) { self.todos.remove(at: index) } } private func updateTodoInArray(_ todo: Todo) { print("update?") } }
AWSDataStoreApp.swift
import SwiftUI import Amplify import AWSCognitoAuthPlugin import AWSDataStorePlugin import Foundation @main struct AWSDataStoreTestApp: App { @ObservedObject var sessionManager = SessionManager() init() { configureAmplify() sessionManager.getCurrentAuthUser() } var body: some Scene { WindowGroup { switch sessionManager.authState { case .login: LoginView() .environmentObject(sessionManager) case .resetPassword: ResetPasswordView() .environmentObject(sessionManager) case .signUp: SignUpView() .environmentObject(sessionManager) case .confirmCode(let username): ConfirmationView(username: username) .environmentObject(sessionManager) case .session(let user): SessionView(user: user) .environmentObject(sessionManager) } } } private func configureAmplify() { do { try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.add(plugin: AWSDataStorePlugin(modelRegistration: AmplifyModels())) try Amplify.configure() print("Amplify configured sucessfully") } catch { print("Could not intstall Amplify", error) } } }
SessionView.swift
import SwiftUI import Amplify import CoreLocation struct SessionView: View { @EnvironmentObject var sessionManager: SessionManager @ObservedObject var todoStore = ToDoStore() let user: AuthUser var body: some View { TodoListView() .onAppear(perform: { todoStore.getAllTodosFromDataStore() }) .environmentObject(sessionManager) } } struct TodoListView: View { @EnvironmentObject var sessionManager: SessionManager @State private var todos: [Todo] = [] var body: some View { NavigationView { VStack { List(todos) { todo in Text(todo.name) } .onAppear { // Query the DynamoDB table for Todo items Amplify.DataStore.query(Todo.self) { result in switch result { case .success(let todos): // Update the todos state with the retrieved Todo items self.todos = todos case .failure(let error): print("Error retrieving Todo items: \(error)") } } } NavigationLink(destination: AddTodoView() .environmentObject(sessionManager), label: { Text("Add todo") .padding() .foregroundColor(.white) .background(Color.green) .cornerRadius(10) .font( .system(size: 20)) }) } } } } struct AddTodoView: View { @EnvironmentObject var sessionManager: SessionManager @State var name = "" var body: some View { VStack { TextField("Name", text: $name) Button(action: { // create todo let todo = Todo(name: name, ownerId: sessionManager.getUser().userId) Amplify.DataStore.save(todo) { result in switch result { case .success(let success): // Update the todos state with the retrieved Todo items print(success) print("Saved") case .failure(let error): print("Error retrieving Todo items: \(error)") } } }, label: { Text("Submit") }) } } }
额外信息
应用表现
应用能正常显示DataStore中添加的内容,但无法同步。Cognito认证功能正常,资源已正确添加至项目。
Amplify状态
% amplify status Current Environment: dev ┌──────────┬──────────────────────────────────┬───────────┬───────────────────┐ │ Category │ Resource name │ Operation │ Provider plugin │ ├──────────┼──────────────────────────────────┼───────────┼───────────────────┤ │ Auth │ awsdatastoretest058f3478058f3478 │ No Change │ awscloudformation │ ├──────────┼──────────────────────────────────┼───────────┼───────────────────┤ │ Api │ awsdatastoretest │ No Change │ awscloudformation │
环境信息
- 依赖管理:Swift Package Manager
- Swift版本:Apple Swift 5.7
- Amplify CLI版本:10.5.2
- Xcode版本:14.0.1
我已重新创建项目、从头安装Amplify,排查过网络连接,均无效果。
排查与解决方案
1. Amplify库与AppSync兼容性确认
amplify-ios 1.x版本完全兼容AppSync,DataStore正是基于AppSync实现云端同步的,所以兼容性没问题,无需更换方案。
2. 核心排查点及修复建议
(1)启用DataStore云端同步
DataStore默认处于仅本地模式,你的代码未开启云端同步。修改configureAmplify方法:
private func configureAmplify() { do { let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels()) try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.add(plugin: dataStorePlugin) try Amplify.configure() // 启动云端同步 try Amplify.DataStore.start() print("Amplify configured successfully") } catch { print("Could not install Amplify", error) } }
(2)检查模型的同步与权限规则
确保Todo模型定义包含正确的@auth规则,关联认证用户:
type Todo @model @auth(rules: [{ allow: owner, ownerField: "ownerId" }]) { id: ID! name: String! ownerId: String! }
如果缺少该规则,DataStore会因权限不足无法同步到云端。
(3)验证用户认证状态与令牌有效性
DataStore同步需要有效用户令牌,可在同步前打印状态排查:
Amplify.Auth.fetchAuthSession { result in switch result { case .success(let session): print("用户已登录: \(session.isSignedIn)") print("令牌有效: \(session.userPoolTokens != nil)") case .failure(let error): print("认证会话错误: \(error)") } }
(4)检查AppSync配置与数据源
- 确认
amplifyconfiguration.json已正确添加到项目,文件需包含AppSync端点、认证信息。 - 登录AWS控制台,检查AppSync API的数据源是否指向目标DynamoDB表,Resolver规则配置正确。
(5)启用详细日志排查
开启日志查看同步失败的具体原因:
// 在Amplify.configure()之前添加 Amplify.Logging.logLevel = .verbose
控制台中搜索DataStore、SyncEngine相关日志,定位错误根源。
(6)清空本地DataStore重试
若本地存在脏数据导致同步卡住,可清空本地存储后重新测试:
Amplify.DataStore.clear { result in switch result { case .success: print("DataStore已清空") case .failure(let error): print("清空DataStore失败: \(error)") } }
内容的提问来源于stack exchange,提问作者Philip
相关产品推荐
相关产品推荐

