@VIViewInvalidating

一个 Swift PropertyWrapper,用于在属性值更改时自动使 NSView/UIView 失效。它复制了 @Invalidating propertyWrapper,以支持 macOS 12 和 iOS 15 之前的构建目标。

Swift Package Manager

为什么需要它?

我在 WWDC2021 的视频 'AppKit 的新功能' 中看到,他们简要提到了一个新的 propertyWrapper 类型 @Invalidating(),它会在 wrappedValue 更改时自动更新视图。但似乎这个 propertyWrapper 仅在更高版本的 AppKit(以及 UIKit)中可用。

考虑到许多 AppKit/UIKit 开发人员短期内无法将其最低目标版本迁移到 macOS 12 或 iOS 15,我决定尝试复制我在视频中看到的内容。

@VIViewInvalidating() 由此诞生!

一旦你的目标设置为 macOS 13 或更高版本,你的 @VIViewInvalidating() 定义将生成弃用警告,提示你迁移到 @Invalidating()

我已尽力确保 API 尽可能接近 @Invalidating,因此理论上,迁移你的应用程序目标应该像更改一些名称一样简单

失效类型

内置

提供以下内置失效器:

示例

class BadgeView: NSView {
   // Automatically sets needsDisplay = true on the view when the value changes
   @VIViewInvalidating(.display) var color: NSColor = NSColor.blue
   
   // Set needsDisplay, needsLayout and invalidateIntrinsicContentSize() on 
   // the view when the value changes
   @VIViewInvalidating(.display, .layout, .intrinsicContentSize)
   var position: NSControl.ImagePosition = .imageLeft
}

自定义失效

使您的视图遵循 VIViewCustomInvalidating 协议

该协议方法提供了一个非常高级的回调,当任何 @VIViewInvalidating 属性在您的视图中更新时,它会被调用。这等效于更高 SDK(macOS 12 和 iOS 15)中的 NSViewInvalidating 协议。

示例

class BadgeView: NSView  {
   @VIViewInvalidating(.display) var color: NSColor = NSColor.blue
   @VIViewInvalidating(.display) var backgroundColor: NSColor = NSColor.white
}

extension BadgeView: VIViewCustomInvalidating {
   // Will be called when any `@VIViewInvalidating` property is updated in the view
   func invalidate(view: NSView) {
      Swift.print("custom invalidation!")
   }
}

提供您自己的失效器 (不推荐!)

注意 此行为与 Apple 的 @Invalidating property wrapper 不兼容。 @Invalidating 不提供类似的功能,因此请注意,当您将构建目标升级到 macOS13/iOS15 时,没有直接的替代品,您的代码将会中断。

您可以通过定义 VIViewType.VIViewInvalidatorAction 类型的新类来提供自定义失效器。

示例

class CustomInvalidator: VIViewInvalidatorAction {
   public override func invalidate(_ view: VIViewType) {
      Swift.print("Custom invalidator called")
   }
}

class ExcitingView: NSView {
   @VIViewInvalidating(.display) var color: NSColor = .white
   @VIViewInvalidating(.display, CustomInvalidator()) var backgroundColor: NSColor = .systemBlue
   override func draw(_ dirtyRect: NSRect) {
      self.backgroundColor.setFill()
      dirtyRect.fill()
   }
}

更新

3.0.1

3.0.0

2.0.1

2.0.0

1.0.0

感谢

John Sundell

Twitter, Swift By Sundell

许可证

麻省理工学院许可证。 您可以随意使用! 如果您在某处使用了它,请告诉我,我很乐意听到它。

MIT License

Copyright (c) 2021 Darren Ford

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.