Natalie - Storyboard Code Generator (for Swift)

Overview

Natalie

Natalie - Storyboard Code Generator (for Swift)

Swift

Current codebase is Swift 4 compatible.

Swift 3.x code may be found from swift3 branch

Swift 2.x code may be found from swift2 branch

Swift 1.x code may be found from swift2 branch

Synopsis

Natalie generates Swift code based on storyboard files to make work with Storyboards and segues easier. Generated file reduce usage of Strings as identifiers for Segues or Storyboards.

Proof of concept implementation to address the String issue for strongly typed Swift language. Natalie is a Swift command-line application (written in Swift) that produces a single .swift file with a bunch of extensions to project classes along the generated Storyboard enum.

Natalie is written in Swift and requires Swift to run. The project uses SWXMLHash as a dependency to parse XML and due to framework limitations.

Enumerate Storyboards

Generated enum Storyboards with a convenient interface (drop-in replacement for UIStoryboard).

struct Storyboards {
    struct Main {...}
    struct Second {...}
    ...

Instantiate initial view controller for storyboard

let vc = Storyboards.Main.instantiateInitialViewController()

Instantiate ScreenTwoViewController in storyboard, using storyboard id

let vc = Storyboards.Main.instantiateScreenTwoViewController()

example usage for prepareForSegue()

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue == MainViewController.Segue.ScreenOneSegue {    
    let viewController = segue.destinationViewController as? MyViewController
    viewController?.view.backgroundColor = UIColor.yellowColor()
  }
}

...it could be switch { } statement, but it's broken.

Segues

Perform segue

self.perform(segue: MainViewController.Segue.ScreenOneSegue, sender: nil)

Each custom view controller is extended with this code and provide a list of available segues and additional information from Storyboard.

Segue enumeration contains list of available segues

kind property represent types Segue

destination property return type of destination view controller.

extension MainViewController {

    enum Segue: String, Printable, SegueProtocol {
        case ScreenOneSegueButton = "Screen One Segue Button"
        case ScreenOneSegue = "ScreenOneSegue"

        var kind: SegueKind? {
            ...
        }

        var destination: UIViewController.Type? {
            switch (self) {
            case ScreenOneSegueButton:
                return ScreenOneViewController.self
            case ScreenOneSegue:
                return ScreenOneViewController.self
            default:
                assertionFailure("Unknown destination")
                return nil
            }
        }

        var identifier: String { return self.description }
        var description: String { return self.rawValue }
    }
}

Reusable Views To Improve Performance

Collections and tables views use reuseidentifier on cell to recycle a view.

If you define it, their custom view controllers will be extended with a Reusable enumeration, which contains list of available reusable identifiers

example to dequeue a view with Reusable enumeration with UITableView:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(ScreenTwoViewController.Reusable.MyCell, forIndexPath: indexPath) as! UITableViewCell
    cell.textLabel?.text = "\(indexPath.row)"
    return cell
}

Before dequeuing your view, you must register a class or a xib for each identifier. If your cell view has custom class defined in storyboard, in your controller you can call directly

override func viewDidLoad()  {
    tableView.registerReusableCell(MainViewController.Reusable.MyCell)
}

You can pass the view instead - the view must define the reuseidentifier

    tableView.registerReusableCell(tableViewCell)

If your reusable custom view, you can also execute code according to reusable values

class MyCustomTableViewCell: UITableViewCell {
    override func prepareForReuse() {
        if self == MyCustomTableViewController.Reusable.MyCell {
            ...
        }
        else if self == MyCustomTableViewController.Reusable.mySecondCellId {
            ...
        }
    }
}

Colors (iOS 11, macOS 10.13)

Generate an UIColor (or NSColor) static property for each asset colors used in your storyboard.

Installation

Swift Package Manager

$ git clone https://github.com/krzyzanowskim/Natalie.git
$ cd Natalie
$ ./scripts/build.sh
$ Binary at path ./Natalie/natalie

if you want easy Xcode integration you may want to install the binary to be easily accessible for any application from /usr/local/bin

$ cp natalie /usr/local/bin

Homebrew

$ brew install natalie

You can also put natalie executable file at the root of your project folder and keep it under version control. This way everyone even your CI will be able to generate the files.

Xcode Integration

Natalie can be integrated with Xcode in such a way that the Storyboards.swift the file will be updated with every build of the project, so you don't have to do it manually every time.

This is my setup created with New Run Script Phase on Build Phase Xcode target setting. It is important to move this phase above Compilation phase because this file is expected to be up to date for the rest of the application.

  • Select the project in the Project Navigator on the left of your Xcode window
  • Select your App Target in the list
  • Go in the "Build Phases" tab
  • Click on the "+" button on the upper left corner and choose "New Run Script Phase" and copy/paste script:
# Adjust path to "natalie" binary
# NATALIE_PATH="$PROJECT_DIR/natalie"
NATALIE_PATH="/usr/local/bin/natalie"

if [ -f $NATALIE_PATH ]; then
    echo "Natalie Generator: Determining if generated Swift file is up-to-date."
    
    BASE_PATH="$PROJECT_DIR/$PROJECT_NAME"
    OUTPUT_PATH="$BASE_PATH/Storyboards.swift"

    if [ ! -e "$OUTPUT_PATH" ] || [ -n "$(find "$BASE_PATH" -type f -name "*.storyboard" -newer "$OUTPUT_PATH" -print -quit)" ]; then
        echo "Natalie Generator: Generated Swift is out-of-date; re-generating..."

        /usr/bin/chflags nouchg "$OUTPUT_PATH"
        "$NATALIE_PATH" "$BASE_PATH" > "$OUTPUT_PATH"
        /usr/bin/chflags uchg "$OUTPUT_PATH"

        echo "Natalie Generator: Done."
    else
        echo "Natalie Generator: Generated Swift is up-to-date; skipping re-generation."
    fi
else 
    echo "error: Could not find Natalie Generator at $NATALIE_PATH; Please visit https://github.com/krzyzanowskim/Natalie for installation instructions."
    exit 1
fi
  • add Storyboards.swift to the project.

Usage:

Download Natalie from Github: https://github.com/krzyzanowskim/Natalie and use it in the console, for example like this:

$ git clone https://github.com/krzyzanowskim/Natalie.git
$ cd Natalie

The command expects one of two types of parameters:

  • path to a single .storyboard file
  • path to a folder

If the parameter is a Storyboard file, then this file will be used. If a path to a folder is provided Natalie will generate code for every storyboard found inside.

$ natalie NatalieExample/NatalieExample/Base.lproj/Main.storyboard > NatalieExample/NatalieExample/Storyboards.swift

Contribution

Please submit Pull Request against current development branch.

Author and contact

Marcin Krzyżanowski

Licence

The MIT License (MIT)

Copyright (c) 2015 Marcin Krzyzanowski

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.

Comments
  • OS X support is broken

    OS X support is broken

    Running what's in master against my OS X Storyboard, I get references to UIStoryboard and UIViewController. Changing these to NSStoryboard and NSViewController gives me an error: ambiguous use of identifier (on line 13).

    //
    // Autogenerated by Natalie - Storyboard Generator Script.
    // http://blog.krzyzanowskim.com
    //
    
    import Cocoa
    
    //MARK: - Storyboards
    
    extension UIStoryboard {
        func instantiateViewController<T: UIViewController where T: IdentifiableProtocol>(type: T.Type) -> T? {
            let instance = type.init()
            if let identifier = instance.identifier {
                return self.instantiateViewControllerWithIdentifier(identifier) as? T
            }
            return nil
        }
    }
    
    protocol Storyboard {
        static var storyboard: NSStoryboard { get }
        static var identifier: String { get }
    }
    
    struct Storyboards {
    
        struct Main: Storyboard {
    
            static let identifier = "Main"
    
            static var storyboard: NSStoryboard {
                return NSStoryboard(name: self.identifier, bundle: nil)
            }
    
            static func instantiateWindowControllerWithIdentifier(identifier: String) -> NSWindowController {
                return self.storyboard.instantiateControllerWithIdentifier(identifier) as! NSWindowController
            }
    
            static func instantiateViewController<T: UIViewController where T: IdentifiableProtocol>(type: T.Type) -> T? {
                return self.storyboard.instantiateViewController(type)
            }
    
            static func instantiateViewControllerWithIdentifier(identifier: String) -> NSViewController {
                return self.storyboard.instantiateControllerWithIdentifier(identifier) as! NSViewController
            }
    
            static func instantiateViewController<T: UIViewController where T: IdentifiableProtocol>(type: T.Type) -> T? {
                return self.storyboard.instantiateViewController(type)
            }
    
            static func instantiateDocumentWindowController() -> NSWindowController {
                return self.storyboard.instantiateControllerWithIdentifier("Document Window Controller") as! NSWindowController
            }
        }
    }
    
    //MARK: - ReusableKind
    enum ReusableKind: String, CustomStringConvertible {
        case TableViewCell = "tableViewCell"
        case CollectionViewCell = "collectionViewCell"
    
        var description: String { return self.rawValue }
    }
    
    //MARK: - SegueKind
    enum SegueKind: String, CustomStringConvertible {    
        case Relationship = "relationship" 
        case Show = "show"                 
        case Presentation = "presentation" 
        case Embed = "embed"               
        case Unwind = "unwind"             
        case Push = "push"                 
        case Modal = "modal"               
        case Popover = "popover"           
        case Replace = "replace"           
        case Custom = "custom"             
    
        var description: String { return self.rawValue } 
    }
    
    //MARK: - SegueProtocol
    public protocol IdentifiableProtocol: Equatable {
        var identifier: String? { get }
    }
    
    public protocol SegueProtocol: IdentifiableProtocol {
    }
    
    public func ==<T: SegueProtocol, U: SegueProtocol>(lhs: T, rhs: U) -> Bool {
        return lhs.identifier == rhs.identifier
    }
    
    public func ~=<T: SegueProtocol, U: SegueProtocol>(lhs: T, rhs: U) -> Bool {
        return lhs.identifier == rhs.identifier
    }
    
    public func ==<T: SegueProtocol>(lhs: T, rhs: String) -> Bool {
        return lhs.identifier == rhs
    }
    
    public func ~=<T: SegueProtocol>(lhs: T, rhs: String) -> Bool {
        return lhs.identifier == rhs
    }
    
    public func ==<T: SegueProtocol>(lhs: String, rhs: T) -> Bool {
        return lhs == rhs.identifier
    }
    
    public func ~=<T: SegueProtocol>(lhs: String, rhs: T) -> Bool {
        return lhs == rhs.identifier
    }
    
    //MARK: - ReusableViewProtocol
    public protocol ReusableViewProtocol: IdentifiableProtocol {
        var viewType: NSView.Type? { get }
    }
    
    public func ==<T: ReusableViewProtocol, U: ReusableViewProtocol>(lhs: T, rhs: U) -> Bool {
        return lhs.identifier == rhs.identifier
    }
    
    //MARK: - Protocol Implementation
    extension NSStoryboardSegue: SegueProtocol {
    }
    
    //MARK: - NSViewController extension
    extension NSViewController {
        func performSegue<T: SegueProtocol>(segue: T, sender: AnyObject?) {
            if let identifier = segue.identifier {
                performSegueWithIdentifier(identifier, sender: sender)
            }
        }
    
        func performSegue<T: SegueProtocol>(segue: T) {
            performSegue(segue, sender: nil)
        }
    }
    
    //MARK: - NSWindowController extension
    extension NSWindowController {
        func performSegue<T: SegueProtocol>(segue: T, sender: AnyObject?) {
            if let identifier = segue.identifier {
                performSegueWithIdentifier(identifier, sender: sender)
            }
        }
    
        func performSegue<T: SegueProtocol>(segue: T) {
            performSegue(segue, sender: nil)
        }
    }
    
    
    //MARK: - ViewController
    
    bug 
    opened by tonyarnold 11
  • natalie binary of 0.6.5 does not work after updating to Xcode 9.3

    natalie binary of 0.6.5 does not work after updating to Xcode 9.3

    Executing natalie, even with no arguments, in commandline throws an error like this: dyld: Symbol not found: __T0s11CommandLineO9argumentsSaySSGvZ.

    swift --version outputs the following after switching command-line-tools back to 9.2 (9C40b): Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2) Target: x86_64-apple-macosx10.9

    If I build the natalie project in Xcode 9.2 or 9.3 and execute the generated executable it just works fine.

    Maybe the natalie executable is not compatible with the updated swift version in the system?

    opened by Fab1n 10
  • Added the ViewController Storyboard Identifiers to each storyboard

    Added the ViewController Storyboard Identifiers to each storyboard

    Hi,

    I modified quite a few things, the main reason was to be able to use the same ViewController class multiple times in different storyboards each with a different Storyboard ID. This was impossible before because you would end up adding an extension twice to the same class.

    Now because the storyboards are structs, it means that I was able to specialise instantiateInitialViewController method so that the return type is the same as the type of the ViewController.

    To instantiate a Viewcontroller with id "ListVC" in storyboard Main, you do:

    let vc = Storyboards.Main.ListVC()
    

    If you have any questions or remarks, my ears are open.

    Open ears

    opened by CallumOz 10
  • OSX issue

    OSX issue

    this https://github.com/krzyzanowskim/Natalie/blame/master/natalie.swift#L681 is not working for OSX. Do not compile. saying that Segue is not convertible to AnyObject.Type cc @phimage

    opened by krzyzanowskim 9
  • Operation not permitted

    Operation not permitted

    I always get this error whenever I try to checkout other branch in Xcode.

    could not remove '/Users/account/Documents/Code/App/Company/project-app/PROJ/Storyboards.swift': Operation not permitted (-1)
    

    Any ideas?

    opened by aabanaag 8
  • New issue after XCode 7 installarion

    New issue after XCode 7 installarion

    I'm having a new issue after xcode 7 kicked in. I have 2 xcode installations now, one with 6.4 and one with 7. The only thing that doesn't pass during the build phase is Natalie. It throws me "Command /bin/sh failed with exit code 133"

    and "Natalie generator dyld: Library not loaded: @rpath/libswiftSecurity.dylib Referenced from: /usr/local/bin/natalie.swift Reason: image not found"

    and "/usr/local/bin/natalie.swift "$PROJECT_DIR/$PROJECT_NAME" > "$PROJECT_DIR/$PROJECT_NAME/Layout/Storyboards.swift""

    Anyone has the same issue? Did I mess up when doubling the installation?

    opened by TheTonon 8
  • add make and script

    add make and script

    I've splited Natalie.swift into 2 files:

    • code, main code that you can add to target and use Xcode highlight and autosuggestions
    • main, a global code for script

    Also there are 2 ways to merge them.

    • run make
    • open NatalieExample and run it. It uses a script to merge source code into Natalie.swift file
    opened by kostiakoval 8
  • Build failure on macOS 10.13 with Xcode 9 (swift 3.2)

    Build failure on macOS 10.13 with Xcode 9 (swift 3.2)

    Cannot build 0.5.0 on macOS 10.13 with Xcode 9:

    $ swift build -c release -Xswiftc -static-stdlib
    Compile Swift Module 'natalie' (14 sources)
    natalie.XMLIndexer:72:22: error: invalid redeclaration of 'Element'
        public typealias Element = natalie.XMLIndexer
                         ^
    /private/tmp/Natalie-0.5.0/Sources/natalie/SWXMLHash/SWXMLHash.swift:359:10: note: 'Element' previously declared here
        case Element(XMLElement)
             ^
    error: terminated(1): /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /private/tmp/Natalie-0.5.0/.build/release.yaml main
    
    opened by fxcoudert 7
  • using a switch statement in prepareForSegue

    using a switch statement in prepareForSegue

    Im interested to know what is actually broken here, what is it that you are trying to achieve?

    Here is a playground I was messing about in, could you please give me one in a broken state?

    enum Segue: String {
      case ScreenOneSegue = "abcdef"
    }
    
    func prepareForSegue(storyboardSegue: UIStoryboardSegue, sender: AnyObject?) {
    
    //  if storyboardSegue == Segue.ScreenOneSegue {
    //    let viewController = storyboardSegue.destinationViewController
    //    viewController?.view.backgroundColor = UIColor.yellowColor()
    //  }
    
      guard let identifier = storyboardSegue.identifier, segue = Segue(rawValue: identifier) else {
        return
      }
    
      switch segue {
    
      case .ScreenOneSegue:
        print("got here")
    
      }
    
      switch storyboardSegue {
    
      case _ where storyboardSegue == Segue.ScreenOneSegue:
        print("got here")
    
      default:
        break
    
      }
    
    }
    
    func ==<T: RawRepresentable where T.RawValue == String>(x: UIStoryboardSegue, y: T) -> Bool {
      return x.identifier == y.rawValue
    }
    

    From what I can gather you are trying to remove the need for

    guard let identifier = storyboardSegue.identifier, segue = Segue(rawValue: identifier) else {
      return
    }
    

    and perform a switch on the UIStoryboardSegue itself

    opened by ollieatkinson 7
  • Add Xcode plugin named XNatalie to generate storyboards code

    Add Xcode plugin named XNatalie to generate storyboards code

    in Xcode Product menu, added a Natalie menu

    • Generate to launch code generation
    • Enable generate when saving : to save each time a user do File>Save
    • the last menu to change natalie.swift path

    Feel free to reject the pull request, if you prefer I will make an independent project

    opened by phimage 7
  • UIViewController subclasses from separate modules/frameworks breaks generated file

    UIViewController subclasses from separate modules/frameworks breaks generated file

    If one's .storyboard includes a View Controller subclass defined in a module/framework that must normally be imported the generated file will have to import it as well.

    question 
    opened by yoiang 7
  • Conflict when Storyboard filename matches UIViewController subclass name

    Conflict when Storyboard filename matches UIViewController subclass name

    A project I am working on correlates our Storyboard file's names with the UIViewController subclass that is it's initial view controller. The result is a Storyboards.* struct that conflicts in naming with the view controller type itself:

    ...
        struct ExampleViewController: Storyboard {
    
            static let identifier = "ExampleViewController"
    
            static var storyboard: UIStoryboard {
                return UIStoryboard(name: self.identifier, bundle: nil)
            }
    
            static func instantiateExampleViewController() -> ExampleViewController {
                return self.storyboard.instantiateExampleViewController() as! ExampleViewController
            }
    
            static func instantiateViewController(withIdentifier identifier: String) -> UIViewController {
                return self.storyboard.instantiateViewController(withIdentifier: identifier)
            }
    
            static func instantiateViewController<T: UIViewController>(ofType type: T.Type) -> T? where T: IdentifiableProtocol {
                return self.storyboard.instantiateViewController(ofType: type)
            }
        }
    ...
    

    I appreciate the brevity of the struct's name and appending something like "File" clutters that. On the other hand it is more explicit: these are mappings to files as much as we'd love to abstract them away.

    opened by yoiang 3
  • Cannot declare a public var in an extension with internal requirements

    Cannot declare a public var in an extension with internal requirements

    I am getting a build issue in my generated output file. The issue is with this code:

    extension IdentifiableProtocol where Self: ExpenseClaimsNavigationController {
        public var storyboardIdentifier: String? { return "ExpenseClaimsNavigationController" }
        static var storyboardIdentifier: String? { return "ExpenseClaimsNavigationController" }
    }
    
    

    Specifically the public var. The exact error is: Cannot declare a public var in an extension with internal requirements

    This is the relevant class:

    class RotatingNavigationController: UINavigationController {
    	override var shouldAutorotate: Bool {
    		return true
    	}
    	
    	override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    		return [.portrait, .landscape]
    	}
    }
    
    class LeaveAttachmentNavigationController: RotatingNavigationController {}
    class ExpenseClaimsNavigationController: RotatingNavigationController {}
    

    Strangely I don't have this issue in another project, the public keyword is not present. Am I doing something wrong or is this an issue with Natalie?

    opened by aspyre 3
  • instantiateInitialController return type should be scoped by enclosing module

    instantiateInitialController return type should be scoped by enclosing module

    This is an issue if the storyboard has the same name as the initial controller e.g.

    struct Storyboards {
        struct FooViewController: Storyboard {
            static func instantiateInitialController() -> FooViewController {
                return self.storyboard.instantiateInitialController() as! FooViewController
            }
        }
    }
    

    Opps! instantiateInitialController returns a Storyboards.FooViewController, not a Module.FooViewController :-(

    The obvious work-around is not to name storyboards using the same name as the initial view controller. However for simple storyboards this can be a convenient and natural naming.

    Looks like natalie just needs to parse the "customModule" attribute for "viewControllers" in the storyboard xml.

    bug 
    opened by nhojb 0
  • Refactoring with Natalie in a project.

    Refactoring with Natalie in a project.

    We have a project that came with Natalie installed and contains a very large storyboard. Our next step is that we want to refactor this main storyboard into a number of smaller storyboards. Do you have any suggestions of how to do this with Natalie installed? At the moment, as I understand it, there are a few issues being caused?

    I can't really find any documentation on this and the team members (@gslondon) haven't really used Natalie before? If you could give some suggestions, documentations or blog posts about this that would be really helpful!

    opened by alexpchin 4
  • Ambiguous type name 'Segue'

    Ambiguous type name 'Segue'

    Hello,

    I have just integrated Natalie with my project using the build script given in the README. When trying to compile the generated Storyboards.swift, I am having the error Ambiguous type name 'Segue'.

    The issue is caused on a custom view controller inheriting from another custom view controller, therefore, on the child view controller, the type Segue can refer to neither it's own type or it's parent's type.

    The generated code looks like the following:

    extension X { 
    
        enum Segue: String, CustomStringConvertible, SegueProtocol {
            case viewDetail = "viewDetail"
    
            var kind: SegueKind? {
                switch (self) {
                case .viewDetail:
                    return SegueKind(rawValue: "show")
                }
            }
    
            var destination: UIViewController.Type? {
                switch (self) {
                default:
                    assertionFailure("Unknown destination")
                    return nil
                }
            }
    
            var identifier: String? { return self.description } 
            var description: String { return self.rawValue }
        }
    
    }
    
    extension UIStoryboardSegue {
        func selection() -> Y.Segue? {  // <-- Error on this line
            if let identifier = self.identifier {
                return DeliveryOrderHistoryViewController.Segue(rawValue: identifier)
            }
            return nil
        }
    }
    
    extension Y { 
    
        enum Segue: String, CustomStringConvertible, SegueProtocol {
            case viewDetail = "viewDetail"
    
            var kind: SegueKind? {
                switch (self) {
                case .viewDetail:
                    return SegueKind(rawValue: "show")
                }
            }
    
            var destination: UIViewController.Type? {
                switch (self) {
                default:
                    assertionFailure("Unknown destination")
                    return nil
                }
            }
    
            var identifier: String? { return self.description } 
            var description: String { return self.rawValue }
        }
    
    }
    
    

    On the code above, Y inherits from X, which in turn inherits from UIViewController.

    Do you have any recommendations on how to fix the issue?

    opened by moray95 4
Releases(0.7.0)
Owner
Marcin Krzyzanowski
Passionate about the open source & developer productivity. You can follow me on Twitter @krzyzanowskim
Marcin Krzyzanowski
Xcode .appiconset generator for Adobe Illustrator.

Creating AppIcon sets from Adobe Illustrator This repo is rewrited from original repo https://github.com/CaryChamplin/CreatingIconsFromAI. Just genera

gitmerge 73 Nov 9, 2020
AVXCAssets Generator takes path for your assets images and creates appiconset and imageset for you in just one click

AVXCAssets Generator Often while developing an app, We ran into a condition when we need to scale images to each and every aspect ratios for icons and

Angel Vasa 339 Dec 6, 2022
SwiftGen is a tool to automatically generate Swift code for resources of your projects

SwiftGen SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them ty

null 8.3k Jan 5, 2023
An Xcode plug-in to format your code using SwiftLint.

SwiftLintXcode An Xcode plug-in to format your code using SwiftLint. Runs swiftlint autocorrect --path CURRENT_FILE before *.swift file is saved. IMPO

Yuya Tanaka 348 Sep 18, 2022
Swift CLI for strong-typing images, colors, storyboards, fonts and localizations

Shark Shark is a Swift command line tool that generates type safe enums for your images, colors, storyboards, fonts and localizations. Because Shark r

Kaan Dedeoglu 377 Dec 1, 2022
Strong typed, autocompleted resources like images, fonts and segues in Swift projects

R.swift Get strong typed, autocompleted resources like images, fonts and segues in Swift projects Why use this? It makes your code that uses resources

Mathijs Kadijk 8.9k Jan 6, 2023
Soulful docs for Swift & Objective-C

jazzy is a command-line utility that generates documentation for Swift or Objective-C About Both Swift and Objective-C projects are supported. Instead

Realm 7.2k Jan 3, 2023
swiftenv allows you to easily install, and switch between multiple versions of Swift.

Swift Version Manager swiftenv allows you to easily install, and switch between multiple versions of Swift. This project was heavily inspired by pyenv

Kyle Fuller 1.9k Dec 27, 2022
Script to support easily using Xcode Asset Catalog in Swift.

Misen Misen is a script to support using Xcode Asset Catalog in Swift. Features Misen scans sub-directories in the specified Asset Catalog and creates

Kazunobu Tasaka 123 Jun 29, 2022
An Xcode Plugin to convert Objective-C to Swift

XCSwiftr Convert Objective-C code into Swift from within Xcode. This plugin uses the Java applet of objc2swift to do the conversion. Noticed that the

Ignacio Romero Zurbuchen 338 Nov 29, 2022
Swift autocompleter for Sublime Text, via the adorable SourceKitten framework

SwiftKitten SwiftKitten is a Swift autocompleter for Sublime Text, via the adorable SourceKitten framework. Faster than XCode ! This package is new an

John Snyder 142 Sep 9, 2022
The Swift code generator for your assets, storyboards, Localizable.strings, … — Get rid of all String-based APIs!

SwiftGen SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them ty

null 8.3k Dec 31, 2022
The Swift code generator for your assets, storyboards, Localizable.strings, … — Get rid of all String-based APIs!

SwiftGen SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them ty

null 8.3k Jan 3, 2023
GenStore is a lightweight swift code generator for your resources.

GenStore is a lightweight swift code generator for your resources. GenStore can create classes for your images, colors and localized strings.

null 11 Oct 23, 2021
Laurine - Localization code generator written in Swift. Sweet!

Author's note: Thanks everyone for making Laurine the TOP trending Swift repository in the world - this is amazing and very heart-warming! But this is

Jiri Trecak 1.3k Dec 28, 2022
QR code generator in Swift, with no external dependencies.

QRDispenser is a lightweight library to generate a QR code as image (UIImage) in your app. It uses only native components, with no dependency from oth

Andrea Mario Lufino 12 Nov 17, 2022
qr code generator tool

qr code generator tool Small command line tool for generate and reconition qr codes written in Swift Using Usage: ./qrgen [options] -m, --mode:

Igor 3 Jul 15, 2022
Objective-c code Apple style documentation set generator.

About appledoc IMPORTANT NOTICE: collaborators needed appledoc is command line tool that helps Objective-C developers generate Apple-like source code

tomaz 4.2k Dec 20, 2022
Gett's Design System code generator. Use Zeplin Styleguides as your R&D's Single Source of Truth.

Prism is a Design System code generator developed by the team at Gett ?? . Synchronizing design teams with engineering teams is a huge challenge. As t

Gett 346 Dec 31, 2022
NV_MVVM-C is a template file generator. This can reduce the time taken to write the boilerplate code and create the files.

NV_MVVM-C Template, is an MVVM-C Boilerplate generator which will help you generate all the necessary files for your project architected in MVVM-C.

Nikhil Vinod 9 Sep 6, 2022