Backports the new @Invalidating property wrapper to older platforms

Overview

ViewInvalidating

A property wrapper that backports the new @Invalidating property wrapper to older versions of iOS/tvOS/macOS. For more information on this new property wrapper, see the WWDC 2021 talk "What's new in AppKit" for a brief introduction.

The syntax and types closely follows what Apple is doing, so when it's time to finally update your project's deployment target to iOS 15+/tvOS 15+/macOS 12+, you can easily migrate to using Apple's version by making very minimal changes. See the migration section for more info!

Usage

Annotate your Equatable properties with @ViewInvalidating and provide options that will be used to invalidate the view whenever the property's value changes:

final class MyView: UIView {
  // Calls setNeedsLayout()
  @ViewInvalidating(.layout) var cornerRadius: CGFloat = 12.0
  
  // Calls setNeedsLayout() then setNeedsUpdateConstraints()
  @ViewInvalidating(.layout, .constraints) var heightConstraintValue: CFloat = 200.0
  
  // Calls setNeedsLayout() then setNeedsUpdateConstraints() then invalidateIntrinsicContentSize()
  @ViewInvalidating(.layout, .constraints, .intrinsicContentSize) var magicProperty: CGFloat = 1234.0

You can initialize the property wrapper with up to 10 options. You can of course add extensions to support more options though, but realistically speaking you'll likely never have a need to pass more than a few of them!

By default, there is support for a total of 5 invalidation options per platform:

Common

  • Layout
  • Display
  • Constraints
  • Intrinsic Size

macOS only

  • Restorable State

iOS 14+ only

  • Configuration

Adding custom invalidators

You can add custom invalidators by creating a type that conforms to UIViewInvalidatingType or NSViewInvalidatingType protocol (depending on the target platform) and implementing the invalidate method requirement:

extension Invalidations {
  struct Focus: UIViewInvalidatingType {
    static let focus: Self = .init()

    func invalidate(view: UIView) {
      view.setNeedsFocusUpdate()
    }
  }
}

You can then expose it to the property wrapper by extending the InvalidatingStaticMember type:

extension InvalidatingStaticMember where Base: UIViewInvalidatingType {
  static var focus: InvalidatingStaticMember<Invalidations.Focus> { .init(.focus) }
}

Note:

If you're using Xcode 13, you should do this instead:

extension UIViewInvalidatingType where Self == Invalidations.Focus {
 static var focus: Self { .focus }
}

The InvalidatingStaticMember type only exists to workaround some language limitations which have been addressed in Swift 5.5, which ships with Xcode 13. So if you're on the latest Xcode, you do not need to use the workaround. The InvalidatingStaticMember will also be unavailable.

Then you can use your new invalidator on @ViewInvalidating:

final class MyView: UIView {

  // Calls setNeedsLayout() and Focus.invalidate(self)
  @ViewInvalidating(.layout, .focus) var customProperty: CGFloat = 1.0
}

Requirements

  • Deployment target of iOS 11+, tvOS 11+ or macOS 10.11+
  • Xcode 11 or above

Installation

Add the following to your project's Package.swift file:

.package(url: "https://github.com/theblixguy/Invalidating", from: "0.1.0")

or add this package via the Xcode UI by going to File > Swift Packages > Add Package Dependency.

Migration to iOS 15+/tvOS 15+/macOS 12+ deployment target

When it's time to update your project's deployment target to iOS 15+/tvOS 15+/macOS 12+, you will need to make some very minor changes to your code to make it compatible with Apple's @Invalidating and related types.

The types that ship with this package have been annotated with @available and contain the right mappings to Apple's types on its renamed argument to make it super easy for you to update your code. Once you have update the deployment target, you will see some errors:

Migration Fix-it Migration Fix-it

As you can see, they all offer a fix-it to automatically change the type names. With a click of a button, the errors disappears without you even having to manually rename them:

Migration Fix-it Migration Fix-it

License

MIT License

Copyright (c) 2021 Suyash Srijan

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.
You might also like...
💡 A light Swift wrapper around Objective-C Runtime
💡 A light Swift wrapper around Objective-C Runtime

A light wrapper around Objective-C Runtime. What exactly is lumos? lumos as mentioned is a light wrapper around objective-c runtime functions to allow

UTIKit is an UTI (Uniform Type Identifier) wrapper for Swift.

UTIKit UTIKit is an UTI (Uniform Type Identifier) wrapper for Swift. Features UTIKit is a full featured library including entire UTI functions. Conver

Swift wrapper for PuLP module.

SwiftPuLP Wraps Python Linear Programming PuLP module. Requirements Requires PuLP to be installed, and may require PYTHON_LIBRARY environment variable

Dungeon Crawl: Stone Soup iOS Webtiles wrapper

dcss-ios Dungeon Crawl: Stone Soup iOS Webtiles wrapper Summary This project aims to make DCSS webtiles a joy to play on any iOS device without an ext

Contacts wrapper for iOS 9 or upper with Objective-C

ContactsWrapper Contacts wrapper for iOS 9 or upper with Objective-C. For the information translated to Russian, take a look at this link. Requirement

Swift-ndi - Swift wrapper around NewTek's NDI SDK

swift-ndi Swift wrapper around NewTek's NDI SDK. Make sure you extracted latest

Coz profiler Swift wrapper/bindings

Swift Coz (Linux Only) Coz profiler Swift wrapper/bindings. This is a Swift wrapper around the Coz profiler here: https://github.com/plasma-umass/coz

An unofficial wrapper around FSEvent tailored for Swift 5.

EonilFSEvents Eonil 2018 Maintenance. 2019 Maintenance. It's possible to use FSEvents directly in Swift, but it still involves many boilerplate works

A swift wrapper for NSTimer

Every.Swift - A Convenient NSTimer Wrapper Usage Provided that your class implement TimerManageable protocol you just do: self.every(3.seconds) {

Comments
  • Rename a few types to avoid name lookup ambiguities and improve APIs for Xcode 13

    Rename a few types to avoid name lookup ambiguities and improve APIs for Xcode 13

    Unfortunately, the property wrapper needs to be renamed otherwise name lookup will treat a reference to Invalidating and other types as ambiguous in Xcode 13 due to conflicts with the same type name in UIKit/AppKit. I did not expect this behavior because I assumed the new types would be effectively unavailable on lower deployment targets and the compiler will allow me to shadow those types with mine, however that does not seem to be the case.

    I have tried to isolate the changes to just the name of the property wrapper slightly (to ViewInvalidating), removing the Invalidations type from the UIView/NSView namespace and making it standalone and renaming UIViewInvalidating/NSViewInvalidating by adding a Type suffix to it.

    These changes alone were enough to resolve the problems while still making it super easy to migrate to the new type names when the deployment target is changed to iOS 15+/tvOS 15+/macOS 12+. This is achieved by adding @available annotations and providing the new type names for the renamed argument. The renamed type name is then provided as a fix-it on the availability errors making it very easy for the user to migrate without manually needing to rename anything.

    opened by theblixguy 0
Releases(0.1.0)
  • 0.1.0(Jul 2, 2021)

    Unfortunately, the property wrapper needs to be renamed otherwise name lookup will treat a reference to Invalidating and other types as ambiguous in Xcode 13 due to conflicts with the same type name in UIKit/AppKit. I did not expect this behavior because I assumed the new types would be effectively unavailable on lower deployment targets and the compiler will allow me to shadow those types with mine, however that does not seem to be the case.

    I have tried to isolate the changes to just the name of the property wrapper slightly (to ViewInvalidating), removing the Invalidations type from the UIView/NSView namespace and making it standalone and renaming UIViewInvalidating/NSViewInvalidating by adding a Type suffix to it.

    These changes alone were enough to resolve the problems while still making it super easy to migrate to the new type names when the deployment target is changed to iOS 15+/tvOS 15+/macOS 12+. This is achieved by adding @available annotations and providing the new type names for the renamed argument. The renamed type name is then provided as a fix-it on the availability errors making it very easy for the user to migrate without manually needing to rename anything.

    Source code(tar.gz)
    Source code(zip)
  • 0.0.4(Jun 30, 2021)

  • 0.0.3(Jun 29, 2021)

    • Adds Restorable State (macOS only) and Configuration (iOS 14+ only) invalidation options
    • Adds support for specifying up to 10 invalidation options
    Source code(tar.gz)
    Source code(zip)
  • 0.0.2(Jun 28, 2021)

  • 0.0.1(Jun 28, 2021)

Owner
Suyash Srijan
25. iOS Engineer currently working at @theappbusiness. Swift compiler collaborator.
Suyash Srijan
StoredIn is a simple property wrapper library to store any value in anywhere

StoredIn StoredIn is a simple property wrapper library to store any value in anywhere. Installation Please use the Swift Package Manager. dependencies

Henrique Sasaki Yuya 2 Jul 4, 2022
`Republished` is a property wrapper enabling nested ObservableObjects in SwiftUI.

Republished The @Republished proprty wrapper allows an ObservableObject nested within another ObservableObject to naturally notify SwiftUI of changes.

Adam Zethraeus 13 Dec 5, 2022
A most fully customization calendar for Apple platforms 📅

KVKCalendar KVKCalendar is a most fully customization calendar. Library consists of five modules for displaying various types of calendar (day, week,

Kviatkovskii Sergei 353 Jan 5, 2023
Swift Property Wrappers, but in Objective-C. And done horribly.

TOPropertyAccessor is an open source, Objective-C abstract class. Similar to Realm's Cocoa API, it uses the dynamic nature of the Objective-C runtime to access the properties of any of its subclasses, and routes calling them through overridable access points.

Tim Oliver 3 May 23, 2021
A Collection of useful Swift property wrappers to make coding easier

Swift Property Wrappers A Collection of useful Swift property wrappers to make c

Gordan Glavaš 2 Jan 28, 2022
Showcase new features after an app update similar to Pages, Numbers and Keynote.

WhatsNew Description WhatsNew automatically displays a short description of the new features when users update your app. This is similar to what happe

Patrick Balestra 1.5k Jan 4, 2023
WhatsNewKit enables you to easily showcase your awesome new app features.

WhatsNewKit enables you to easily showcase your awesome new app features. It's designed from the ground up to be fully customized to your needs. Featu

Sven Tiigi 2.8k Jan 3, 2023
What's new in Swift 5.x

wnis Resources What's new in Swift? Swift CHANGELOG Swift Evolution Usage $ swift run What's new in Swift (5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6): Examp

Zach Eriksen 2 Apr 3, 2022
Verify New Zealand COVID Passes in iOS apps using Swift

NzCovidPass-Swift Swift library for verification of the NZ Covid Vaccination Pas

Gallagher Security 4 Jul 19, 2022