{"id":38392,"date":"2023-02-06T16:50:35","date_gmt":"2023-02-06T21:50:35","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=38392"},"modified":"2023-03-08T14:18:14","modified_gmt":"2023-03-08T19:18:14","slug":"tracking-hover-location-in-swiftui","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/02\/06\/tracking-hover-location-in-swiftui\/","title":{"rendered":"Tracking Hover Location in SwiftUI"},"content":{"rendered":"<p><a href=\"https:\/\/nilcoalescing.com\/blog\/TrackingHoverLocationInSwiftUI\/\">Natalia Panferova<\/a> (<a href=\"https:\/\/twitter.com\/natpanferova\/status\/1622499700598517762\">tweet<\/a>):<\/p>\n<blockquote cite=\"https:\/\/nilcoalescing.com\/blog\/TrackingHoverLocationInSwiftUI\/\"><p>For a while we only had <a href=\"https:\/\/developer.apple.com\/documentation\/swiftui\/view\/onhover%28perform%3A%29\">onHover(perform:)<\/a> modifier in SwiftUI that is called when the user moves the pointer over or away from the view&rsquo;s frame. There used to be no official way to continuously track the pointer location. This changed with the introduction of <a href=\"https:\/\/developer.apple.com\/documentation\/swiftui\/menu\/oncontinuoushover%28coordinatespace%3Aperform%3A%29\">onContinuousHover(coordinateSpace:perform:)<\/a> in macOS 13 and iPadOS 16.<\/p><p>The new modifier lets us read the current <a href=\"https:\/\/developer.apple.com\/documentation\/swiftui\/hoverphase\">HoverPhase<\/a> and reports the exact location of the pointer when it&rsquo;s within the view&rsquo;s bounds. Let&rsquo;s see it in action.<\/p><\/blockquote>\n\n<p id=\"tracking-hover-location-in-swiftui-update-2023-02-13\">Update (2023-02-13): <a href=\"https:\/\/github.com\/siracusa\/SwiftUIHoverBug\">John Siracusa<\/a> (<a href=\"https:\/\/mastodon.social\/@siracusa\/109853396808025911\">Mastodon<\/a>):<\/p>\n<blockquote cite=\"https:\/\/github.com\/siracusa\/SwiftUIHoverBug\"><p>SwiftUI&rsquo;s <a href=\"https:\/\/developer.apple.com\/documentation\/swiftui\/spacer\/onhover(perform:)\"><code>.onHover<\/code><\/a> View method fails sporadically when applied to a view that does not cover the entire containing window and that window has a &ldquo;clear&rdquo; background color. This sample project demonstrates the bug, which has been filed with Apple as FB11988707.<\/p><p>The workaround is to make the background color anything that is not &ldquo;clear.&rdquo;<\/p><\/blockquote>\n\n<p id=\"tracking-hover-location-in-swiftui-update-2023-03-08\">Update (2023-03-08): <a href=\"https:\/\/chaos.social\/@donnywals\/109988375735109162\">Donny Wals<\/a>:<\/p>\n<blockquote cite=\"https:\/\/chaos.social\/@donnywals\/109988375735109162\"><p>Long shot: in a macOS app that leverages <a href=\"https:\/\/gist.github.com\/importRyan\/c668904b0c5442b80b6f38a980595031\">this gist<\/a> for a more reliable hover effect in SwiftUI[&#8230;]<\/p><p>On some macs with macOS 12.x this is completely fine. On others with 12.x the app is fine until the very first time the app is clicked. After that happens there&rsquo;s a huge slowdown that seems related to the code in that gist (based on Instruments trace) but without a reliable reproduction on virtually identical machines I have no idea where to start debugging.<\/p><\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Natalia Panferova (tweet): For a while we only had onHover(perform:) modifier in SwiftUI that is called when the user moves the pointer over or away from the view&rsquo;s frame. There used to be no official way to continuously track the pointer location. This changed with the introduction of onContinuousHover(coordinateSpace:perform:) in macOS 13 and iPadOS 16.The [&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-02-06T21:50:37Z","apple_news_api_id":"d450f54d-9c84-40ba-9cbd-705bd15a9877","apple_news_api_modified_at":"2023-03-08T19:18:17Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/A1FD1TZyEQLqcvXBb0VqYdw","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":[131,31,2185,30,2223,71,901,1812],"class_list":["post-38392","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-bug","tag-ios","tag-ios-16","tag-mac","tag-macos-13-ventura","tag-programming","tag-swift-programming-language","tag-swiftui"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38392","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=38392"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38392\/revisions"}],"predecessor-version":[{"id":38712,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/38392\/revisions\/38712"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=38392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=38392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=38392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}