{"id":44105,"date":"2024-07-16T14:49:30","date_gmt":"2024-07-16T18:49:30","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=44105"},"modified":"2024-07-17T14:31:08","modified_gmt":"2024-07-17T18:31:08","slug":"nscopyobject-the-griefer-that-keeps-on-griefing","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2024\/07\/16\/nscopyobject-the-griefer-that-keeps-on-griefing\/","title":{"rendered":"NSCopyObject, the Griefer That Keeps on Griefing"},"content":{"rendered":"<p><a href=\"https:\/\/wadetregaskis.com\/nscopyobject-the-griefer-that-keeps-on-griefing\/\">Wade Tregaskis<\/a>:<\/p>\n<blockquote cite=\"https:\/\/wadetregaskis.com\/nscopyobject-the-griefer-that-keeps-on-griefing\/\"><p>Almost nobody <em>intentionally<\/em> uses <code>NSCopyObject<\/code>, but your superclass might, and therefore you might.<\/p><p>[&#8230;]<\/p><p><a href=\"https:\/\/wiki.herzbube.ch\/index.php\/LearningObjectiveC#Object_copy\">Some<\/a><a href=\"https:\/\/robnapier.net\/implementing-nscopying\">guides<\/a> specify a better method, which is to manually zero out the copied object&rsquo;s ivars and then repopulate them via formal property setters.  That actually works with or without ARC, although it may break &#x2013; causing memory leaks &#x2013; if the superclass ever stops using <code>NSCopyObject<\/code> (or if <code>NSCopyObject<\/code> ever gets upgraded to understand reference-counted ivars that it currently does not).  It&rsquo;s also only possible in Objective-C because Swift doesn&rsquo;t provide direct access to instance variables.<\/p><p>[&#8230;]<\/p><p>It appears that the best you can do [in Swift] is <em>assume<\/em> the superclass will always use <code>NSCopyObject<\/code>, if it does currently, and just manually increment the retain count.  Like Objective-C with ARC, the language &amp; standard library really don&rsquo;t want you to actually do this, but at least in Swift it&rsquo;s relatively straightforward[&#8230;]<\/p><p>[&#8230;]<\/p><p>And yet, Apple <em>still<\/em> use <code>NSCopyObject<\/code> themselves <em>to this very day<\/em>, in their own applications and frameworks &#x2013; including major frameworks like AppKit that almost all 3rd party developers rely on.  <code>NSCell<\/code> is <em>still<\/em> broken, three decades later, as is <code>NSImage<\/code> &amp; <code>NSImageRep<\/code>, and <code>NSAnimation<\/code>.  Most of those are <em>explicitly designed to be subclassed<\/em>, despite Apple&rsquo;s own very clear instructions to never mix subclassing with <code>NSCopyObject<\/code>.<\/p><\/blockquote>\n<p>Maybe Apple doesn&rsquo;t want to dig into that old code and possibly break apps. However, with recent major changes to <code>NSView<\/code>, perhaps it&rsquo;s not entirely off the table.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/07\/15\/nscopying-in-a-swift-world\/\">NSCopying in a Swift World<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/06\/28\/view-clipping-changes-in-macos-14\/\">View Clipping Changes in macOS 14<\/a><\/li>\n<\/ul>\n\n<p id=\"nscopyobject-the-griefer-that-keeps-on-griefing-update-2024-07-17\">Update (2024-07-17): See also: <a href=\"https:\/\/news.ycombinator.com\/item?id=40976474\">Hacker News<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Wade Tregaskis: Almost nobody intentionally uses NSCopyObject, but your superclass might, and therefore you might.[&#8230;]Someguides specify a better method, which is to manually zero out the copied object&rsquo;s ivars and then repopulate them via formal property setters. That actually works with or without ARC, although it may break &#x2013; causing memory leaks &#x2013; if the [&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":"2024-07-16T18:49:34Z","apple_news_api_id":"3f4f2798-fb2f-45ab-b515-42a2e93ce3cb","apple_news_api_modified_at":"2024-07-17T18:31:11Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AP08nmPsvRau1FUKi6Tzjyw","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":[55,69,31,2321,30,2385,54,71,901],"class_list":["post-44105","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-arc","tag-cocoa","tag-ios","tag-ios-17","tag-mac","tag-macos-14-sonoma","tag-objective-c","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44105","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=44105"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44105\/revisions"}],"predecessor-version":[{"id":44114,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/44105\/revisions\/44114"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=44105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=44105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=44105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}