{"id":50503,"date":"2025-12-18T15:49:19","date_gmt":"2025-12-18T20:49:19","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=50503"},"modified":"2025-12-18T15:49:19","modified_gmt":"2025-12-18T20:49:19","slug":"batch-delete-in-swiftdata","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2025\/12\/18\/batch-delete-in-swiftdata\/","title":{"rendered":"Batch Delete in SwiftData"},"content":{"rendered":"<p><a href=\"https:\/\/fatbobman.com\/en\/snippet\/how-to-batch-delete-data-in-swiftdata\/\">Fatbobman<\/a>:<\/p>\n<blockquote cite=\"https:\/\/fatbobman.com\/en\/snippet\/how-to-batch-delete-data-in-swiftdata\/\">\n<p>SwiftData provides a batch deletion API that is more modern and type-safe than its Core Data counterpart.<\/p>\n<p>[&#8230;]<\/p>\n<p>Note: Unlike the standard single-object deletion <code>modelContext.delete(_ model: T)<\/code>, batch deletion is only applied to the database after <code>save()<\/code> is executed.<\/p>\n<\/blockquote>\n\n<p>Coming from Core Data, this is really strange. With Core Data, <code>NSBatchUpdateRequest<\/code> and the other batch operations are completely separate from saving the context. This makes sense because they operate directly on the database rather than on the in-memory objects that are owned by the context.<\/p>\n\n<p>I&rsquo;m trying to wrap my head around what SwiftData is even doing that batch deletions happen on save. Is it queuing up a bunch of SQL to be executed along with the save? Why would anyone want this?<\/p>\n\n<p>Going by what the documentation literally says, with it taking place <em>after<\/em> the save, it sounds like it even <em>reorders<\/em> operations. If I do a batch delete, then insert some objects, then save, will it delete the new objects (if they match the predicate) even though I intended the insert to happen after clearing out the old objects? Or does executing the batch delete eagerly fetch the IDs of the objects to be deleted and then it deletes them by ID later (when the predicate might no longer match)?<\/p>\n\n<p>Either way, it seems confusing in the event that there are multiple batch deletes in sequence. The first one might affect which objects match the predicate of the second one.<\/p>\n\n<blockquote cite=\"https:\/\/fatbobman.com\/en\/snippet\/how-to-batch-delete-data-in-swiftdata\/\">\n<p>Although Swift 6 and iOS 26 have brought many improvements, as of now, SwiftData natively supports <strong>only batch deletion<\/strong>. It does not yet provide native APIs for Batch Update or Batch Insert.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/12\/15\/entity-inheritance-slowdowns\/\">Entity Inheritance Slowdowns<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2018\/10\/01\/ios-12-and-core-data-external-binary-data-storage\/\">iOS 12 and Core Data External Binary Data Storage<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/10\/07\/core-data-in-el-capitan\/\">Core Data in El Capitan<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/06\/09\/wwdc-2015-links\/\">WWDC 2015 Links<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Fatbobman: SwiftData provides a batch deletion API that is more modern and type-safe than its Core Data counterpart. [&#8230;] Note: Unlike the standard single-object deletion modelContext.delete(_ model: T), batch deletion is only applied to the database after save() is executed. Coming from Core Data, this is really strange. With Core Data, NSBatchUpdateRequest and the other [&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":"2025-12-18T20:49:22Z","apple_news_api_id":"d9501dda-a041-45a4-9d53-366b9faf7661","apple_news_api_modified_at":"2025-12-18T20:49:22Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/A2VAd2qBBRaSdUzZrn692YQ","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,31,2741,30,2742,71,2404],"class_list":["post-50503","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-coredata","tag-ios","tag-ios-26","tag-mac","tag-macos-tahoe-26","tag-programming","tag-swiftdata"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/50503","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=50503"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/50503\/revisions"}],"predecessor-version":[{"id":50504,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/50503\/revisions\/50504"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=50503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=50503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=50503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}