Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for visionOS #1099

Open
rcolon-shockoe opened this issue Jan 26, 2024 · 2 comments
Open

Support for visionOS #1099

rcolon-shockoe opened this issue Jan 26, 2024 · 2 comments

Comments

@rcolon-shockoe
Copy link

Latest stable version 6.6.2 doesn't support visionOS for generating the image Assets specifically as it doesn't currently have compiler flags for os(visionOS). Are there any updates coming soon to support visionOS either for this repo or for a Stencil script?
Screenshot 2024-01-26 at 2 50 30 PM

Thanks!

shadone added a commit to shadone/SwiftGen that referenced this issue Feb 9, 2024
shadone added a commit to shadone/SwiftGen that referenced this issue Feb 9, 2024
shadone added a commit to shadone/SwiftGen that referenced this issue Feb 9, 2024
@Liquidsoul
Copy link
Member

While we see to work on this stencil issue, note that you can use custom ones. Use the existing ones as a starting point.

@lucaArchidiacono
Copy link

Might be already solved based on @Liquidsoul 's comment.

But just want to leave a draft, for those who want to quickly have a copy-paste solution:

// swiftlint:disable all
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen

{% if catalogs %}
{% macro hasValuesBlock assets filter %}
  {%- for asset in assets -%}
    {%- if asset.type == filter -%}
      1
    {%- elif asset.items -%}
      {% call hasValuesBlock asset.items filter %}
    {%- endif -%}
  {%- endfor -%}
{% endmacro %}
{% set enumName %}{{param.enumName|default:"Asset"}}{% endset %}
{% set arResourceGroupType %}{{param.arResourceGroupTypeName|default:"ARResourceGroupAsset"}}{% endset %}
{% set colorType %}{{param.colorTypeName|default:"ColorAsset"}}{% endset %}
{% set dataType %}{{param.dataTypeName|default:"DataAsset"}}{% endset %}
{% set imageType %}{{param.imageTypeName|default:"ImageAsset"}}{% endset %}
{% set symbolType %}{{param.symbolTypeName|default:"SymbolAsset"}}{% endset %}
{% set forceNamespaces %}{{param.forceProvidesNamespaces|default:"false"}}{% endset %}
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
{% set hasARResourceGroup %}{% for catalog in catalogs %}{% call hasValuesBlock catalog.assets "arresourcegroup" %}{% endfor %}{% endset %}
{% set hasColor %}{% for catalog in catalogs %}{% call hasValuesBlock catalog.assets "color" %}{% endfor %}{% endset %}
{% set hasData %}{% for catalog in catalogs %}{% call hasValuesBlock catalog.assets "data" %}{% endfor %}{% endset %}
{% set hasImage %}{% for catalog in catalogs %}{% call hasValuesBlock catalog.assets "image" %}{% endfor %}{% endset %}
{% set hasSymbol %}{% for catalog in catalogs %}{% call hasValuesBlock catalog.assets "symbol" %}{% endfor %}{% endset %}
#if os(macOS)
  import AppKit
#elseif os(iOS) || os(visionOS)
{% if hasARResourceGroup %}
  import ARKit
{% endif %}
  import UIKit
#elseif os(tvOS) || os(watchOS)
  import UIKit
#endif
#if canImport(SwiftUI)
  import SwiftUI
#endif

// Deprecated typealiases
{% if hasColor %}
@available(*, deprecated, renamed: "{{colorType}}.Color", message: "This typealias will be removed in SwiftGen 7.0")
{{accessModifier}} typealias {{param.colorAliasName|default:"AssetColorTypeAlias"}} = {{colorType}}.Color
{% endif %}
{% if hasImage %}
@available(*, deprecated, renamed: "{{imageType}}.Image", message: "This typealias will be removed in SwiftGen 7.0")
{{accessModifier}} typealias {{param.imageAliasName|default:"AssetImageTypeAlias"}} = {{imageType}}.Image
{% endif %}

// swiftlint:disable superfluous_disable_command file_length implicit_return

// MARK: - Asset Catalogs

{% macro enumBlock assets %}
  {% call casesBlock assets %}
  {% if param.allValues %}

  // swiftlint:disable trailing_comma
  {% set hasItems %}{% call hasValuesBlock assets "arresourcegroup" %}{% endset %}
  {% if hasItems %}
  @available(*, deprecated, message: "All values properties are now deprecated")
  {{accessModifier}} static let allResourceGroups: [{{arResourceGroupType}}] = [
    {% filter indent:2," ",true %}{% call allValuesBlock assets "arresourcegroup" "" %}{% endfilter %}
  ]
  {% endif %}
  {% set hasItems %}{% call hasValuesBlock assets "color" %}{% endset %}
  {% if hasItems %}
  @available(*, deprecated, message: "All values properties are now deprecated")
  {{accessModifier}} static let allColors: [{{colorType}}] = [
    {% filter indent:2," ",true %}{% call allValuesBlock assets "color" "" %}{% endfilter %}
  ]
  {% endif %}
  {% set hasItems %}{% call hasValuesBlock assets "data" %}{% endset %}
  {% if hasItems %}
  @available(*, deprecated, message: "All values properties are now deprecated")
  {{accessModifier}} static let allDataAssets: [{{dataType}}] = [
    {% filter indent:2," ",true %}{% call allValuesBlock assets "data" "" %}{% endfilter %}
  ]
  {% endif %}
  {% set hasItems %}{% call hasValuesBlock assets "image" %}{% endset %}
  {% if hasItems %}
  @available(*, deprecated, message: "All values properties are now deprecated")
  {{accessModifier}} static let allImages: [{{imageType}}] = [
    {% filter indent:2," ",true %}{% call allValuesBlock assets "image" "" %}{% endfilter %}
  ]
  {% endif %}
  {% set hasItems %}{% call hasValuesBlock assets "symbol" %}{% endset %}
  {% if hasItems %}
  @available(*, deprecated, message: "All values properties are now deprecated")
  {{accessModifier}} static let allSymbols: [{{symbolType}}] = [
    {% filter indent:2," ",true %}{% call allValuesBlock assets "symbol" "" %}{% endfilter %}
  ]
  {% endif %}
  // swiftlint:enable trailing_comma
  {% endif %}
{% endmacro %}
{% macro casesBlock assets %}
  {% for asset in assets %}
  {% if asset.type == "arresourcegroup" %}
  {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{arResourceGroupType}}(name: "{{asset.value}}")
  {% elif asset.type == "color" %}
  {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{colorType}}(name: "{{asset.value}}")
  {% elif asset.type == "data" %}
  {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{dataType}}(name: "{{asset.value}}")
  {% elif asset.type == "image" %}
  {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{imageType}}(name: "{{asset.value}}")
  {% elif asset.type == "symbol" %}
  {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{symbolType}}(name: "{{asset.value}}")
  {% elif asset.items and ( forceNamespaces == "true" or asset.isNamespaced == "true" ) %}
  {{accessModifier}} enum {{asset.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
    {% filter indent:2," ",true %}{% call casesBlock asset.items %}{% endfilter %}
  }
  {% elif asset.items %}
  {% call casesBlock asset.items %}
  {% endif %}
  {% endfor %}
{% endmacro %}
{% macro allValuesBlock assets filter prefix %}
  {% for asset in assets %}
  {% if asset.type == filter %}
  {{prefix}}{{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}},
  {% elif asset.items and ( forceNamespaces == "true" or asset.isNamespaced == "true" ) %}
  {% set prefix2 %}{{prefix}}{{asset.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}.{% endset %}
  {% call allValuesBlock asset.items filter prefix2 %}
  {% elif asset.items %}
  {% call allValuesBlock asset.items filter prefix %}
  {% endif %}
  {% endfor %}
{% endmacro %}
// swiftlint:disable identifier_name line_length nesting type_body_length type_name
{{accessModifier}} enum {{enumName}} {
  {% if catalogs.count > 1 or param.forceFileNameEnum %}
  {% for catalog in catalogs %}
  {{accessModifier}} enum {{catalog.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
    {% if catalog.assets %}
    {% filter indent:2," ",true %}{% call enumBlock catalog.assets %}{% endfilter %}
    {% endif %}
  }
  {% endfor %}
  {% else %}
  {% call enumBlock catalogs.first.assets %}
  {% endif %}
}
// swiftlint:enable identifier_name line_length nesting type_body_length type_name

// MARK: - Implementation Details
{% if hasARResourceGroup %}

{{accessModifier}} struct {{arResourceGroupType}} {
  {{accessModifier}} fileprivate(set) var name: String

  #if os(iOS) || os(visionOS)
  @available(iOS 11.3, *)
  {{accessModifier}} var referenceImages: Set<ARReferenceImage> {
    return ARReferenceImage.referenceImages(in: self)
  }

  @available(iOS 12.0, visionOS 1.0, *)
  {{accessModifier}} var referenceObjects: Set<ARReferenceObject> {
    return ARReferenceObject.referenceObjects(in: self)
  }
  #endif
}

#if os(iOS) || os(visionOS)
@available(iOS 11.3, visionOS 1.0, *)
{{accessModifier}} extension ARReferenceImage {
  static func referenceImages(in asset: {{arResourceGroupType}}) -> Set<ARReferenceImage> {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    return referenceImages(inGroupNamed: asset.name, bundle: bundle) ?? Set()
  }
}

@available(iOS 12.0, visionOS 1.0, *)
{{accessModifier}} extension ARReferenceObject {
  static func referenceObjects(in asset: {{arResourceGroupType}}) -> Set<ARReferenceObject> {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    return referenceObjects(inGroupNamed: asset.name, bundle: bundle) ?? Set()
  }
}
#endif
{% endif %}
{% if hasColor %}

{{accessModifier}} final class {{colorType}} {
  {{accessModifier}} fileprivate(set) var name: String

  #if os(macOS)
  {{accessModifier}} typealias Color = NSColor
  #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
  {{accessModifier}} typealias Color = UIColor
  #endif

  @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *)
  {{accessModifier}} private(set) lazy var color: Color = {
    guard let color = Color(asset: self) else {
      fatalError("Unable to load color asset named \(name).")
    }
    return color
  }()

  #if os(iOS) || os(tvOS) || os(visionOS)
  @available(iOS 11.0, tvOS 11.0, visionOS 1.0, *)
  {{accessModifier}} func color(compatibleWith traitCollection: UITraitCollection) -> Color {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    guard let color = Color(named: name, in: bundle, compatibleWith: traitCollection) else {
      fatalError("Unable to load color asset named \(name).")
    }
    return color
  }
  #endif

  #if canImport(SwiftUI)
  @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
  {{accessModifier}} private(set) lazy var swiftUIColor: SwiftUI.Color = {
    SwiftUI.Color(asset: self)
  }()
  #endif

  fileprivate init(name: String) {
    self.name = name
  }
}

{{accessModifier}} extension {{colorType}}.Color {
  @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, visionOS 1.0, *)
  convenience init?(asset: {{colorType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    #if os(iOS) || os(tvOS) || os(visionOS)
    self.init(named: asset.name, in: bundle, compatibleWith: nil)
    #elseif os(macOS)
    self.init(named: NSColor.Name(asset.name), bundle: bundle)
    #elseif os(watchOS)
    self.init(named: asset.name)
    #endif
  }
}

#if canImport(SwiftUI)
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
{{accessModifier}} extension SwiftUI.Color {
  init(asset: {{colorType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(asset.name, bundle: bundle)
  }
}
#endif
{% endif %}
{% if hasData %}

{{accessModifier}} struct {{dataType}} {
  {{accessModifier}} fileprivate(set) var name: String

  @available(iOS 9.0, tvOS 9.0, watchOS 6.0, macOS 10.11, visionOS 1.0, *)
  {{accessModifier}} var data: NSDataAsset {
    guard let data = NSDataAsset(asset: self) else {
      fatalError("Unable to load data asset named \(name).")
    }
    return data
  }
}

@available(iOS 9.0, tvOS 9.0, watchOS 6.0, macOS 10.11, visionOS 1.0, *)
{{accessModifier}} extension NSDataAsset {
  convenience init?(asset: {{dataType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    #if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
    self.init(name: asset.name, bundle: bundle)
    #elseif os(macOS)
    self.init(name: NSDataAsset.Name(asset.name), bundle: bundle)
    #endif
  }
}
{% endif %}
{% if hasImage %}

{{accessModifier}} struct {{imageType}} {
  {{accessModifier}} fileprivate(set) var name: String

  #if os(macOS)
  {{accessModifier}} typealias Image = NSImage
  #elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
  {{accessModifier}} typealias Image = UIImage
  #endif

  @available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, visionOS 1.0, *)
  {{accessModifier}} var image: Image {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    #if os(iOS) || os(tvOS) || os(visionOS)
    let image = Image(named: name, in: bundle, compatibleWith: nil)
    #elseif os(macOS)
    let name = NSImage.Name(self.name)
    let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name)
    #elseif os(watchOS)
    let image = Image(named: name)
    #endif
    guard let result = image else {
      fatalError("Unable to load image asset named \(name).")
    }
    return result
  }

  #if os(iOS) || os(tvOS) || os(visionOS)
  @available(iOS 8.0, tvOS 9.0, visionOS 1.0, *)
  {{accessModifier}} func image(compatibleWith traitCollection: UITraitCollection) -> Image {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else {
      fatalError("Unable to load image asset named \(name).")
    }
    return result
  }
  #endif

  #if canImport(SwiftUI)
  @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
  {{accessModifier}} var swiftUIImage: SwiftUI.Image {
    SwiftUI.Image(asset: self)
  }
  #endif
}

{{accessModifier}} extension {{imageType}}.Image {
  @available(iOS 8.0, tvOS 9.0, watchOS 2.0, visionOS 1.0, *)
  @available(macOS, deprecated,
    message: "This initializer is unsafe on macOS, please use the {{imageType}}.image property")
  convenience init?(asset: {{imageType}}) {
    #if os(iOS) || os(tvOS) || os(visionOS)
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(named: asset.name, in: bundle, compatibleWith: nil)
    #elseif os(macOS)
    self.init(named: NSImage.Name(asset.name))
    #elseif os(watchOS)
    self.init(named: asset.name)
    #endif
  }
}

#if canImport(SwiftUI)
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
{{accessModifier}} extension SwiftUI.Image {
  init(asset: {{imageType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(asset.name, bundle: bundle)
  }

  init(asset: {{imageType}}, label: Text) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(asset.name, bundle: bundle, label: label)
  }

  init(decorative asset: {{imageType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(decorative: asset.name, bundle: bundle)
  }
}
#endif
{% endif %}
{% if hasSymbol %}

{{accessModifier}} struct {{symbolType}} {
  {{accessModifier}} fileprivate(set) var name: String

  #if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
  @available(iOS 13.0, tvOS 13.0, watchOS 6.0, visionOS 1.0, *)
  {{accessModifier}} typealias Configuration = UIImage.SymbolConfiguration
  {{accessModifier}} typealias Image = UIImage

  @available(iOS 12.0, tvOS 12.0, watchOS 5.0, visionOS 1.0, *)
  {{accessModifier}} var image: Image {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    #if os(iOS) || os(tvOS) || os(visionOS)
    let image = Image(named: name, in: bundle, compatibleWith: nil)
    #elseif os(watchOS)
    let image = Image(named: name)
    #endif
    guard let result = image else {
      fatalError("Unable to load symbol asset named \(name).")
    }
    return result
  }

  @available(iOS 13.0, tvOS 13.0, watchOS 6.0, visionOS 1.0, *)
  {{accessModifier}} func image(with configuration: Configuration) -> Image {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    guard let result = Image(named: name, in: bundle, with: configuration) else {
      fatalError("Unable to load symbol asset named \(name).")
    }
    return result
  }
  #endif

  #if canImport(SwiftUI)
  @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
  {{accessModifier}} var swiftUIImage: SwiftUI.Image {
    SwiftUI.Image(asset: self)
  }
  #endif
}

#if canImport(SwiftUI)
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, visionOS 1.0, *)
{{accessModifier}} extension SwiftUI.Image {
  init(asset: {{symbolType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(asset.name, bundle: bundle)
  }

  init(asset: {{symbolType}}, label: Text) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(asset.name, bundle: bundle, label: label)
  }

  init(decorative asset: {{symbolType}}) {
    let bundle = {{param.bundle|default:"BundleToken.bundle"}}
    self.init(decorative: asset.name, bundle: bundle)
  }
}
#endif
{% endif %}
{% if not param.bundle %}

// swiftlint:disable convenience_type
private final class BundleToken {
  static let bundle: Bundle = {
    #if SWIFT_PACKAGE
    return Bundle.module
    #else
    return Bundle(for: BundleToken.self)
    #endif
  }()
}
// swiftlint:enable convenience_type
{% endif %}
{% else %}
// No assets found
{% endif %}

I guess there is room for improvements, or even some API's which are not correctly marked as available for visionOS 1.0. But keep in mind this is just a draft 😄

@rcolon-shockoe Save this template in your directory. I named it like this: visionOS-supported-xcassets-template.stencil. Go to your swiftgen.yml and leave this in your xcassets config section:

xcassets:
  inputs:
    - Assets.xcassets
  outputs:
    - templatePath: visionOS-supported-xcassets-template.stencil
      output: Assets+Generated.swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants