{"id":51217,"date":"2026-03-11T16:20:35","date_gmt":"2026-03-11T20:20:35","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=51217"},"modified":"2026-03-19T11:25:01","modified_gmt":"2026-03-19T15:25:01","slug":"coredataevolution","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2026\/03\/11\/coredataevolution\/","title":{"rendered":"CoreDataEvolution"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/fatbobman\/CoreDataEvolution\">Fatbobman<\/a> (<a href=\"https:\/\/mastodon.social\/@fatbobman\/116173553595030634\">Mastoson<\/a>):<\/p>\n<blockquote cite=\"https:\/\/github.com\/fatbobman\/CoreDataEvolution\">\n<p>This library is designed to simplify and enhance Core Data&rsquo;s handling of multithreading, drawing inspiration from SwiftData&rsquo;s <code>@ModelActor<\/code> feature, enabling efficient, safe, and scalable operations.<\/p>\n<p>[&#8230;]<\/p>\n<ul><li><p><strong>Custom Executors for Core Data Actors<\/strong><br\/>\nCoreDataEvolution provides custom executors that ensure all operations on managed objects are performed on the appropriate thread associated with their managed object context. It uses a <code>UnownedJob<\/code>-based serial executor path compatible with the minimum supported OS versions.<\/p>\n<\/li>\n<li>\n<p><strong>@NSModelActor Macro<\/strong><br\/>\nThe <code>@NSModelActor<\/code> macro simplifies Core Data concurrency, mirroring SwiftData&rsquo;s <code>@ModelActor<\/code> macro. It generates the necessary boilerplate code to manage a Core Data stack within an actor, ensuring safe and efficient access to managed objects.<\/p>\n<\/li>\n<li>\n<p><strong>NSMainModelActor Macro<\/strong><br\/>\n<code>NSMainModelActor<\/code> is the main-thread companion macro for classes. It binds <code>modelContext<\/code> to <code>viewContext<\/code> and provides the same convenience access APIs (<code>subscript<\/code>, <code>withContext<\/code>) through <code>NSMainModelActor<\/code> protocol extensions.<\/p>\n<\/li>\n<li>\n<p><strong>Elegant Actor-based Concurrency<\/strong><br\/>\nCoreDataEvolution allows you to create actors with custom executors tied to Core Data contexts, ensuring that all operations within the actor are executed serially on the context&rsquo;s thread.<\/p><\/li><\/ul>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/08\/05\/macos-tahoe-26-developer-beta-5\/\">macOS Tahoe 26 Developer Beta 5<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/04\/23\/elegant-concurrency-operations-in-core-data\/\">Elegant Concurrency Operations in Core Data<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/10\/02\/model-for-coredata\/\">@Model for CoreData<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/12\/02\/generating-core-data-swift\/\">Generating Core Data Swift<\/a><\/li>\n<\/ul>\n\n<p id=\"coredataevolution-update-2026-03-19\">Update (<a href=\"#coredataevolution-update-2026-03-19\">2026-03-19<\/a>): <a href=\"https:\/\/fatbobman.com\/en\/posts\/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift\/\">Fatbobman<\/a>:<\/p>\n<blockquote cite=\"https:\/\/fatbobman.com\/en\/posts\/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift\/\">\n<p>More precisely, it&rsquo;s my own answer to these disconnects: If I still value Core Data&rsquo;s object graph model, its migration system, and its mature runtime capabilities, can I make it continue to exist in modern Swift projects in a more natural way?<\/p>\n<p>[&#8230;]<\/p>\n<p>But in the era of cloud sync, Core Data projects often encounter two other very real needs: how to handle continuously changing transaction histories, and how to monitor iCloud \/ CloudKit&rsquo;s operational status.<\/p>\n<p>To that end, I&rsquo;ve also built two complementary tools: <a href=\"https:\/\/github.com\/fatbobman\/PersistentHistoryTrackingKit?utm_source=Fatbobman%20Blog&amp;utm_medium=web\">PersistentHistoryTrackingKit<\/a> and <a href=\"https:\/\/github.com\/fatbobman\/iCloudSyncStatusKit?utm_source=Fatbobman%20Blog&amp;utm_medium=web\">iCloudSyncStatusKit<\/a>.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Fatbobman (Mastoson): This library is designed to simplify and enhance Core Data&rsquo;s handling of multithreading, drawing inspiration from SwiftData&rsquo;s @ModelActor feature, enabling efficient, safe, and scalable operations. [&#8230;] Custom Executors for Core Data Actors CoreDataEvolution provides custom executors that ensure all operations on managed objects are performed on the appropriate thread associated with their managed [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2026-03-11T20:20:39Z","apple_news_api_id":"5c0d9899-5dd8-4591-a523-65360d9a4516","apple_news_api_modified_at":"2026-03-19T15:25:04Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AXA2YmV3YRZGlI2U2DZpFFg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[109,2741,30,2742,941,74,71,2200,901],"class_list":["post-51217","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-coredata","tag-ios-26","tag-mac","tag-macos-tahoe-26","tag-macros","tag-opensource","tag-programming","tag-swift-concurrency","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=51217"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51217\/revisions"}],"predecessor-version":[{"id":51302,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51217\/revisions\/51302"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=51217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=51217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=51217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}