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

Usable from Objective-C? #4

Closed
samizdatco opened this issue Jul 9, 2022 · 4 comments
Closed

Usable from Objective-C? #4

samizdatco opened this issue Jul 9, 2022 · 4 comments

Comments

@samizdatco
Copy link

Thanks so much for this terrific library. I've been looking into getting it working with an old objc-based app of mine and am a little confused by the interface in the generated headers. I can see in Image.swift that the init method can handle urls, bundle names, as well as data. But the SwiftDraw-Swift.h file that's generated via swift build only contains argument-less stubs:

SWIFT_CLASS_NAMED("Image")
@interface SVGImage : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end

Shouldn't the various other initializers also be present (or am I missing something obvious here)?

@swhitty
Copy link
Owner

swhitty commented Jul 11, 2022

Hi @samizdatco, thanks for the feedback. 🙏🏻

Most of the functionality within SwiftDraw is only available from Swift. Thanks for pointing out the shortcoming, the latest version 0.9.2 now allows you to create images from svgs within Objective-C;

UIKit

imageView.image = [UIImage svgNamed: @"sample.svg"];

macOS

imageView.image = [NSImage svgNamed: @"sample.svg"];

I do not plan on exposing much more to ObjectiveC. It is possible to write your own extensions and expose additional functionality as you require.

Cheers

@samizdatco
Copy link
Author

I do not plan on exposing much more to ObjectiveC. It is possible to write your own extensions and expose additional functionality as you require.

That seems totally reasonable and thanks a ton for adding the bundle-loading method!

The thing that would be especially handy for me is being able to create NSImages from NSData though. Would you consider adding bindings for the data & url initializers too? Maybe something along the lines of this copy-and-paste job (though surely there's a way to cut down on the redundancy...):

public extension NSImage {

  convenience init?(svgNamed name: String, in bundle: Bundle = Bundle.main) {
    guard let image = Image(named: name, in: bundle) else { return nil }

    self.init(size: image.size, flipped: true) { rect in
      guard let ctx = NSGraphicsContext.current?.cgContext else { return false }
      ctx.draw(image, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
      return true
    }
  }

  convenience init?(svgData data: Data) {
    guard let image = Image(data: data) else { return nil }

    self.init(size: image.size, flipped: true) { rect in
      guard let ctx = NSGraphicsContext.current?.cgContext else { return false }
      ctx.draw(image, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
      return true
    }
  }

  convenience init?(svgFileURL url: URL) {
    guard let image = Image(fileURL: url) else { return nil }

    self.init(size: image.size, flipped: true) { rect in
      guard let ctx = NSGraphicsContext.current?.cgContext else { return false }
      ctx.draw(image, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
      return true
    }
  }

  @objc
  static func svgNamed(_ name: String, inBundle: Bundle) -> NSImage? {
    NSImage(svgNamed: name, in: inBundle)
  }

  @objc
  static func svgNamed(_ name: String) -> NSImage? {
      NSImage(svgNamed: name, in: .main)
  }

  @objc
  static func svgFromData(_ data: Data) -> NSImage? {
      NSImage(svgData: data)
  }

  @objc
  static func svgFromURL(_ url: URL) -> NSImage? {
      NSImage(svgFileURL: url)
  }
}

@swhitty
Copy link
Owner

swhitty commented Jul 24, 2022

Hi @samizdatco

Release 0.9.4 adds 2 more convenience initialisers to Swift and ObjectiveC. They have been named in line with the existing platform initialisers

UIImage(svgData: Data)
UIImage(contentsOfSVGFile path: String)

NSImage(svgData: Data)
NSImage(contentsOfSVGFile path: String)

And exports to Objective-C

- (instancetype) initWithSVGData: (NSData *)
- (instancetype) initWithContentsOfSVGFile: (NSString *)

While AppKit does include NSImage(contentsOf url: URL) I have not implemented an SVG variant as it is trivial for consumers to write using Data(contentsOf url: URL).

@samizdatco
Copy link
Author

Fantastic! Thanks again for making these changes.

@swhitty swhitty closed this as completed Jul 30, 2022
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

2 participants