{"id":38679,"date":"2023-03-03T16:36:38","date_gmt":"2023-03-03T21:36:38","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=38679"},"modified":"2023-04-22T09:17:44","modified_gmt":"2023-04-22T13:17:44","slug":"nsviewcontroller-viewloading","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/03\/03\/nsviewcontroller-viewloading\/","title":{"rendered":"NSViewController.ViewLoading"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/documentation\/appkit\/nsviewcontroller\/viewloading\">NSViewController.ViewLoading<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/appkit\/nsviewcontroller\/viewloading\"><p>Use this property wrapper on view controller properties that can be <code>nil<\/code> before the view controller&rsquo;s view loads. Wrapping view controller properties this way eliminates crashes that can occur from implicitly defining properties as <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/optional\"><code>Optional<\/code><\/a>, and then referencing them before the view controller finishes loading.<\/p><p>[&#8230;]<\/p><p>Use this property wrapper over implicitly unwrapped optionals for <code>IBOutlets<\/code> as well.<\/p><\/blockquote>\n<p>This is introduced in the <a href=\"https:\/\/developer.apple.com\/documentation\/xcode-release-notes\/xcode-14_3-release-notes\">Xcode 14.3 beta<\/a> but requires macOS 13.3 (still in beta) for deployment. So it will be a long time before many developers can use this, but it seems like the sort of thing you could <a href=\"https:\/\/cohost.org\/jnadeau\/post\/1069174-view-loading-window#comment-0e10cc5f-08f8-4280-97d3-0d29d1a2f7c3\">reimplement<\/a> yourself.<\/p>\n\n<p>There are also <a href=\"https:\/\/developer.apple.com\/documentation\/appkit\/nswindowcontroller\/windowloading\">NSWindowController.WindowLoading<\/a> and <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/uiviewcontroller\/viewloading\">UIViewController.ViewLoading<\/a>.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2022\/09\/09\/using-lazy-properties-for-views\/\">Using Lazy Properties for Views<\/a><\/li>\n<\/ul>\n\n<p id=\"nsviewcontroller-viewloading-update-2023-04-22\">Update (2023-04-22): <a href=\"https:\/\/indiestack.com\/2023\/04\/magic-loading-property-wrappers\/\">Daniel Jalkut<\/a>:<\/p>\n<blockquote cite=\"https:\/\/indiestack.com\/2023\/04\/magic-loading-property-wrappers\/\">\n<p><a href=\"https:\/\/github.com\/danielpunkass\/MagicLoading\">MagicLoading<\/a> is a reference implementation of a @ViewLoading-style property wrapper.<\/p>\n<p>[&#8230;]<\/p>\n<p>The magic in Apple&rsquo;s wrappers is an under-documented but widely used alternative mechanism for property wrappers: the ability to define getters and setters with knowledge of the containing object&rsquo;s type, and access to the specific instance. The &ldquo;subscript&rdquo; variant of property wrappers is described in the <a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/main\/proposals\/0258-property-wrappers.md\">original proposal<\/a>, but has never been publicly endorsed, as far as I know, by Apple or the Swift team.<\/p>\n<p>Usually I would shy away from undocumented features, but in this situation I believe it&rsquo;s safe to use the undocumented subscript functionality because doing so only instructs the compiler to generate wrapper code that is compiled into the resulting binary. In other words: there are no private runtime dependencies that are being assumed by opting into this more sophisticated form of property wrapper.<\/p>\n<\/blockquote>\n<p>So it shouldn&rsquo;t count as private API for the App Store. I guess the main danger is that future versions of the compiler could remove support for this feature. Hopefully they will instead replace it with an official feature that&rsquo;s more ergonomic.<\/p>","protected":false},"excerpt":{"rendered":"<p>NSViewController.ViewLoading: Use this property wrapper on view controller properties that can be nil before the view controller&rsquo;s view loads. Wrapping view controller properties this way eliminates crashes that can occur from implicitly defining properties as Optional, and then referencing them before the view controller finishes loading.[&#8230;]Use this property wrapper over implicitly unwrapped optionals for IBOutlets [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2023-03-03T21:36:41Z","apple_news_api_id":"df7a976d-724a-4f16-89e2-3779fac42976","apple_news_api_modified_at":"2023-04-22T13:17:46Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAw==","apple_news_api_share_url":"https:\/\/apple.news\/A33qXbXJKTxaJ4jd5-sQpdg","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":[69,31,2185,30,2223,74,1013,71,901],"class_list":["post-38679","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-cocoa","tag-ios","tag-ios-16","tag-mac","tag-macos-13-ventura","tag-opensource","tag-private-api","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38679","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=38679"}],"version-history":[{"count":5,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38679\/revisions"}],"predecessor-version":[{"id":39128,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38679\/revisions\/39128"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=38679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=38679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=38679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}