Skip to content

Instantly share code, notes, and snippets.

@brennanMKE
Created April 26, 2021 19:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brennanMKE/d3002c9e503239b8558c973b207ac575 to your computer and use it in GitHub Desktop.
Save brennanMKE/d3002c9e503239b8558c973b207ac575 to your computer and use it in GitHub Desktop.
Cross Platform Property Wrapper

Cross Platform Property Wrapper

Javier Soto posted a tweet which showed a clever use property wrappers for supporting cross platform development. It has a lot of potential but does not appear to work when the value is not a short reference. It is also not clear how well it would work with the compiler when targeting each platform.


import Foundation
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#elseif canImport(WatchKit)
import WatchKit
#endif
@propertyWrapper
public struct PlatformDependentValue<T> {
public var wrappedValue: T { self.resolvedValue }
private let resolvedValue: T
#if os(iOS) || os(macOS) || os(watchOS) || os(tvOS)
init(iOS: @autoclosure () -> T, macOS: @autoclosure () -> T,
watchOS: @autoclosure () -> T, tvOS: @autoclosure () -> T) {
#if os(iOS)
resolvedValue = iOS()
#elseif os(macOS)
resolvedValue = macOS()
#elseif os(watchOS)
resolvedValue = watchOS()
#elseif os(tvOS)
resolvedValue = tvOS()
#endif
}
#endif
}
enum CrossPlatform {
static func deviceName() -> String {
#if canImport(UIKit)
UIDevice.current.name
#elseif canImport(AppKit)
ProcessInfo.processInfo.hostName
#elseif canImport(WatchKit)
WKInterfaceDevice.current.name
#endif
}
static func devicModel() -> String {
#if canImport(UIKit)
UIDevice.current.model
#elseif canImport(AppKit)
"Mac"
#elseif canImport(WatchKit)
WKInterfaceDevice.current.model
#endif
}
static func systemVersion() -> String {
#if canImport(UIKit)
UIDevice.current.systemVersion
#elseif canImport(AppKit)
ProcessInfo.processInfo.operatingSystemVersionString
#elseif canImport(WatchKit)
WKInterfaceDevice.current.systemVersion
#endif
}
static func systemName() -> String {
#if canImport(UIKit)
UIDevice.current.systemName
#elseif canImport(AppKit)
ProcessInfo.processInfo.hostName
#elseif canImport(WatchKit)
"Darwin"
#endif
}
}
struct Device {
@PlatformDependentValue(iOS: CrossPlatform.deviceName(),
macOS: CrossPlatform.deviceName(),
watchOS: CrossPlatform.deviceName(),
tvOS: CrossPlatform.deviceName())
var name: String
@PlatformDependentValue(iOS: CrossPlatform.devicModel(),
macOS: CrossPlatform.devicModel(),
watchOS: CrossPlatform.devicModel(),
tvOS: CrossPlatform.devicModel())
var model: String
@PlatformDependentValue(iOS: CrossPlatform.systemVersion(),
macOS: CrossPlatform.systemVersion(),
watchOS: CrossPlatform.systemVersion(),
tvOS: CrossPlatform.systemVersion())
var systemVersion: String
@PlatformDependentValue(iOS: CrossPlatform.systemName(),
macOS: CrossPlatform.systemName(),
watchOS: CrossPlatform.systemName(),
tvOS: CrossPlatform.systemName())
var systemName: String
}
let device = Device()
device.name
device.model
device.systemVersion
device.systemName
struct NumberContainer {
@PlatformDependentValue(iOS: 1, macOS: 2, watchOS: 3, tvOS: 4)
var number: Int
}
let nc = NumberContainer()
nc.number
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment