{"id":370298,"date":"2024-05-21T04:22:02","date_gmt":"2024-05-21T04:22:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=370298"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=370298","title":{"rendered":"<span>\u041f\u043e \u0433\u0440\u0430\u0431\u043b\u044f\u043c, \u043f\u043e \u0433\u0440\u0430\u0431\u043b\u044f\u043c. \u041f\u0438\u0448\u0435\u043c \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0438\u0434\u0436\u0435\u0442 IOS 17<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" width=\"760\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ql\/2d\/uu\/ql2duu-la0mvblcl9ouzehmsv7q.png\" alt=\"image\" data-src=\"https:\/\/habrastorage.org\/webt\/ql\/2d\/uu\/ql2duu-la0mvblcl9ouzehmsv7q.png\"\/><\/p>\n<p>  \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0410\u043d\u043d\u0430 \u0416\u0430\u0440\u043a\u043e\u0432\u0430, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u0433\u0440\u0443\u043f\u043f\u044b \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Usetech. \u0412 2023 \u0433\u043e\u0434\u0443 \u043d\u0430 WWDC Apple \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e API, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b\u0438 \u0434\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b, \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 AppIntent \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0449\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u043d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u043a\u0430\u043a Apple \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u044f\u0445, \u0430 \u043e\u0442 \u0431\u0435\u0442\u044b \u0434\u043e \u0440\u0435\u043b\u0438\u0437\u0430 \u0447\u0442\u043e-\u0442\u043e \u0432 API \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. <\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c, \u043a\u0430\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Widget Kit iOS 17 \u0438 AppIntent \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c, \u043d\u043e \u0438 \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u0438 \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u044b\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0435, \u0438 \u043e\u0431\u043e\u0439\u0442\u0438 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u0443\u0448\u043a\u0438, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 API. \u0420\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0442\u043e\u043a TODO.<\/p>\n<p>  <img decoding=\"async\" width=\"760\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y1\/rp\/eh\/y1rpehyfrhbmg9ps6qq4fvyuqns.png\" data-src=\"https:\/\/habrastorage.org\/webt\/y1\/rp\/eh\/y1rpehyfrhbmg9ps6qq4fvyuqns.png\"\/><\/p>\n<p>  <a href=\"https:\/\/github.com\/anioutkazharkova\/todo_widget_sample\">\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0435 \u0442\u0435\u0440\u043f\u0438\u0442\u0441\u044f, \u0438\u043b\u0438 \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0441\u0430\u043c \u043a\u043e\u0434<\/a><\/p>\n<p>  \u041f\u043e\u043c\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0432 \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0442\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u043c\u0438 \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c \u0438 \u0437\u0430\u0434\u0435\u0440\u0436\u0435\u043a. \u0414\u0430\u043d\u043d\u044b\u0435 (\u043d\u0430\u0448\u0438 \u0442\u0443\u0434\u0443\u0448\u043a\u0438 \u0438 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435) \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 SwiftData. \u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0430 WWDC 2023, \u0438 \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u0442\u043e\u0436\u0435 \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439. <br \/>  <a name=\"habracut\"><\/a><br \/>  \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432 \u043d\u0430\u0447\u0430\u043b\u0435. \u041d\u0430\u0448\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443 \u043d\u0430\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u043d\u0430 SwiftUI:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 View<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"swift\">struct ListContentView: View {    @Query var items: [TodoItem]          var body: some View {         NavigationView {             List {                 ForEach(tems) { item in                     Label(item.taskName , systemImage: \"circle\\(item.isCompleted ? \".fill\" : \"\")\")                         .frame(maxWidth: .infinity, alignment: .leading).contentShape(Rectangle())                         .onTapGesture {                             withAnimation {                                 item.isCompleted = !item.isCompleted                      \/\/\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435                             }                         }                 }.onDelete {index in                   \/\/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435                     deleteItems(offsets: index)                 }             }             .navigationTitle(\"TODO\")             .navigationBarItems(trailing: Button(action: addItem, label: {               \/\/\/ \u041f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043d\u0430 \u044d\u0442\u0443 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c                 Image(systemName: \"plus\")             }))         }     } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  <b>\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0430 SwiftData<\/b><br \/>  \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0431\u0435\u0440\u0435\u043c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0440\u043e\u0441\u0430 <b><a href=\"https:\/\/habr.com\/ru\/users\/query\/\" class=\"user_link\">Query<\/a><\/b>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <b>SwiftData<\/b>. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 TodoDataManager: <\/p>\n<pre><code class=\"swift\">class TodoDataManager {     static var sharedModelContainer: ModelContainer = {do {             return try ModelContainer(for: TodoItem.self)         } catch {             fatalError(\"Could not create ModelContainer: \\(error)\")         }     }()  \/\/ \u0422\u0443\u0442 \u043c\u0435\u0442\u043e\u0434\u044b } <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e TodoDataManager:<\/p>\n<pre><code class=\"swift\">@main struct TodoAppApp: App {     var sharedModelContainer: ModelContainer = TodoDataManager.sharedModelContainer      var body: some Scene {         WindowGroup {             ListContentView()         }         .modelContainer(sharedModelContainer)     } }<\/code><\/pre>\n<p>  \u0421\u0430\u043c\u0430 \u0436\u0435 \u043c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439: \u0438\u043c\u044f \u0437\u0430\u0434\u0430\u0447\u0438, \u0444\u043b\u0430\u0433 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0434\u0430\u0442\u0430.<\/p>\n<pre><code class=\"swift\">@Model class TodoItem: Identifiable {     var id: UUID     var taskName: String     var startDate: Date     var isCompleted: Bool = false          init(task: String, startDate: Date) {         id = UUID()         taskName = task         self.startDate = startDate     } } <\/code><\/pre>\n<p>  \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430:<\/p>\n<pre><code class=\"swift\">    @MainActor     func addItem(name: String) {        withAnimation {         let newItem = TodoItem(task: name, startDate: Date())         TodoDataManager.sharedModelContext.insert(newItem)     }     } <\/code><\/pre>\n<p>  \u041f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e, \u0441\u0430\u043c\u043e\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/p>\n<p>  <b>\u041f\u0438\u0448\u0435\u043c \u0432\u0438\u0434\u0436\u0435\u0442<\/b><br \/>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0432\u0438\u0434\u0436\u0435\u0442\u0443:<\/p>\n<p>  <img decoding=\"async\" width=\"500\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/nv\/5k\/vr\/nv5kvrkjl32b00r2idseanwoy6k.png\" data-src=\"https:\/\/habrastorage.org\/webt\/nv\/5k\/vr\/nv5kvrkjl32b00r2idseanwoy6k.png\"\/><\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0442\u0430\u0440\u0433\u0435\u0442 <b> New Target \u2014 Widget Extensions<\/b>. \u0423 \u043d\u0430\u0441 \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 Widget<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"swift\">struct TodoAppWidget: Widget {     let kind: String = \"TodoAppWidget\"      var body: some WidgetConfiguration {         AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in             TodoAppWidgetView(entry: entry)                 .containerBackground(for: .widget) {                     BackgroundView()                 }         }.supportedFamilies([.systemSmall, .systemLarge])     } } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u042d\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0438\u043f\u0430 Widget \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0432\u0438\u0434\u0436\u0435\u0442\u0430, \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0435\u0433\u043e UI \u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 (Provider).<\/p>\n<p>  \u0417\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e View \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 TodoAppWidgetView. <\/p>\n<p>  \u0417\u0430\u043c\u0435\u043d\u0438\u043c UI View \u0432\u0438\u0434\u0436\u0435\u0442\u0430:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">TodoAppWidgetView<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"swift\">import WidgetKit  struct TodoAppWidgetView : View {     var entry: Provider.Entry      var body: some View {         VStack(alignment: .leading) {             HStack(alignment: .center, content: {                 Text(\"Notes\").foregroundStyle(.white)                 Spacer()                 Text(\"\\(entry.uncompleted)\/\\(entry.total)\").foregroundStyle(.white)             }).frame(height: 40)             ForEach(entry.data.indices) { index in                     Label(entry.data[index].taskName , systemImage: \"circle\\(entry.data[index].isCompleted ? \".fill\" : \"\")\")                         .frame(maxWidth: .infinity, alignment: .leading)                          }             Spacer()             HStack(alignment: .bottom, content: {                 Text(\"Add task +\").foregroundColor(.gray)             }).frame(height: 40)         }     } } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0412\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f @PropertyWrapper. \u0414\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u043e View \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c Entry \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 <b>Provider<\/b>. \u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <b>TimelineEntry<\/b>:<\/p>\n<pre><code class=\"swift\">struct SimpleEntry: TimelineEntry {     let date: Date     let data: [TodoItem]     var completed: Int {         return data.filter{             $0.isCompleted         }.count     }     var total: Int {         return data.count     } } <\/code><\/pre>\n<p>  \u041d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0443\u0434\u0443\u0448\u0435\u043a, \u0447\u0438\u0441\u043b\u043e \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438 \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044b\u0445. \u0427\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0442\u0443 \u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432\u0441\u0435\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <img decoding=\"async\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kr\/z1\/np\/krz1np4jwg2cquic1siasgbil94.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kr\/z1\/np\/krz1np4jwg2cquic1siasgbil94.png\"\/><\/p>\n<p>  \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432\u0441\u0435\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u043e\u0432 \u0434\u043b\u044f TodoDataManager. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u0432\u0438\u0434\u0436\u0435\u0442\u0430<\/p>\n<p>  <b>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0438 \u0448\u0430\u0440\u0438\u043d\u0433 SwiftData<\/b><br \/>  \u0421\u0430\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043d\u0430\u0431\u043e\u0440 \u0441\u043d\u0435\u043f\u0448\u043e\u0442\u043e\u0432 \u043d\u0430\u0448\u0435\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0445 \u043f\u043e \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u0443 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043a\u0438. \u0412 iOS 17 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <b>AppIntentTimelineProvider<\/b> \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 async\/await:<\/p>\n<pre><code class=\"swift\">struct Provider: AppIntentTimelineProvider {  \/\/...      func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry {         let items = await loadData()         return SimpleEntry(date: Date(), data: items)     }          func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> Timeline&lt;SimpleEntry> {         var entries: [SimpleEntry] = []         let entryDate = Date()         let items = await loadData() \/\/&lt;-- \u0432\u043e\u0442 \u0442\u0443\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0438\u0437 TodoDataManager         let entry = SimpleEntry(date: entryDate, data: items)         \/\/20 \u043f\u043e\u0442\u043e\u043c \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430 60         return Timeline(entries: [entry], policy: .after(.now.addingTimeInterval(20)))     } }<\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 loadData \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 TodoDataManager \u0447\u0435\u0440\u0435\u0437 fetch, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f sharedModelContainer \u0438 \u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<pre><code class=\"swift\">\/\/Widget @MainActor     func loadData()->[TodoItem] {         return TodoDataManager.shared.loadItems()     }  \/\/TodoDataManager @MainActor     func loadItems(_ count: Int? = nil)->[TodoItem] {        return (try? TodoDataManager.sharedModelContainer.mainContext                           .fetch(FetchDescriptor&lt;TodoItem>())) ?? []     } <\/code><\/pre>\n<p>  \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c `@Query`\u043f\u0440\u044f\u043c\u043e \u0432 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0435? \u041e\u0442\u0432\u0435\u0442: \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<p>  \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0443 \u0437\u0430\u043f\u0438\u0441\u0435\u0439: <\/p>\n<p>  <img decoding=\"async\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/1h\/xk\/cf\/1hxkcfrmcgcdfcldckmus0w075g.png\" data-src=\"https:\/\/habrastorage.org\/webt\/1h\/xk\/cf\/1hxkcfrmcgcdfcldckmus0w075g.png\"\/> <\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e, \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043d\u0430\u0448 \u0432\u0438\u0434\u0436\u0435\u0442. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0443 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0441\u0448\u0430\u0440\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <b>AppGroups <\/b> \u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438 \u0442\u0430\u0440\u0433\u0435\u0442\u0443 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<p>  <img decoding=\"async\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/8e\/qx\/cm\/8eqxcmr6xion-7o1cgiq8r9bonm.png\" data-src=\"https:\/\/habrastorage.org\/webt\/8e\/qx\/cm\/8eqxcmr6xion-7o1cgiq8r9bonm.png\"\/><\/p>\n<p>  \u0423\u043a\u0430\u0436\u0435\u043c \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443 \u0436\u0435 \u0433\u0440\u0443\u043f\u043f\u0443:<\/p>\n<p>  <img decoding=\"async\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ab\/fs\/mj\/abfsmjw_23w7yo1pblbnu0zrwjy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ab\/fs\/mj\/abfsmjw_23w7yo1pblbnu0zrwjy.png\"\/><\/p>\n<p>  \u0413\u0440\u0443\u043f\u043f\u0430 \u0437\u0430\u0434\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 url \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u0414\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0433\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u0441 \u044d\u043a\u0440\u0430\u043d\u044b \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439:<\/p>\n<p>  <img decoding=\"async\" width=\"300\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/re\/17\/4h\/re174hk7grp6jmdwpkocfqn9je8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/re\/17\/4h\/re174hk7grp6jmdwpkocfqn9je8.png\"\/><\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u0430\u043d\u043d\u044b\u043c, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u043c \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<p>  <b>\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0443<\/b><br \/>  \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u043c, \u043d\u0430\u0448 \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u043e\u0442\u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438 \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. <\/p>\n<p>  \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u0430. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0435 \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u0430:<\/p>\n<pre><code class=\"swift\">Timeline(entries: [entry], policy: .after(.now.addingTimeInterval(60))) <\/code><\/pre>\n<p>  <b>\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f\u043c\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u043c\u0438\u043d\u0443\u0442\u044b, \u0438\u043d\u0430\u0447\u0435 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/b> \u0414\u043b\u044f \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432, \u043f\u043b\u0435\u0435\u0440\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0435 \u0441\u0435\u0433\u043e\u0434\u043d\u044f.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043d\u0430\u0448\u0435\u043c TodoDataManager \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u044b\u0437\u043e\u0432 <b>WidgetCenter.shared.reloadAllTimelines()<\/b> \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0441\u0435\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u043b\u0438\u0431\u043e <b>reloadTimelines(of: Kind) <\/b>\u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c Kind:<\/p>\n<pre><code class=\"swift\"> @MainActor     func addItem(name: String) {         \/\/ \u043a\u043e\u0434         WidgetCenter.shared.reloadAllTimelines()     }          @MainActor     func deleteItem(offsets: IndexSet) {         \/\/\u043a\u043e\u0434         WidgetCenter.shared.reloadAllTimelines()     }      @MainActor     func updateItem(index: Int) {         let items = loadItems()         let checked = items[index].isCompleted         items[index].isCompleted = !checked         WidgetCenter.shared.reloadAllTimelines()     } <\/code><\/pre>\n<p>  <b>\u0415\u0434\u0438\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/b><\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439:<\/p>\n<pre><code class=\"swift\"> static var sharedModelContainer: ModelContainer = {         let schema = Schema([             TodoItem.self,         ])         let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)          do {             return try ModelContainer(for: schema, configurations: [modelConfiguration])         } catch {             fatalError(\"Could not create ModelContainer: \\(error)\")         }     }()  \/\/\u0422\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442     static var sharedModelContext = ModelContext(sharedModelContainer) <\/code><\/pre>\n<p>  \u041d\u0430\u0448 \u0432\u0438\u0434\u0436\u0435\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043c\u043e\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e.<br \/>  <b>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u044b \u043f\u043e\u043c\u0435\u0442\u0438\u043b\u0438 @MainActor \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. <\/b><\/p>\n<p>  <b>\u0414\u0435\u043b\u0430\u0435\u043c \u0432\u0438\u0434\u0436\u0435\u0442 \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u043c<\/b><br \/>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u0430\u043a\u0446\u0438\u044e \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u0438\u0434\u0436\u0435\u0442\u0430. \u0412 ios 17 \u0432 WidgetKit \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <b>AppIntent <\/b>\u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0442 \u043a\u043d\u043e\u043f\u043e\u043a \u0438 \u0442\u043e\u0433\u0433\u043b\u043e\u0432 \u0438 \u0432\u044b\u0437\u043e\u0432\u0430 \u043b\u043e\u0433\u0438\u043a\u0438. \u0415\u0441\u0442\u044c \u0446\u0435\u043b\u044b\u0439 \u0440\u044f\u0434 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 AppIntent, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0432 \u0441\u0435\u0431\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.<\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u043d\u0442:<\/p>\n<pre><code class=\"swift\">struct CheckTodoIntent: AppIntent {     @Parameter(title: \"Index\")     var index: Int          init(index: Int) {         self.index = index     }          func perform() async throws -> some IntentResult {       \/\/\u0412\u044b\u0437\u043e\u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443         await TodoDataManager.shared.updateItem(index: index)         return .result()     } } <\/code><\/pre>\n<p>  \u041c\u044b \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u0443\u0436\u043d\u043e\u0435 \u043d\u0430\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u044b \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u043c <a href=\"https:\/\/habr.com\/ru\/users\/parameter\/\" class=\"user_link\">Parameter<\/a> \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043a\u043b\u044e\u0447\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0434\u0435\u043a\u0441 (\u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440) \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0432\u0438\u0434\u0436\u0435\u0442\u0435. <\/p>\n<p>  \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 perform \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 TodoDataManager. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430\u0448\u0438 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code class=\"swift\"> ForEach(entry.data.indices) { index in               \/\/\u0412\u043e\u0442 \u0441\u044e\u0434\u0430 \u043c\u044b \u0438\u043d\u0434\u0435\u043a\u0441 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c                 Button(intent: CheckTodoIntent(index: index)) {                     Label(entry.data[index].taskName , systemImage: \"circle\\(entry.data[index].isCompleted ? \".fill\" : \"\")\")                         .frame(maxWidth: .infinity, alignment: .leading)                 }                  } <\/code><\/pre>\n<p>  <b>SwiftData \u0438 foreground\/background<\/b><br \/>  \u041e\u0434\u043d\u0430\u043a\u043e, \u0437\u0430\u0434\u0430\u0447\u0443 \u0448\u0430\u0440\u0438\u043d\u0433\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0435 \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u0438\u0437 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0414\u0435\u043b\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c:<\/p>\n<p>  1. `@Query` \u0443 \u043d\u0430\u0441 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 Foreground. \u0418 \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u043d \u0431\u0430\u0433\u043e\u0432\u0430\u043d\u043d\u044b\u0439.<\/p>\n<p>  2. SwiftData mainContext \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 foreground. \u0412\u0438\u0434\u0436\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0438\u0437 foreground, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0438\u0437 background. \u041d\u0443\u0436\u0435\u043d \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0444\u043e\u043d\u043e\u0432\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p>  3. \u0412 \u0432\u0438\u0434\u0436\u0435\u0442\u0435 \u043c\u043e\u0436\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0441\u0441\u0438\u043d\u0445\u0440\u043e\u043d \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. <\/p>\n<p>  <img decoding=\"async\" width=\"760\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rb\/lc\/-p\/rblc-pq1bffetng_to-0g6meyno.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rb\/lc\/-p\/rblc-pq1bffetng_to-0g6meyno.png\"\/><br \/>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442. \u041d\u0435 \u043f\u0443\u0442\u0430\u0439\u0442\u0435 \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u0444\u043e\u043d\u043e\u0432\u0443\u044e \u0442\u0430\u0441\u043a\u0443. \u0420\u0435\u0447\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439.<\/p>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 background-\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443-\u0430\u043a\u0442\u043e\u0440:<\/p>\n<pre><code class=\"swift\">@ModelActor actor SwiftDataModelActor {          func loadData() -> [TodoItem] {         let data = (try? modelExecutor.modelContext.fetch(FetchDescriptor&lt;TodoItem>())) ??                   [TodoItem]()         return data     } } <\/code><\/pre>\n<p>  \u041c\u0430\u043a\u0440\u043e\u0441 <b>ModelActor<\/b> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 modelExecutor, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u0434\u0430\u0441\u0442 \u043d\u0430\u043c \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0434\u0435\u043b\u0438. \u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 fetch \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<p>  \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:<\/p>\n<pre><code class=\"swift\"> @MainActor     func reloadItems() async -> [TodoItem] {             let actor = SwiftDataModelActor(modelContainer: TodoDataManager.sharedModelContainer)             return await actor.loadData()     } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435. \u0423\u0431\u0438\u0440\u0430\u0435\u043c `@Query`, \u0441\u043e\u0437\u0434\u0430\u0435\u043c ObservableObject \u0438 \u043a\u0440\u0435\u043f\u0438\u043c \u043a \u043d\u0430\u0448\u0435\u043c\u0443 View \u043a\u0430\u043a ObservedObject. \u0412 \u043d\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0435\u043c 2 \u043c\u0435\u0442\u043e\u0434\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0444\u043e\u043d\u0435 \u0438 \u0432 main \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\u0445:<\/p>\n<pre><code class=\"swift\">@MainActor     func loadItems(){         Task.detached {             let actor = SwiftDataModelActor(modelContainer: TodoDataManager.sharedModelContainer)             await self.save(items: await actor.loadData())         }     }          @MainActor     func save(items: [TodoItem]) {         self.items = items     }         @MainActor     func reloadItems() {         self.items = TodoDataManager.shared.loadItems()     } <\/code><\/pre>\n<p>  \u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0444\u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 onChange:<\/p>\n<pre><code class=\"swift\">.onChange(of: phase) { oldValue, newValue in             if oldValue == .background {                 model.loadItems()             } <\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 reloadItems \u0441 mainContext \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0444\u043e\u0440\u0433\u0440\u0430\u0443\u043d\u0434\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<p>  \u041c\u044b \u0443\u0431\u0440\u0430\u043b\u0438 `@Query`, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b UpdateListener, \u0438 \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430, \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c TodoDataManager \u0441 \u043d\u0430\u0448\u0435\u0439 ViewModel:<\/p>\n<pre><code class=\"swift\">protocol UpdateListener {     func loadItems()          func reloadItems() }  \/\/TodoDataManager @MainActor     func addItem(name: String) {         let newItem = TodoItem(task: name, startDate: Date())         TodoDataManager.sharedModelContext.insert(newItem)         listeners.forEach { listener in             listener.reload()         }         WidgetCenter.shared.reloadAllTimelines()     } <\/code><\/pre>\n<p>  \u041d\u0430\u0434\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<pre><code class=\"swift\">.onTapGesture {        withAnimation {            item.isCompleted = !item.isCompleted           TodoDataManager.shared.updateItem(index: model.items.firstIndex(of: item) ?? 0)               }       } <\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c:<\/p>\n<p>  <img decoding=\"async\" width=\"360\" src=\"https:\/\/habrastorage.org\/webt\/4y\/d0\/9p\/4yd09pheaufajhfa-y58lsa9-hw.gif\" data-src=\"https:\/\/habrastorage.org\/webt\/4y\/d0\/9p\/4yd09pheaufajhfa-y58lsa9-hw.gif\"\/><\/p>\n<p>  <a href=\"https:\/\/github.com\/anioutkazharkova\/todo_widget_sample\">\u041a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<p>  \u0420\u0435\u0437\u044e\u043c\u0438\u0440\u0443\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438:<\/p>\n<p>  1. \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 AppGroups \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u0443<br \/>  2. \u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u0435\u0434\u0438\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c<br \/>  3. \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 AppIntent \u0432 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<br \/>  4. \u0418\u0437 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432\u0438\u0434\u0436\u0435\u0442\u0430.<br \/>  5. \u0420\u0435\u0448\u0438\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0432 \u0444\u043e\u043d\u0435 \u0434\u043b\u044f SwiftData <br \/>  Profit!<\/p>\n<p>  <b>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0438\u0442\u043e\u0433\u0435: <\/b><br \/>  \u0425\u043e\u0442\u044f \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0438 \u0434\u043b\u044f \u0448\u0430\u0440\u0438\u043d\u0433\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439, \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0445 \u043d\u044e\u0430\u043d\u0441\u043e\u0432. \u0412\u0441\u0435-\u0442\u0430\u043a\u0438 \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043d\u0438\u0447\u0435\u0433\u043e, \u043c\u043e\u0436\u0435\u0442, \u043a \u0432\u0435\u0440\u0441\u0438\u0438 iOS 18 \u044d\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u044f\u0442. \u041b\u0438\u0431\u043e \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u043d\u0430\u043c \u043d\u043e\u0432\u044b\u0439 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b.<\/p>\n<p>  \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043b\u0435\u0435\u0440\u043e\u043c \u0438 \u043e\u0441\u043e\u0431\u044b\u043c\u0438 AppIntent. <\/p>\n<p>  \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<p>  <a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2023\/10028\">developer.apple.com\/videos\/play\/wwdc2023\/10028<\/a><br \/>  <a href=\"https:\/\/developer.apple.com\/documentation\/widgetkit\/adding-interactivity-to-widgets-and-live-activities\">developer.apple.com\/documentation\/widgetkit\/adding-interactivity-to-widgets-and-live-activities<\/a><br \/>  <a href=\"https:\/\/developer.apple.com\/documentation\/swiftdata\/modelactor\">developer.apple.com\/documentation\/swiftdata\/modelactor<\/a><\/p>\n<p>  <a href=\"https:\/\/github.com\/anioutkazharkova\/todo_widget_sample\">\u0421\u0430\u043c \u043a\u043e\u0434<\/a><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/798925\/\"> https:\/\/habr.com\/ru\/articles\/798925\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" width=\"760\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ql\/2d\/uu\/ql2duu-la0mvblcl9ouzehmsv7q.png\" alt=\"image\" data-src=\"https:\/\/habrastorage.org\/webt\/ql\/2d\/uu\/ql2duu-la0mvblcl9ouzehmsv7q.png\"\/><\/p>\n<p>  \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0410\u043d\u043d\u0430 \u0416\u0430\u0440\u043a\u043e\u0432\u0430, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u0433\u0440\u0443\u043f\u043f\u044b \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Usetech. \u0412 2023 \u0433\u043e\u0434\u0443 \u043d\u0430 WWDC Apple \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e API, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b\u0438 \u0434\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b, \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 AppIntent \u043d\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0449\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u043d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u043a\u0430\u043a Apple \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u044f\u0445, \u0430 \u043e\u0442 \u0431\u0435\u0442\u044b \u0434\u043e \u0440\u0435\u043b\u0438\u0437\u0430 \u0447\u0442\u043e-\u0442\u043e \u0432 API \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. <\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c, \u043a\u0430\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Widget Kit iOS 17 \u0438 AppIntent \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c, \u043d\u043e \u0438 \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u0438 \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u044b\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442\u0435, \u0438 \u043e\u0431\u043e\u0439\u0442\u0438 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u0443\u0448\u043a\u0438, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 API. \u0420\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0442\u043e\u043a TODO.<\/p>\n<p>  <img decoding=\"async\" width=\"760\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/y1\/rp\/eh\/y1rpehyfrhbmg9ps6qq4fvyuqns.png\" data-src=\"https:\/\/habrastorage.org\/webt\/y1\/rp\/eh\/y1rpehyfrhbmg9ps6qq4fvyuqns.png\"\/><\/p>\n<p>  <a href=\"https:\/\/github.com\/anioutkazharkova\/todo_widget_sample\">\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0435 \u0442\u0435\u0440\u043f\u0438\u0442\u0441\u044f, \u0438\u043b\u0438 \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0441\u0430\u043c \u043a\u043e\u0434<\/a><\/p>\n<p>  \u041f\u043e\u043c\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0432 \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0442\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u043c\u0438 \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c \u0438 \u0437\u0430\u0434\u0435\u0440\u0436\u0435\u043a. \u0414\u0430\u043d\u043d\u044b\u0435 (\u043d\u0430\u0448\u0438 \u0442\u0443\u0434\u0443\u0448\u043a\u0438 \u0438 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435) \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 SwiftData. \u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0430 WWDC 2023, \u0438 \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0430\u0440\u0433\u0435\u0442\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u0442\u043e\u0436\u0435 \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439.   <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-370298","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=370298"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370298\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=370298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=370298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=370298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}