{"id":24403,"date":"2019-02-22T16:18:45","date_gmt":"2019-02-22T21:18:45","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=24403"},"modified":"2019-03-06T08:58:07","modified_gmt":"2019-03-06T13:58:07","slug":"swift-subclass-of-nstextstorage-is-slow-because-of-swift-bridging","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/02\/22\/swift-subclass-of-nstextstorage-is-slow-because-of-swift-bridging\/","title":{"rendered":"Swift Subclass of NSTextStorage Is Slow Because of Swift Bridging"},"content":{"rendered":"<p><a href=\"https:\/\/bugs.swift.org\/browse\/SR-6197\">Darren Mo<\/a> (via <a href=\"https:\/\/twitter.com\/krzyzanowskim\/status\/1098895780763615232\">Marcin Krzyzanowski<\/a>):<\/p>\n<blockquote cite=\"https:\/\/bugs.swift.org\/browse\/SR-6197\"><p>Calling <code>-[NSTextStorage attributesAtIndex:effectiveRange:]<\/code> is nearly 3 times as slow for <code>TextStorageSwiftSubclass<\/code> compared to <code>NSTextStorage<\/code>. Time profiling shows that this is caused by the bridging of the Objective-C dictionary return value to Swift. Effectively, this means we cannot use Swift if we want to subclass <code>NSTextStorage<\/code>.<\/p><\/blockquote>\n<p>There are ways to get around bridging overhead at method call sites. I think the issue here is that these techniques can&rsquo;t be applied because the subclass is being called by the frameworks. Perhaps there&rsquo;s a way to work around it by implementing certain methods in Objective-C and others in a Swift extension, but interoperability can be messy depending on how much you are taking advantage of Swift&rsquo;s features.<\/p>\n\n<p><a href=\"https:\/\/bugs.swift.org\/browse\/SR-6197?focusedCommentId=42971\">Jonas Boberg<\/a>:<\/p>\n<blockquote cite=\"https:\/\/bugs.swift.org\/browse\/SR-6197?focusedCommentId=42971\"><p>Note that this is not just an issue with subclasses, but also delegate methods, such as <code>NSLayoutManagerDelegate<\/code> <code>shouldUseTemporaryAttributes<\/code>.<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/08\/29\/swift-4-bridging-peephole-for-as-casts\/\">Swift 4: Bridging Peephole for &ldquo;as&rdquo; Casts<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/12\/05\/key-difference-between-dictionary-and-nsdictionary\/\">Key Difference Between Dictionary and NSDictionary<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/07\/24\/matching-and-bridging-nserrors-in-swfit\/\">Matching and Bridging NSErrors in Swift<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/04\/22\/swift-proposal-mutability-and-foundation-value-types\/\">Swift Proposal: Mutability and Foundation Value Types<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/10\/15\/swift-casting-with-_objectivecbridgeable\/\">Swift Casting With _ObjectiveCBridgeable<\/a><\/li>\n<\/ul>\n\n<p id=\"swift-subclass-of-nstextstorage-is-slow-because-of-swift-bridging-update-2019-02-26\">Update (2019-02-26): <a href=\"https:\/\/twitter.com\/pgor\/status\/1099097263828172800\">Paul Goracke<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/pgor\/status\/1099097263828172800\">\n<p>Fortuitously just watched WWDC18 Session 229 (&ldquo;Using Collections Effectively&rdquo;) this morning, which raised this concern (and example using NSAttributedString) starting at 28:16.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Darren Mo (via Marcin Krzyzanowski): Calling -[NSTextStorage attributesAtIndex:effectiveRange:] is nearly 3 times as slow for TextStorageSwiftSubclass compared to NSTextStorage. Time profiling shows that this is caused by the bridging of the Objective-C dictionary return value to Swift. Effectively, this means we cannot use Swift if we want to subclass NSTextStorage. There are ways to get [&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":"2019-02-22T21:18:47Z","apple_news_api_id":"8f089912-a0c2-4fcf-8e77-2a8752c39278","apple_news_api_modified_at":"2019-03-06T13:58:12Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/AjwiZEqDCT8-OdyqHUsOSeA","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,1610,30,1609,71,901],"class_list":["post-24403","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-cocoa","tag-ios","tag-ios-12","tag-mac","tag-macos-10-14","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24403","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=24403"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24403\/revisions"}],"predecessor-version":[{"id":24506,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/24403\/revisions\/24506"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=24403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=24403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=24403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}