一个 Swift PropertyWrapper
,用于在属性值更改时自动使 NSView
/UIView
失效。它复制了 @Invalidating
propertyWrapper,以支持 macOS 12 和 iOS 15 之前的构建目标。
我在 WWDC2021 的视频 'AppKit 的新功能' 中看到,他们简要提到了一个新的 propertyWrapper 类型 @Invalidating()
,它会在 wrappedValue 更改时自动更新视图。但似乎这个 propertyWrapper 仅在更高版本的 AppKit(以及 UIKit)中可用。
考虑到许多 AppKit/UIKit 开发人员短期内无法将其最低目标版本迁移到 macOS 12 或 iOS 15,我决定尝试复制我在视频中看到的内容。
@VIViewInvalidating()
由此诞生!
一旦你的目标设置为 macOS 13 或更高版本,你的 @VIViewInvalidating()
定义将生成弃用警告,提示你迁移到 @Invalidating()
。
我已尽力确保 API 尽可能接近 @Invalidating
,因此理论上,迁移你的应用程序目标应该像更改一些名称一样简单
@VIViewInvalidating
-> @Invalidating
VIViewCustomInvalidating
-> UIViewInvalidating
(适用于 iOS/tvOS)VIViewCustomInvalidating
-> NSViewInvalidating
(适用于 macOS)提供以下内置失效器:
.display
).layout
).constraints
).intrinsicContentSize
).restorableState
) [仅限 macOS]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
}
该协议方法提供了一个非常高级的回调,当任何 @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()
}
}
@Invalidating
,我已更改自定义回调以匹配 Apple 的“Invalidating”协议,以帮助在将 SDK 升级到支持 @Invalidating
的版本时进行采用。restorableState
作为失效类型,以与 macOS 12+ 上的 @Invalidating
兼容。麻省理工学院许可证。 您可以随意使用! 如果您在某处使用了它,请告诉我,我很乐意听到它。
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.