├── .swift-version ├── ResourceKit └── release.txt ├── ResourceKitDemo ├── .gitignore ├── ResourceKit ├── ResourceKit.zip ├── ResourceKitDemo │ ├── ResourceKit │ ├── Resources │ │ ├── swift_logo.png │ │ └── swift_logo@2x.png │ ├── Assets.xcassets │ │ ├── ebi.imageset │ │ │ ├── ebi.jpg │ │ │ ├── ebi-1.jpg │ │ │ └── Contents.json │ │ ├── kake.imageset │ │ │ ├── kake.jpg │ │ │ ├── kake-1.jpg │ │ │ └── Contents.json │ │ ├── kaki.imageset │ │ │ ├── kaki.jpg │ │ │ ├── kaki-1.jpg │ │ │ └── Contents.json │ │ ├── siro.imageset │ │ │ ├── siro.jpg │ │ │ ├── siro-1.jpg │ │ │ └── Contents.json │ │ ├── curry.imageset │ │ │ ├── curry-1.jpg │ │ │ ├── curry.jpg │ │ │ └── Contents.json │ │ ├── inaka.imageset │ │ │ ├── inaka-1.jpg │ │ │ ├── inaka.jpg │ │ │ └── Contents.json │ │ ├── koori.imageset │ │ │ ├── koori-1.jpg │ │ │ ├── koori.jpg │ │ │ └── Contents.json │ │ ├── koumi.imageset │ │ │ ├── koumi-1.jpg │ │ │ ├── koumi.jpg │ │ │ └── Contents.json │ │ ├── ususio.imageset │ │ │ ├── ususio.jpg │ │ │ ├── ususio-1.jpg │ │ │ └── Contents.json │ │ ├── ninniku.imageset │ │ │ ├── ninniku.jpg │ │ │ ├── ninniku-1.jpg │ │ │ └── Contents.json │ │ ├── kikkoman.imageset │ │ │ ├── kikkoman.jpg │ │ │ ├── kikkoman-1.jpg │ │ │ └── Contents.json │ │ ├── marudaizu.imageset │ │ │ ├── marudaizu.jpg │ │ │ ├── marudaizu-1.jpg │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── ResourceKitDemo-Bridging-Header.h │ ├── ja.lproj │ │ ├── LaunchScreen.strings │ │ └── Localizable.strings │ ├── ObjCViewController.m │ ├── ObjCViewController.h │ ├── ObjectiveCTableViewCell.h │ ├── ObjCOveerrideViewController.m │ ├── ObjCOveerrideViewController.h │ ├── SecondCollectionViewCell.swift │ ├── CustomView.swift │ ├── CollectionViewCell.swift │ ├── ObjectiveCTableViewCell.m │ ├── en.lproj │ │ └── Localizable.strings │ ├── TableViewCell.swift │ ├── SecondTableViewCell.swift │ ├── ViewController.swift │ ├── OverrideViewController.swift │ ├── Info.plist │ ├── SecondTableViewController.swift │ ├── TableViewCell.xib │ ├── SecondCollectionViewController.swift │ ├── ObjectiveCTableViewCell.xib │ ├── ObjCViewController.storyboard │ ├── ObjCOverrideViewController.storyboard │ ├── TableViewController.swift │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── CustomView.xib │ ├── CollectionViewController.swift │ ├── AppDelegate.swift │ ├── InstanceFromOverride.storyboard │ ├── CollectionViewCell.xib │ ├── OverrideViewController.storyboard │ ├── ViewController.storyboard │ ├── SecondTableViewController.storyboard │ └── TabBarController.storyboard ├── Podfile.lock ├── Pods │ └── Manifest.lock ├── Podfile ├── ResourceKitDemoTests │ ├── LocalizedStringTest.swift │ ├── ResourceKitDemoTests.swift │ ├── XibTests.swift │ ├── Info.plist │ └── StoryboardTests.swift ├── ResourceKitDemoUITests │ ├── Info.plist │ └── ResourceKitDemoUITests.swift ├── ResourceKitDemo.xcodeproj │ └── xcuserdata │ │ └── kingkong999yhirose.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── ResourceKitDemo.xcscheme ├── ResourceKitConfig.plist ├── ResourceKit.log.swift └── Resource.generated.swift ├── .gitignore ├── Tests ├── LinuxMain.swift └── ResourceKitCoreTests │ └── ResourceKitTests.swift ├── Sources ├── ResourceKitCore │ ├── Core │ │ ├── Output.swift │ │ ├── Translator.swift │ │ ├── Helper.swift │ │ ├── Const.swift │ │ ├── Resources │ │ │ ├── AppendableProtocols.swift │ │ │ └── ProjectResource.swift │ │ ├── AccessControlType.swift │ │ ├── Environment.swift │ │ ├── Error.swift │ │ ├── Resource.swift │ │ └── Config.swift │ ├── Parser │ │ ├── Parser.swift │ │ ├── XibParser.swift │ │ ├── StoryboardParser.swift │ │ └── ProjectResourceParser.swift │ ├── Storyboard │ │ ├── Reusable │ │ │ ├── ReusableResource.swift │ │ │ ├── TableViewCell │ │ │ │ └── TableViewCell.swift │ │ │ ├── ReusableTranslator.swift │ │ │ ├── CollectionViewCell │ │ │ │ └── CollectionViewCell.swift │ │ │ ├── ReusableResourceType.swift │ │ │ └── ReusableResourceOutput.swift │ │ └── ViewController │ │ │ ├── ViewControllerTranslator.swift │ │ │ ├── ViewController.swift │ │ │ ├── ViewControllerResourceType.swift │ │ │ └── ViewControllerOutput.swift │ ├── Xib │ │ ├── XibTranslator.swift │ │ ├── Xib.swift │ │ └── XibOutput.swift │ ├── LocalizedString │ │ ├── LocalizedStringTranslator.swift │ │ ├── LocalizedStringRepository.swift │ │ ├── LocalizedStringEntity.swift │ │ └── LocalizedStringOutputer.swift │ ├── Image │ │ ├── ImageRepository.swift │ │ ├── ImageTranslator.swift │ │ ├── ImageEntity.swift │ │ └── ImageOutputer.swift │ ├── Config │ │ └── ResourceKitConfig.swift │ ├── Imports │ │ └── ImportOutput.swift │ └── Extensions │ │ └── ExtensionsOutput.swift └── ResourceKit │ └── main.swift ├── Makefile ├── ResourceKit.podspec ├── Package.swift ├── Package.resolved ├── LICENSE.txt ├── Documents └── Examples.md └── README.md /.swift-version: -------------------------------------------------------------------------------- 1 | 4.1 2 | -------------------------------------------------------------------------------- /ResourceKit/release.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ResourceKitDemo/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Pods/** 3 | *.xcodeproj/project.xcworkspace 4 | *.xcworkspace 5 | 6 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKit -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKit.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKit.zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Pods/** 3 | *.xcodeproj/project.xcworkspace 4 | *.xcworkspace 5 | *.xcodeproj 6 | /.build 7 | .gitmodule 8 | 9 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ResourceKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/ResourceKit -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ResourceKitTests 3 | 4 | XCTMain([ 5 | testCase(ResourceKitTests.allTests), 6 | ]) 7 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Resources/swift_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Resources/swift_logo.png -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Resources/swift_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Resources/swift_logo@2x.png -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ebi.imageset/ebi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ebi.imageset/ebi.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ebi.imageset/ebi-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ebi.imageset/ebi-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kake.imageset/kake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kake.imageset/kake.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kaki.imageset/kaki.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kaki.imageset/kaki.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/siro.imageset/siro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/siro.imageset/siro.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/curry.imageset/curry-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/curry.imageset/curry-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/curry.imageset/curry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/curry.imageset/curry.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/inaka.imageset/inaka-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/inaka.imageset/inaka-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/inaka.imageset/inaka.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/inaka.imageset/inaka.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kake.imageset/kake-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kake.imageset/kake-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kaki.imageset/kaki-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kaki.imageset/kaki-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koori.imageset/koori-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koori.imageset/koori-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koori.imageset/koori.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koori.imageset/koori.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koumi.imageset/koumi-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koumi.imageset/koumi-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koumi.imageset/koumi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koumi.imageset/koumi.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/siro.imageset/siro-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/siro.imageset/siro-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ususio.imageset/ususio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ususio.imageset/ususio.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ninniku.imageset/ninniku.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ninniku.imageset/ninniku.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ususio.imageset/ususio-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ususio.imageset/ususio-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kikkoman.imageset/kikkoman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kikkoman.imageset/kikkoman.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ninniku.imageset/ninniku-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ninniku.imageset/ninniku-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kikkoman.imageset/kikkoman-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kikkoman.imageset/kikkoman-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/marudaizu.imageset/marudaizu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/marudaizu.imageset/marudaizu.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/marudaizu.imageset/marudaizu-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bannzai/ResourceKit/HEAD/ResourceKitDemo/ResourceKitDemo/Assets.xcassets/marudaizu.imageset/marudaizu-1.jpg -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ResourceKitDemo-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "ObjCViewController.h" 6 | #import "ObjCOveerrideViewController.h" 7 | #import "ObjectiveCTableViewCell.h" 8 | -------------------------------------------------------------------------------- /ResourceKitDemo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SegueAddition (1.1.0) 3 | 4 | DEPENDENCIES: 5 | - SegueAddition 6 | 7 | SPEC CHECKSUMS: 8 | SegueAddition: 80b3f77c6c5ad082cb983df1d47f9721264deaf3 9 | 10 | PODFILE CHECKSUM: 92652161d639f7d92903c222c5510fae64667b93 11 | 12 | COCOAPODS: 1.2.0.beta.1 13 | -------------------------------------------------------------------------------- /ResourceKitDemo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SegueAddition (1.1.0) 3 | 4 | DEPENDENCIES: 5 | - SegueAddition 6 | 7 | SPEC CHECKSUMS: 8 | SegueAddition: 80b3f77c6c5ad082cb983df1d47f9721264deaf3 9 | 10 | PODFILE CHECKSUM: 92652161d639f7d92903c222c5510fae64667b93 11 | 12 | COCOAPODS: 1.2.0.beta.1 13 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Output.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Output.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Output { 12 | var declaration: String { get } 13 | } 14 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ja.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UIButton"; accessibilityIdentifier = "testtest"; ObjectID = "WJi-cT-cOB"; */ 3 | "WJi-cT-cOB.accessibilityIdentifier" = "testtest"; 4 | 5 | /* Class = "UIButton"; normalTitle = "Button"; ObjectID = "WJi-cT-cOB"; */ 6 | "WJi-cT-cOB.normalTitle" = "Button"; 7 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Parser/Parser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // parser.swift 3 | // o 4 | // 5 | // Created by kingkong999yhirose on 2016/04/12. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Parsable: XMLParserDelegate { 12 | func parse() throws 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCViewController.m 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import "ObjCViewController.h" 10 | 11 | @implementation ObjCViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCViewController.h 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ObjCViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjectiveCTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectiveCTableViewCell.h 3 | // ResourceKitDemo 4 | // 5 | // Created by Yudai.Hirose on 2018/02/08. 6 | // Copyright © 2018年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ObjectiveCTableViewCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCOveerrideViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCOveerrideViewController.m 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import "ObjCOveerrideViewController.h" 10 | 11 | @implementation ObjCOveerrideViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCOveerrideViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjCOveerrideViewController.h 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import "ObjCViewController.h" 10 | 11 | @interface ObjCOveerrideViewController : ObjCViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/ReusableResource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReusableResource.swift 3 | // ResourceKit 4 | // 5 | // Created by Hirose.Yudai on 2016/04/07. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ReusableResource { 12 | var className: String { get } 13 | var reusableIdentifiers: Set { get set } 14 | } 15 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/SecondCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondCollectionViewCell.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondCollectionViewCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var label: UILabel! 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Translator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Translator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Translator { 12 | associatedtype Input 13 | associatedtype Output 14 | 15 | func translate(for input: Input) throws -> Output 16 | } 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILD_FOLDER?=.build 2 | PROJECT?=ResourceKit 3 | RELEASE_BINARY_FOLDER?=$(BUILD_FOLDER)/release/$(PROJECT) 4 | 5 | build: 6 | swift build 7 | 8 | release: 9 | swift build --disable-sandbox -c release -Xswiftc -static-stdlib 10 | open ./.build/x86_64-apple-macosx10.10/release/ 11 | 12 | clean: 13 | swift package clean 14 | rm -rf $(BUILD_FOLDER) $(PROJECT).xcodeproj 15 | 16 | xcode: 17 | swift package generate-xcodeproj 18 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ebi.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ebi.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ebi-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/curry.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "curry.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "curry-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/inaka.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "inaka.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "inaka-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "kake.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "kake-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kaki.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "kaki.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "kaki-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koori.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "koori.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "koori-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/koumi.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "koumi.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "koumi-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/siro.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "siro.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "siro-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ususio.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ususio.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ususio-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/kikkoman.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "kikkoman.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "kikkoman-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/ninniku.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ninniku.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ninniku-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/marudaizu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "marudaizu.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "marudaizu-1.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Tests/ResourceKitCoreTests/ResourceKitTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ResourceKit 3 | 4 | class ResourceKitTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(ResourceKit().text, "Hello, World!") 10 | } 11 | 12 | 13 | static var allTests = [ 14 | ("testExample", testExample), 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/CustomView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomView.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CustomView: UIView { 12 | 13 | @IBOutlet weak var imageView: UIImageView! 14 | override func awakeFromNib() { 15 | super.awakeFromNib() 16 | imageView.image = UIImage.Resource.swift_logo 17 | imageView.sizeToFit() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Xib/XibTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XibTranslator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct XibTranslator: Translator { 12 | public init() { } 13 | public func translate(for input: Xib) throws -> XibOutput { 14 | return XibOutputImpl( 15 | nibName: input.nibName, 16 | className: input.className 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Xib/Xib.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Xib.swift 3 | // o 4 | // 5 | // Created by kingkong999yhirose on 2016/04/10. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Xib { 12 | let nibName: String 13 | let className: String 14 | let isFilesOwner: Bool 15 | 16 | init(nibName: String, className: String, isFilesOwner: Bool) { 17 | self.nibName = nibName 18 | self.className = className 19 | self.isFilesOwner = isFilesOwner 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/LocalizedString/LocalizedStringTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedStringTranslator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/22. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct LocalizedStringTranslator: Translator { 12 | public init() { } 13 | public func translate(for input: LocalizedString) throws -> LocalizedStringOutputer { 14 | return LocalizedStringOutputerImpl(localizedStrings: input.localizableStrings) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ResourceKitDemo/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'ResourceKitDemo' do 5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | pod 'SegueAddition' 9 | 10 | # Pods for ResourceKitDemo 11 | 12 | target 'ResourceKitDemoTests' do 13 | inherit! :search_paths 14 | # Pods for testing 15 | end 16 | 17 | target 'ResourceKitDemoUITests' do 18 | inherit! :search_paths 19 | # Pods for testing 20 | end 21 | 22 | end 23 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/TableViewCell/TableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class TableViewCell: ReusableResource { 12 | public let className: String 13 | public var reusableIdentifiers: Set = [] 14 | 15 | init(reusableIdentifier: String, className: String) { 16 | self.reusableIdentifiers.insert(reusableIdentifier) 17 | self.className = className 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/CollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewCell.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CollectionViewCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var label: UILabel! 14 | @IBOutlet weak var imageView: UIImageView! 15 | 16 | override func awakeFromNib() { 17 | super.awakeFromNib() 18 | } 19 | 20 | func setupWith(_ image: UIImage) { 21 | imageView.image = image 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/ReusableTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReusableTranslator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct ReusableTranslator: Translator { 12 | public init() { } 13 | public func translate(for input: ReusableResource) throws -> ReusableResourceOutput { 14 | return ReusableResourceOutputImpl( 15 | className: input.className, 16 | reusableIdentifers: input.reusableIdentifiers 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/CollectionViewCell/CollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewCell.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class CollectionViewCell: ReusableResource { 12 | public let className: String 13 | public var reusableIdentifiers: Set = [] 14 | 15 | init(reusableIdentifier: String, className: String) { 16 | self.reusableIdentifiers.insert(reusableIdentifier) 17 | self.className = className 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjectiveCTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectiveCTableViewCell.m 3 | // ResourceKitDemo 4 | // 5 | // Created by Yudai.Hirose on 2018/02/08. 6 | // Copyright © 2018年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | #import "ObjectiveCTableViewCell.h" 10 | 11 | @implementation ObjectiveCTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/ReusableResourceType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReusableResourceType.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum ReusableResourceType: String { 12 | case UITableViewCell 13 | case UICollectionViewCell 14 | 15 | init?(name: String) { 16 | switch name { 17 | case "tableViewCell": self = .UITableViewCell 18 | case "collectionViewCell": self = .UICollectionViewCell 19 | default: return nil 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ResourceKitDemo 4 | 5 | Created by kingkong999yhirose on 2016/05/03. 6 | Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | */ 8 | 9 | 10 | "hello world 1" = "hello world 1"; 11 | "hello world 2" = "hello world 2"; 12 | "hello world 3" = "hello world 3"; 13 | "hello world 4" = "hello world 4"; 14 | 15 | "hello.world 05" = "hello.world 05" ; 16 | "hello!world 06" = "hello!world 06"; 17 | "hello?world 07" = "hello?world 07"; 18 | "hello,world 08" = "hello,world 08"; 19 | "hello(world 09" = "hello(world 09"; 20 | "hello}world 10" = "hello}world 10"; -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/TableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewCell: UITableViewCell { 12 | 13 | override func awakeFromNib() { 14 | super.awakeFromNib() 15 | // Initialization code 16 | } 17 | 18 | override func setSelected(_ selected: Bool, animated: Bool) { 19 | super.setSelected(selected, animated: animated) 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Helper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Helper.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/04/12. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String { 12 | var first: String { 13 | return String(characters.prefix(1)) 14 | } 15 | var lowerFirst: String { 16 | return first.lowercased() + String(characters.dropFirst()) 17 | } 18 | 19 | public func appendNewLineIfNotEmpty() -> String { 20 | if isEmpty { 21 | return "" 22 | } 23 | 24 | return self + Const.newLine 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Const.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Const.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Const { 12 | public static let newLine = "\n" 13 | public static let tab1 = "\t" 14 | public static let tab2 = "\t\t" 15 | public static let tab3 = "\t\t\t" 16 | 17 | public static let Header = [ 18 | "// This is a generated file \n", 19 | "// Generated by ResouceKit \n", 20 | "// You can write custom imoprt XXXX logic" 21 | ].joined(separator: "") + Const.newLine 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/LocalizedString/LocalizedStringRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedStringRepository.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/22. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol LocalizedStringRepository { 12 | func load() -> LocalizedString 13 | } 14 | 15 | public struct LocalizedStringRepositoryImpl: LocalizedStringRepository { 16 | public let urls: [URL] 17 | public init( 18 | urls: [URL] 19 | ) { 20 | self.urls = urls 21 | } 22 | public func load() -> LocalizedString { 23 | return LocalizedString(urls: urls) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ResourceKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | 3 | spec.name = "ResourceKit" 4 | spec.version = "0.4.8" 5 | spec.license = "MIT" 6 | 7 | spec.summary = "Enable autocomplete use resources like in swift project" 8 | spec.homepage = "https://github.com/bannzai/ResourceKit" 9 | 10 | spec.author = { "Yudai hirose" => "kingkong999yhirose@gmail.com" } 11 | spec.social_media_url = "https://facebook.com/yudai.owata.hirose" 12 | 13 | spec.source = { :http => "https://github.com/bannzai/ResourceKit/releases/download/#{spec.version}/ResourceKit.zip" } 14 | 15 | spec.ios.deployment_target = '10.0' 16 | 17 | spec.preserve_paths = "ResourceKit" 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/SecondTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondTableViewCell.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var label: UILabel! 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | // Initialization code 18 | } 19 | 20 | override func setSelected(_ selected: Bool, animated: Bool) { 21 | super.setSelected(selected, animated: animated) 22 | 23 | // Configure the view for the selected state 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "ResourceKit", 6 | dependencies: [ 7 | .package(url: "https://github.com/bannzai/XcodeProject.git", from: Version(0, 1, 1)), 8 | .package(url: "https://github.com/kylef/Commander.git", from: Version(0, 8, 0)), 9 | ], 10 | targets: [ 11 | .target( 12 | name: "ResourceKit", 13 | dependencies: ["ResourceKitCore"] 14 | ), 15 | .target( 16 | name: "ResourceKitCore", 17 | dependencies: ["XcodeProject", "Commander"] 18 | ), 19 | .testTarget(name: "ResourceKitCoreTests", dependencies: ["ResourceKitCore"]), 20 | ], 21 | swiftLanguageVersions: [4] 22 | ) 23 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | ResourceKitDemo 4 | 5 | Created by kingkong999yhirose on 2016/05/03. 6 | Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | */ 8 | 9 | "helloworld" = "僕と契約して魔法少女になってよ!"; 10 | 11 | "hello world 1" = "hello world 1"; 12 | "hello world 2" = "hello world 2"; 13 | "hello world 3" = "hello world 3"; 14 | "hello world 4" = "hello world 4"; 15 | 16 | "hello.world 05" = "hello.world 05" ; 17 | "hello!world 06" = "hello!world 06"; 18 | "hello?world 07" = "hello?world 07"; 19 | "hello,world 08" = "hello,world 08"; 20 | "hello(world 09" = "hello(world 09"; 21 | "hello}world 10" = "hello}world 10"; 22 | 23 | "hello}world 11 %@" = "hello}world 11 %@"; 24 | "hello}world 12 %@" = "hello}world 12 %@"; -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoTests/LocalizedStringTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedStringTest.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/05. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ResourceKitDemo 11 | 12 | class LocalizedStringTest: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | func testLocalizedString() { 20 | XCTAssertTrue(NSLocalizedString("hello world 4", comment: "") == String.Localized.hello_world_4) 21 | XCTAssertTrue(NSLocalizedString("hello.world 05", comment: "") == String.Localized.hello_world_05) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoTests/ResourceKitDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceKitDemoTests.swift 3 | // ResourceKitDemoTests 4 | // 5 | // Created by kingkong999yhirose on 2016/04/10. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ResourceKitDemo 11 | 12 | class ResourceKitDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | } 17 | 18 | override func tearDown() { 19 | super.tearDown() 20 | } 21 | 22 | func testExample() { 23 | 24 | } 25 | 26 | func testPerformanceExample() { 27 | // This is an example of a performance test case. 28 | self.measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoTests/XibTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XibTests.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/03. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ResourceKitDemo 11 | 12 | class XibTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | } 17 | 18 | override func tearDown() { 19 | super.tearDown() 20 | } 21 | 22 | 23 | func testPerformanceExample() { 24 | self.measure { 25 | } 26 | } 27 | 28 | func testName() { 29 | XCTAssertTrue(CustomView.Xib.name == "CustomView") 30 | } 31 | 32 | func testView() { 33 | XCTAssertTrue(CustomView.Xib.view().isMember(of: CustomView.classForCoder())) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Resources/AppendableProtocols.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppendableProtocols.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/23. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol AppendableForPaths: class { 12 | func appendFileReferencePaths(urls: [URL]) 13 | func appendLocalizedPaths(urls: [URL]) 14 | } 15 | 16 | public protocol AppendableForXibs: class { 17 | func appendXib(_ xib: Xib) 18 | } 19 | 20 | public protocol AppendableForStoryboard: class { 21 | func appendTableViewCell(_ className: String, reusableIdentifier: String) 22 | func appendCollectionViewCell(_ className: String, reusableIdentifier: String) 23 | func appendViewControllerInfoReference(_ className: String?, viewControllerInfo: ViewControllerInfoOfStoryboard) 24 | } 25 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo.xcodeproj/xcuserdata/kingkong999yhirose.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ResourceKitDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9C8D692A1CBA98DA006F7A40 16 | 17 | primary 18 | 19 | 20 | 9C8D693E1CBA98DA006F7A40 21 | 22 | primary 23 | 24 | 25 | 9C8D69491CBA98DA006F7A40 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/AccessControlType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessControlType.swift 3 | // ResourceKit 4 | // 5 | // Created by 廣瀬雄大 on 2017/07/03. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum AccessControlType: String { 12 | case `private` 13 | case `fileprivate` 14 | case `internal` 15 | case `public` 16 | case `open` 17 | 18 | init(from string: String) { 19 | guard let accessControlType = AccessControlType(rawValue: string) else { 20 | self = .internal 21 | return 22 | } 23 | 24 | self = accessControlType 25 | } 26 | 27 | var canOverride: Bool { 28 | switch self { 29 | case .private, .fileprivate: 30 | return false 31 | case .internal, .open, .public: 32 | return true 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitConfig.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segue 6 | 7 | Standard 8 | 9 | Addition 10 | 11 | 12 | Image 13 | 14 | AssetCatalog 15 | 16 | ProjectResource 17 | 18 | 19 | String 20 | 21 | Localized 22 | 23 | 24 | ViewController 25 | 26 | InstantiateStoryboardForSwift 27 | 28 | InstantiateStoryboardForObjC 29 | 30 | 31 | Nib 32 | 33 | Xib 34 | 35 | 36 | Reusable 37 | 38 | Identifier 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/LocalizedString/LocalizedStringEntity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedStringEntity.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/22. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct LocalizedString { 12 | let localizableStrings:[String: String] 13 | init(urls: [URL]) { 14 | let files = urls.filter { $0.lastPathComponent == "Localizable.strings" } 15 | 16 | let maximumLocalizableStringPairs = 17 | files.flatMap ({ NSDictionary(contentsOf: $0) }) 18 | .sorted (by: { $0.count > $1.count }) 19 | .first 20 | 21 | guard let localizableStrings = maximumLocalizableStringPairs as? [String: String] else { 22 | self.localizableStrings = [:] 23 | return 24 | } 25 | self.localizableStrings = localizableStrings 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Commander", 6 | "repositoryURL": "https://github.com/kylef/Commander.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "e5b50ad7b2e91eeb828393e89b03577b16be7db9", 10 | "version": "0.8.0" 11 | } 12 | }, 13 | { 14 | "package": "Spectre", 15 | "repositoryURL": "https://github.com/kylef/Spectre.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "e34d5687e1e9d865e3527dd58bc2f7464ef6d936", 19 | "version": "0.8.0" 20 | } 21 | }, 22 | { 23 | "package": "XcodeProject", 24 | "repositoryURL": "https://github.com/bannzai/XcodeProject.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "8a4100c6da99fcb0633bb32f1b86facd6c04997d", 28 | "version": "0.1.1" 29 | } 30 | } 31 | ] 32 | }, 33 | "version": 1 34 | } 35 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/10. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | view.addSubview(CustomView.Xib.view()) 16 | } 17 | 18 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 19 | if segue.identifier != ViewController.Segue.showSecondTable { 20 | fatalError("\(#file) + \(#function) + \(#line)") 21 | } 22 | } 23 | @IBAction func tappedSecondCollectionView() { 24 | navigationController?.pushViewController(SecondCollectionViewController.instanceFromTabBarController(), animated: true) 25 | } 26 | 27 | @IBAction func tappedSecondTableView() { 28 | performSegueShowSecondTable() 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Image/ImageRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageRepository.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ImageAssetRepository { 12 | func load() -> Image.Assets 13 | } 14 | 15 | public struct ImageAssetRepositoryImpl: ImageAssetRepository { 16 | public init() { } 17 | public func load() -> Image.Assets { 18 | return Image.Assets(urls: 19 | ProjectResource 20 | .shared 21 | .paths 22 | ) 23 | } 24 | } 25 | 26 | public protocol ImageResourcesRepository { 27 | func load() -> Image.Resources 28 | } 29 | 30 | public struct ImageResourcesRepositoryImpl: ImageResourcesRepository { 31 | public init() { } 32 | public func load() -> Image.Resources { 33 | return Image.Resources(urls: 34 | ProjectResource 35 | .shared 36 | .paths 37 | ) 38 | } 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/OverrideViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OverrideViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/12. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class OverrideViewController: ViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | 25 | /* 26 | // MARK: - Navigation 27 | 28 | // In a storyboard-based application, you will often want to do a little preparation before navigation 29 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 30 | // Get the new view controller using segue.destinationViewController. 31 | // Pass the selected object to the new view controller. 32 | } 33 | */ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/Reusable/ReusableResourceOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReusableResourceOutput.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ReusableResourceOutput: Output { 12 | 13 | } 14 | 15 | public struct ReusableResourceOutputImpl: ReusableResourceOutput { 16 | let className: String 17 | let reusableIdentifers: Set 18 | 19 | public var declaration: String { 20 | let names = reusableIdentifers 21 | .map { 22 | return " public static let name: String = \"\($0)\"" 23 | } 24 | .joined(separator: Const.newLine) 25 | 26 | return [ 27 | "extension \(className) {", 28 | " public struct Reusable: ReusableProtocol {", 29 | " public typealias View = \(className)", 30 | "\(names)", 31 | " }", 32 | "}", 33 | ].joined(separator: Const.newLine) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Config/ResourceKitConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceKitConfig.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/10/14. 6 | // 7 | 8 | import Foundation 9 | import XcodeProject 10 | 11 | public struct ResourceKitConfig { 12 | public static let outputFileName = "Resource.generated.swift" 13 | public static var outputPath: String { 14 | let _path = Debug.outputPath ?? Environment.SRCROOT.element 15 | 16 | guard let path = _path else { 17 | fatalError("Can't find outputPath. Run time env: \(Environment.elements)") 18 | } 19 | return path 20 | } 21 | 22 | public struct Debug { 23 | public static let isDebug: Bool = ProcessInfo.processInfo.environment["DEBUG"] != nil 24 | public static let outputPath: String? = ProcessInfo.processInfo.environment["DEBUG_OUTPUT_PATH"] 25 | public static let projectTarget: String? = ProcessInfo.processInfo.environment["DEBUG_TARGET_NAME"] 26 | public static let projectFilePath: String? = ProcessInfo.processInfo.environment["DEBUG_PROJECT_FILE_PATH"] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoTests/StoryboardTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoryboardTests.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/05/03. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ResourceKitDemo 11 | 12 | class ViewControllerFromStoryboardTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | } 17 | 18 | override func tearDown() { 19 | super.tearDown() 20 | } 21 | 22 | func testPerformanceExample() { 23 | self.measure { 24 | } 25 | } 26 | 27 | func testInitialViewController() { 28 | XCTAssertTrue(ViewController.initialViewController().isMember(of: ViewController.classForCoder())) 29 | } 30 | 31 | func testInstanceFromViewController() { 32 | XCTAssertTrue(ViewController.instanceFromInstanceFromOverride().isMember(of: ViewController.classForCoder())) 33 | } 34 | 35 | func testSegueIdentifier() { 36 | XCTAssertTrue(ViewController.Segue.showSecondTable == "ShowSecondTable") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2016 Yudai hirose 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Xib/XibOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XibOutput.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol XibOutput: Output { 12 | 13 | } 14 | 15 | public struct XibOutputImpl: XibOutput { 16 | let nibName: String 17 | let className: String 18 | 19 | public var declaration: String { 20 | return [ 21 | "extension \(className) {", 22 | "\(Const.tab1)public struct Xib: XibProtocol {", 23 | "\(Const.tab2)public typealias View = \(className)", 24 | "\(Const.tab2)public static let name: String = \"\(className)\"", 25 | " ", 26 | "\(Const.tab2)public static func nib() -> UINib {", 27 | "\(Const.tab3)return UINib(nibName: \"\(nibName)\", bundle: Bundle(for: \(className).classForCoder()))", 28 | "\(Const.tab2)}", 29 | "", 30 | "\(Const.tab2)public static func view() -> \(className) {", 31 | "\(Const.tab3)return nib().instantiate(withOwner: nil, options: nil)[0] as! \(className)", 32 | "\(Const.tab2)}", 33 | "", 34 | "\(Const.tab1)}", 35 | "}", 36 | ].joined(separator: Const.newLine) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/ViewController/ViewControllerTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerTranslator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct ViewControllerTranslator: Translator { 12 | public let config: Config 13 | public let viewControllers: [ViewController] 14 | 15 | public init( 16 | config: Config, 17 | viewControllers: [ViewController] 18 | ) { 19 | self.config = config 20 | self.viewControllers = viewControllers 21 | } 22 | 23 | func superClass(for viewController: ViewController) -> ViewController? { 24 | return viewControllers 25 | .filter ({ $0.className == viewController.superClassName }) 26 | .first 27 | } 28 | 29 | public func translate(for input: ViewController) throws -> ViewControllerOutput { 30 | let superClassViewController = superClass(for: input) 31 | return ViewControllerOutputImpl( 32 | name: input.name, 33 | storyboardInfos: input.storyboardInfos, 34 | hasSuperClass: superClassViewController != nil, 35 | superClassStoryboardInfos: superClassViewController?.storyboardInfos ?? [], 36 | config: config 37 | ) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/SecondTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondTableViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondTableViewController: UITableViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | tableView.reloadData() 17 | } 18 | 19 | // MARK: - Table view data source 20 | 21 | override func numberOfSections(in tableView: UITableView) -> Int { 22 | // #warning Incomplete implementation, return the number of sections 23 | return 1 24 | } 25 | 26 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 27 | // #warning Incomplete implementation, return the number of rows 28 | return 40 29 | } 30 | 31 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 32 | let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.Reusable.name, for: indexPath) as! SecondTableViewCell 33 | cell.label.text = "Second" 34 | return cell 35 | } 36 | 37 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 38 | performSegueShowOverride() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Image/ImageTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageTranslator.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct ImageTranslator: Translator { 12 | public typealias Input = (assets: Image.Assets, resources: Image.Resources) 13 | public typealias Output = ImageOutputer 14 | 15 | let config: Config 16 | 17 | public init( 18 | config: Config 19 | ) { 20 | self.config = config 21 | } 22 | 23 | public func translate(for input: Input) throws -> Output { 24 | return ImageOutputerImpl( 25 | assetsOutputer: try ImageAssetsTranslator().translate(for: input.assets), 26 | resourcesOutputer: try ImageeResourcesTranslator().translate(for: input.resources), 27 | config: config 28 | ) 29 | } 30 | } 31 | 32 | public struct ImageAssetsTranslator: Translator { 33 | public init() { } 34 | public func translate(for input: Image.Assets) throws -> ImageOutputer { 35 | return ImageOutputerImpl.AssetsOutputer(imageNames: input.imageNames) 36 | } 37 | } 38 | 39 | public struct ImageeResourcesTranslator: Translator { 40 | public init() { } 41 | public func translate(for input: Image.Resources) throws -> ImageOutputer { 42 | return ImageOutputerImpl.ResourcesOutputer(imageNames: input.imageNames) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/TableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/LocalizedString/LocalizedStringOutputer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedStringOutputer.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/22. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol LocalizedStringOutputer: Output { 12 | 13 | } 14 | 15 | public struct LocalizedStringOutputerImpl: LocalizedStringOutputer { 16 | let localizedStrings: [String: String] 17 | 18 | public var declaration: String { 19 | return [ 20 | "extension String {", 21 | "\(Const.tab1)public struct Localized {", 22 | "\(generateLocalizableConstants().joined(separator: Const.newLine))", 23 | "\(Const.tab1)}", 24 | "}", 25 | ].joined(separator: Const.newLine) 26 | } 27 | } 28 | 29 | fileprivate extension LocalizedStringOutputerImpl { 30 | fileprivate func generateLocalizableConstants() -> [String] { 31 | func toConstantName(_ key: String) -> String { 32 | return key 33 | .replacingOccurrences(of: "[^a-z,^A-Z,^0-9]", with: "_", options: .regularExpression, range: nil) 34 | .replacingOccurrences(of: ",", with: "_", options: .regularExpression, range: nil) 35 | 36 | } 37 | return localizedStrings.keys.flatMap { 38 | return "\(Const.tab2)public static let \(toConstantName($0)) = NSLocalizedString(\"\($0)\", comment: \"\")" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/ViewController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // viewcontroller.swift 3 | // ResourceKit 4 | // 5 | // Created by Hirose.Yudai on 2016/04/06. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class ViewControllerInfoOfStoryboard { 12 | let viewControllerId: String 13 | let storyboardName: String 14 | let initialViewControllerId: String? 15 | let storyboardIdentifier: String 16 | 17 | var segues: [String] = [] 18 | 19 | init(viewControllerId: String, 20 | storyboardName: String, 21 | initialViewControllerId: String?, 22 | storyboardIdentifier: String) { 23 | self.viewControllerId = viewControllerId 24 | self.storyboardName = storyboardName 25 | self.initialViewControllerId = initialViewControllerId 26 | self.storyboardIdentifier = storyboardIdentifier 27 | } 28 | 29 | var isInitial: Bool { 30 | return viewControllerId == initialViewControllerId 31 | } 32 | } 33 | 34 | public class ViewController { 35 | var storyboardInfos: [ViewControllerInfoOfStoryboard] = [] 36 | let className: ResourceType 37 | let superClassName: ResourceType 38 | 39 | init(className: String, superClassName: String = "") throws { 40 | self.className = try ResourceType(viewController: className) 41 | self.superClassName = try ResourceType(viewController: superClassName) 42 | } 43 | 44 | var name: String { 45 | return className.name 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/SecondCollectionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondCollectionViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondCollectionViewController: UICollectionViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | collectionView?.reloadData() 16 | } 17 | 18 | // MARK: UICollectionViewDataSource 19 | 20 | override func numberOfSections(in collectionView: UICollectionView) -> Int { 21 | // #warning Incomplete implementation, return the number of sections 22 | return 1 23 | } 24 | 25 | 26 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 27 | // #warning Incomplete implementation, return the number of items 28 | return 100 29 | } 30 | 31 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 32 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SecondCollectionViewCell.Reusable.name, for: indexPath) as! SecondCollectionViewCell 33 | cell.label.text = "\(indexPath.item)" 34 | return cell 35 | } 36 | 37 | 38 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 39 | navigationController?.pushViewController(OverrideViewController.initialViewController(), animated: true) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjectiveCTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/ViewController/ViewControllerResourceType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerResourceType.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum ViewControllerResourceType: String { 12 | case UIViewController 13 | case UITabBarController 14 | case UIPageViewController 15 | case UITableViewController 16 | case UISplitViewController 17 | case UINavigationController 18 | case UICollectionViewController 19 | 20 | init?(name: String) { 21 | switch name { 22 | case "viewController": 23 | self = .UIViewController 24 | case "tabBarController": 25 | self = .UITabBarController 26 | case "pageViewController": 27 | self = .UIPageViewController 28 | case "tableViewController": 29 | self = .UITableViewController 30 | case "splitViewController": 31 | self = .UISplitViewController 32 | case "navigationController": 33 | self = .UINavigationController 34 | case "collectionViewController": 35 | self = .UICollectionViewController 36 | default: return nil 37 | } 38 | } 39 | 40 | static func standards() -> [ViewControllerResourceType] { 41 | return [ 42 | .UIViewController, 43 | .UITabBarController, 44 | .UIPageViewController, 45 | .UITableViewController, 46 | .UISplitViewController, 47 | .UINavigationController, 48 | .UICollectionViewController 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ObjCOverrideViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Imports/ImportOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImportOutput.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/23. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ImportOutput: Output { 12 | 13 | } 14 | 15 | public struct ImportOutputImpl: ImportOutput { 16 | public let writeUrl: URL 17 | public let config: Config 18 | 19 | public init( 20 | writeUrl: URL, 21 | config: Config 22 | ) { 23 | self.writeUrl = writeUrl 24 | self.config = config 25 | } 26 | 27 | func imports() -> [String] { 28 | guard let content = try? String(contentsOf: writeUrl) else { 29 | return config.segue.addition ? ["import UIKit", "import SegueAddition"] : ["import UIKit"] 30 | } 31 | let pattern = "\\s*import\\s+.+" 32 | guard let regex = try? NSRegularExpression(pattern: pattern, options: .useUnixLineSeparators) else { 33 | return ["import UIKit"] 34 | } 35 | let results = regex.matches(in: content, options: [], range: NSMakeRange(0, content.characters.count)) 36 | 37 | if results.isEmpty { 38 | return config.segue.addition ? ["import UIKit", "import SegueAddition"] : ["import UIKit"] 39 | } 40 | 41 | return results.flatMap { (result) -> String? in 42 | if result.range.location != NSNotFound { 43 | let matchingString = (content as NSString).substring(with: result.range) as String 44 | return matchingString 45 | .replacingOccurrences(of: "\n", with: "") 46 | } 47 | return nil 48 | } 49 | } 50 | 51 | public var declaration: String { 52 | return imports().joined(separator: Const.newLine) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Environment.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Environment.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/24. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XcodeProject 11 | 12 | extension Environment { 13 | public var element: String? { 14 | if ResourceKitConfig.Debug.isDebug { 15 | return ProcessInfo.processInfo.environment["DEBUG_" + self.rawValue]! 16 | } 17 | let element = ProcessInfo.processInfo.environment[self.rawValue] 18 | return element 19 | } 20 | 21 | public var path: URL { 22 | guard let element = element else { 23 | let message: String = [ 24 | "Unexpected value for xcode environment when use Environment.element property.", 25 | "file: \(#file)", 26 | "line: \(#line)", 27 | "function: \(#function)", 28 | "rawValue: \(self.rawValue)", 29 | ].reduce("") 30 | { $0 + $1 + "\n" } 31 | fatalError("message: \(message) ") 32 | } 33 | return URL(fileURLWithPath: element) 34 | } 35 | 36 | public static func pathFrom(_ path: PathComponent) -> URL { 37 | switch path { 38 | case .simple(let absolutePath): 39 | return URL(fileURLWithPath: absolutePath) 40 | case .environmentPath(let environement, let relativePath): 41 | return environement 42 | .path 43 | .appendingPathComponent(relativePath) 44 | } 45 | } 46 | 47 | public static func verifyUseEnvironment() throws { 48 | if let empty = elements.filter ({ ProcessInfo.processInfo.environment[$0.rawValue] == nil }).first { 49 | throw ResourceKitErrorType.environmentError(environmentKey: empty.rawValue, errorInfo: ResourceKitErrorType.createErrorInfo()) 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/TableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewController: UITableViewController { 12 | let localized = [ 13 | String.Localized.hello_world_4, 14 | String.Localized.hello_world_07, 15 | String.Localized.hello_world_2, 16 | String.Localized.hello_world_10, 17 | String.Localized.hello_world_09, 18 | String.Localized.hello_world_08, 19 | String.Localized.hello_world_06, 20 | String.Localized.hello_world_1, 21 | String.Localized.hello_world_05, 22 | String.Localized.helloworld, 23 | String.Localized.hello_world_3 24 | ] 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | 29 | tableView.register(xib: TableViewCell.Xib.self) 30 | tableView.reloadData() 31 | } 32 | 33 | // MARK: - Table view data source 34 | override func numberOfSections(in tableView: UITableView) -> Int { 35 | // #warning Incomplete implementation, return the number of sections 36 | return 1 37 | } 38 | 39 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 40 | // #warning Incomplete implementation, return the number of rows 41 | return localized.count 42 | } 43 | 44 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 45 | let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.Xib.name, for: indexPath) // TODO: Support Generics Type 46 | cell.textLabel?.text = localized[indexPath.row] 47 | return cell 48 | } 49 | 50 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 51 | navigationController?.pushViewController(ViewController.initialViewController(), animated: true) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Error.swift: -------------------------------------------------------------------------------- 1 | // 2 | // error.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/07/10. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | public enum ResourceKitErrorType: Error { 13 | case spcifiedPathError(path: String, errorInfo: String) 14 | case environmentError(environmentKey: String, errorInfo: String) 15 | case configError(configType: String, errorInfo: String) 16 | case xcodeProjectError(xcodeURL: URL, target: String, errorInfo: String) 17 | case xcodeProjectAllTargetError(xcodeURL: URL, target: String, allTargetName: String, errorInfo: String) 18 | case regexError(errorInfo: String) 19 | case resourceParseError(name: String, errorInfo: String) 20 | case writeError(path: String, code: String, errorInfo: String) 21 | 22 | 23 | public func description() -> String { 24 | switch self { 25 | case .spcifiedPathError(let path, let errorInfo): 26 | return "path: \(path), errorInfo: \(errorInfo)" 27 | case .environmentError(let environmentKey, let errorInfo): 28 | return "environmentKey: \(environmentKey), errorInfo: \(errorInfo)" 29 | case .configError(let configType, let errorInfo): 30 | return "configType: \(configType), errorInfo: \(errorInfo)" 31 | case .xcodeProjectError(let xcodeURL, let target, let errorInfo): 32 | return "xcodeURL: \(xcodeURL.absoluteString), target: \(target), errorInfo: \(errorInfo)" 33 | case .xcodeProjectAllTargetError(let xcodeURL, let target, let allTargetName, let errorInfo): 34 | return "xcodeURL: \(xcodeURL.absoluteString), target: \(target), allTargetName: \(allTargetName),errorInfo: \(errorInfo)" 35 | case .regexError(let errorInfo): 36 | return "errorInfo: \(errorInfo)" 37 | case .resourceParseError(let name, let errorInfo): 38 | return "name: \(name), errorInfo:\(errorInfo)" 39 | case .writeError(let path, let code, let errorInfo): 40 | return "path: \(path), code: \(code), errorInfo:\(errorInfo)" 41 | } 42 | } 43 | 44 | static func createErrorInfo(_ file: String = #file, line: Int = #line) -> String { 45 | return "file: \(file), line: \(line)" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Image/ImageEntity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageEntity.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Image { 12 | // let assets: Assets 13 | // let resources: Resources 14 | // 15 | // init(urls: [URL]) { 16 | // assets = Assets(urls: urls) 17 | // resources = Resources(urls: urls) 18 | // } 19 | } 20 | 21 | extension Image { 22 | public struct Assets { 23 | let imageNames: [String] 24 | 25 | init(urls: [URL]) { 26 | let xcassets = urls 27 | .filter { $0.pathExtension == "xcassets" } 28 | .flatMap { 29 | FileManager 30 | .default 31 | .enumerator( 32 | at: $0, 33 | includingPropertiesForKeys: nil, 34 | options: .skipsHiddenFiles, 35 | errorHandler: nil 36 | ) 37 | } 38 | 39 | imageNames = xcassets 40 | .flatMap { $0.flatMap { url in url as? URL } } 41 | .filter { $0.pathExtension == "imageset"} 42 | .flatMap { $0.deletingPathExtension().lastPathComponent } 43 | } 44 | 45 | } 46 | } 47 | 48 | extension Image { 49 | public struct Resources { 50 | static let supportExtensions: Set = [ "png", "jpg", "gif" ] 51 | let imageNames: [String] 52 | 53 | init(urls: [URL]) { 54 | imageNames = urls 55 | .filter { Resources.supportExtensions.contains($0.pathExtension) } 56 | .flatMap { $0.deletingPathExtension().lastPathComponent } 57 | .flatMap { (name: String) -> String? in 58 | // find @2x, @3x pattern 59 | let pattern = "@[0-9]x" 60 | let regex = try? NSRegularExpression(pattern: pattern, options: .useUnixLineSeparators) 61 | let result = regex?.matches(in: name, options: [], range: NSMakeRange(0, name.characters.count)).first 62 | 63 | // if not exists, return is not value 64 | if result != nil { 65 | return nil 66 | } 67 | return name 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/CustomView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemoUITests/ResourceKitDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceKitDemoUITests.swift 3 | // ResourceKitDemoUITests 4 | // 5 | // Created by kingkong999yhirose on 2016/04/10. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ResourceKitDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testCollection_Custom_SecondCollection_SecondCustom_SecondCollection() { 32 | let app = XCUIApplication() 33 | app.tabBars.children(matching: .button).matching(identifier: "Item").element(boundBy: 1).tap() 34 | app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .collectionView).element.tap() 35 | app.buttons["SecondCollectionViewController"].tap() 36 | app.collectionViews/*@START_MENU_TOKEN@*/.staticTexts["52"]/*[[".cells.staticTexts[\"52\"]",".staticTexts[\"52\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() 37 | app.buttons["SecondCollectionViewController"].tap() 38 | } 39 | 40 | func testTable_Custom_SecondTable_SecondCustom_SecondTable() { 41 | let app = XCUIApplication() 42 | app.tables.children(matching: .cell).element(boundBy: 0).staticTexts["hello world 4"].tap() 43 | app.buttons["SecondTableViewController"].tap() 44 | app.tables.children(matching: .cell).element(boundBy: 1).staticTexts["Second"].tap() 45 | app.buttons["SecondTableViewController"].tap() 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Parser/XibParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XibParser.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/05/03. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol XibParser: Parsable { 12 | 13 | } 14 | 15 | public class XibPerserImpl: NSObject, XibParser { 16 | let url: URL 17 | let resource: AppendableForXibs 18 | 19 | fileprivate var name: String = "" 20 | // should parse for root view 21 | // ResourceKit not support second xib view 22 | fileprivate var isOnce: Bool = false 23 | fileprivate let ignoreCase = [ 24 | "UIResponder" 25 | ] 26 | 27 | public init(url: URL, writeResource resource: AppendableForXibs) throws { 28 | self.url = url 29 | self.resource = resource 30 | 31 | super.init() 32 | } 33 | 34 | public func parse() throws { 35 | guard url.pathExtension == "xib" else { 36 | throw ResourceKitErrorType.spcifiedPathError(path: url.absoluteString, errorInfo: ResourceKitErrorType.createErrorInfo()) 37 | } 38 | 39 | name = url.deletingPathExtension().lastPathComponent 40 | // Don't create ipad resources 41 | if name.contains("~") { 42 | return 43 | } 44 | 45 | guard let parser = XMLParser(contentsOf: url) else { 46 | throw ResourceKitErrorType.spcifiedPathError(path: url.absoluteString, errorInfo: ResourceKitErrorType.createErrorInfo()) 47 | } 48 | 49 | parser.delegate = self 50 | parser.parse() 51 | } 52 | 53 | public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 54 | generateXibs(attributeDict, elementName: elementName) 55 | } 56 | 57 | fileprivate func generateXibs(_ attributes: [String: String], elementName: String) { 58 | if isOnce { 59 | return 60 | } 61 | 62 | guard let className = attributes["customClass"] else { 63 | return 64 | } 65 | 66 | if ignoreCase.contains(className) { 67 | return 68 | } 69 | 70 | let hasFilesOwner = attributes.flatMap ({ $1 }).contains("IBFilesOwner") 71 | if hasFilesOwner { 72 | return 73 | } 74 | 75 | isOnce = true 76 | 77 | resource 78 | .appendXib( 79 | Xib( 80 | nibName: name, 81 | className: className, 82 | isFilesOwner: hasFilesOwner 83 | ) 84 | ) 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Extensions/ExtensionsOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionsOutput.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/23. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct ExtensionsOutputImpl { 12 | public init() { } 13 | public let reusableProtocolContent: String = [ 14 | "public protocol ReusableProtocol {", 15 | " associatedtype View", 16 | " static var name: String { get }", 17 | "}", 18 | ].joined(separator: Const.newLine) 19 | 20 | public let xibProtocolContent: String = [ 21 | "public protocol XibProtocol: ReusableProtocol {", 22 | "\(Const.tab1)static func nib() -> UINib", 23 | "\(Const.tab1)static func view() -> View", 24 | "}", 25 | ].joined(separator: Const.newLine) 26 | 27 | public let tableViewExtensionContent: String = [ 28 | "public extension UITableView {", 29 | "\(Const.tab1)public func register(xib: X.Type) -> Void where X.View: UITableViewCell {", 30 | "\(Const.tab2)register(xib.nib(), forCellReuseIdentifier: xib.name)", 31 | "\(Const.tab1)}", 32 | " ", 33 | "\(Const.tab1)public func register(xibs: [X.Type]) -> Void where X.View: UITableViewCell {", 34 | "\(Const.tab2)xibs.forEach { register(xib: $0) }", 35 | "\(Const.tab1)}", 36 | " ", 37 | "\(Const.tab1)public func dequeueReusableCell(with reusable: R.Type, for indexPath: IndexPath) -> R.View where R.View: UITableViewCell {", 38 | "\(Const.tab2)return dequeueReusableCell(withIdentifier: reusable.name, for: indexPath) as! R.View", 39 | "\(Const.tab1)}", 40 | "}", 41 | ].joined(separator: Const.newLine) 42 | 43 | public let collectionViewExtensionContent = [ 44 | "extension UICollectionView {", 45 | "\(Const.tab1)public func register(xib: X.Type) -> Void where X.View: UICollectionViewCell {", 46 | "\(Const.tab2)register(xib.nib(), forCellWithReuseIdentifier: xib.name)", 47 | "\(Const.tab1)}", 48 | " ", 49 | "\(Const.tab1)public func register(xibs: [X.Type]) -> Void where X.View: UICollectionViewCell {", 50 | "\(Const.tab2)xibs.forEach { register(xib: $0) }", 51 | "\(Const.tab1)}", 52 | " ", 53 | "\(Const.tab1)public func dequeueReusableCell(with reusable: R.Type, for indexPath: IndexPath) -> R.View where R.View: UICollectionViewCell {", 54 | "\(Const.tab2)return dequeueReusableCell(withReuseIdentifier: reusable.name, for: indexPath) as! R.View", 55 | "\(Const.tab1)}", 56 | "}", 57 | ].joined(separator: Const.newLine) 58 | } 59 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/CollectionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewController.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/11. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { 12 | 13 | class var baseShoyus: [UIImage] { 14 | return [ 15 | UIImage.Asset.curry, 16 | UIImage.Asset.ebi, 17 | UIImage.Asset.inaka, 18 | UIImage.Asset.kake, 19 | UIImage.Asset.kaki, 20 | UIImage.Asset.kikkoman, 21 | UIImage.Asset.koori, 22 | UIImage.Asset.koumi, 23 | UIImage.Asset.marudaizu, 24 | UIImage.Asset.ninniku, 25 | UIImage.Asset.siro, 26 | UIImage.Asset.ususio 27 | ] 28 | } 29 | 30 | var shoyus: [UIImage] = Array(repeating: CollectionViewController.baseShoyus, count: 10).flatMap { $0 } 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | collectionView?.register(xib: CollectionViewCell.Xib.self) 36 | collectionView?.reloadData() 37 | } 38 | 39 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 40 | if segue.identifier != CollectionViewController.Segue.showViewController { 41 | fatalError("\(#file) + \(#function) + \(#line)") 42 | } 43 | 44 | segue.destination.title = sender as? String 45 | } 46 | 47 | // MARK: UICollectionViewDataSource 48 | override func numberOfSections(in collectionView: UICollectionView) -> Int { 49 | return 1 50 | } 51 | 52 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 53 | return shoyus.count 54 | } 55 | 56 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 57 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.Xib.name, for: indexPath) as! CollectionViewCell // TODO: Support Generics Type 58 | cell.setupWith(shoyus[indexPath.item]) // TODO: Support UIImage Name 59 | return cell 60 | } 61 | 62 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 63 | let width = UIScreen.main.bounds.width / 3 - 2 64 | return CGSize(width: width, height: width) 65 | } 66 | 67 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 68 | performSegueShowViewController() 69 | } 70 | 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Resource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Resource.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/04/15. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | enum ResourceType: Equatable { 13 | case standard(String) 14 | case custom(String) 15 | 16 | static func isSegue(_ elementName: String) -> Bool { 17 | return elementName == "segue" 18 | } 19 | 20 | static func isTableViewCell(_ elementName: String) -> Bool { 21 | if let reusable = ReusableResourceType(name: elementName) 22 | , reusable == .UITableViewCell { 23 | return true 24 | } 25 | 26 | return false 27 | } 28 | 29 | static func isCollectionViewCell(_ elementName: String) -> Bool { 30 | if let reusable = ReusableResourceType(name: elementName) 31 | , reusable == .UICollectionViewCell { 32 | return true 33 | } 34 | 35 | return false 36 | } 37 | 38 | static func isReusableStandardType(_ elementName: String) -> Bool { 39 | return isTableViewCell(elementName) || isCollectionViewCell(elementName) 40 | } 41 | 42 | static func isViewControllerStandardType(_ elementName: String) -> Bool { 43 | if let _ = ViewControllerResourceType(name: elementName) { 44 | return true 45 | } 46 | 47 | return false 48 | } 49 | 50 | init(reusable: String) throws { 51 | if ResourceType.isReusableStandardType(reusable) { 52 | guard let resource = ReusableResourceType(name: reusable) else { 53 | throw ResourceKitErrorType.resourceParseError(name: reusable, errorInfo: ResourceKitErrorType.createErrorInfo()) 54 | } 55 | self = .standard(resource.rawValue) 56 | return 57 | } 58 | 59 | self = .custom(reusable) 60 | } 61 | 62 | init(viewController: String) throws { 63 | if ResourceType.isViewControllerStandardType(viewController) { 64 | guard let resource = ViewControllerResourceType(name: viewController) else { 65 | throw ResourceKitErrorType.resourceParseError(name: viewController, errorInfo: ResourceKitErrorType.createErrorInfo()) 66 | } 67 | self = .standard(resource.rawValue) 68 | return 69 | } 70 | 71 | self = .custom(viewController) 72 | } 73 | 74 | var name: String { 75 | switch self { 76 | case .standard(let standard): 77 | return standard 78 | case .custom(let custom): 79 | return custom 80 | } 81 | } 82 | } 83 | 84 | func ==(lhs: ResourceType, rhs: ResourceType) -> Bool { 85 | return lhs.name == rhs.name 86 | } 87 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ResourceKitDemo 4 | // 5 | // Created by kingkong999yhirose on 2016/04/10. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | let tabBarController = UITabBarController.initialViewController() 19 | window = UIWindow(frame: UIScreen.main.bounds) 20 | window?.rootViewController = tabBarController 21 | window?.addSubview(tabBarController.view) 22 | window?.makeKey() 23 | 24 | window?.isHidden = false // Why wndow is hidden = true ??? 25 | 26 | runtimeValidationViewControllerFromStoryboard() 27 | 28 | return true 29 | } 30 | 31 | fileprivate func runtimeValidationViewControllerFromStoryboard() { 32 | ObjCViewController.initialViewController() 33 | ObjCOveerrideViewController.initialViewController() 34 | } 35 | 36 | func applicationWillResignActive(_ application: UIApplication) { 37 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 38 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 39 | } 40 | 41 | func applicationDidEnterBackground(_ application: UIApplication) { 42 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 44 | } 45 | 46 | func applicationWillEnterForeground(_ application: UIApplication) { 47 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 48 | } 49 | 50 | func applicationDidBecomeActive(_ application: UIApplication) { 51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 52 | } 53 | 54 | func applicationWillTerminate(_ application: UIApplication) { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Resources/ProjectResource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Project.swift 3 | // ResourceKit 4 | // 5 | // Created by Hirose.Yudai on 2016/04/07. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class ProjectResource { 12 | public static let shared: ProjectResource = ProjectResource() 13 | 14 | fileprivate init() { } 15 | 16 | public fileprivate(set) var paths: [URL] = [] 17 | public fileprivate(set) var localizablePaths: [URL] = [] 18 | 19 | public var viewControllers: [ViewController] = [] 20 | 21 | public fileprivate(set) var tableViewCells: [TableViewCell] = [] 22 | public fileprivate(set) var collectionViewCells: [CollectionViewCell] = [] 23 | public fileprivate(set) var xibs: [Xib] = [] 24 | } 25 | 26 | extension ProjectResource: AppendableForPaths { 27 | public func appendFileReferencePaths(urls: [URL]) { 28 | paths.append(contentsOf: urls) 29 | } 30 | 31 | public func appendLocalizedPaths(urls: [URL]) { 32 | localizablePaths.append(contentsOf: urls) 33 | } 34 | } 35 | 36 | extension ProjectResource: AppendableForXibs { 37 | public func appendXib(_ xib: Xib) { 38 | if xibs.contains(where: { $0.className == xib.className }) { 39 | return 40 | } 41 | xibs.append(xib) 42 | } 43 | } 44 | 45 | extension ProjectResource: AppendableForStoryboard { 46 | public func appendTableViewCell(_ className: String, reusableIdentifier: String) { 47 | guard let cell = tableViewCells 48 | .filter ({ $0.className == className}) 49 | .first else { 50 | tableViewCells.append( 51 | TableViewCell( 52 | reusableIdentifier: reusableIdentifier, 53 | className: className 54 | ) 55 | ) 56 | return 57 | } 58 | 59 | cell.reusableIdentifiers.insert(reusableIdentifier) 60 | } 61 | 62 | public func appendCollectionViewCell(_ className: String, reusableIdentifier: String) { 63 | guard let cell = collectionViewCells 64 | .filter ({ $0.className == className}) 65 | .first else { 66 | collectionViewCells.append( 67 | CollectionViewCell ( 68 | reusableIdentifier: reusableIdentifier, 69 | className: className 70 | ) 71 | ) 72 | return 73 | } 74 | 75 | cell.reusableIdentifiers.insert(reusableIdentifier) 76 | } 77 | 78 | public func appendViewControllerInfoReference(_ className: String?, viewControllerInfo: ViewControllerInfoOfStoryboard) { 79 | viewControllers 80 | .filter({ $0.name == className }) 81 | .first? 82 | .storyboardInfos 83 | .append(viewControllerInfo) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Image/ImageOutputer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageOutputer.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/08/09. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | public protocol ImageOutputer: Output { 13 | var begin: String { get } 14 | var body: String { get } 15 | var end: String { get } 16 | } 17 | 18 | public extension ImageOutputer { 19 | var declaration: String { 20 | return [begin, body, end].joined(separator: Const.newLine) 21 | } 22 | } 23 | 24 | public struct ImageOutputerImpl: ImageOutputer { 25 | let assetsOutputer: ImageOutputer 26 | let resourcesOutputer: ImageOutputer 27 | let config: Config 28 | 29 | static func imageFunction(_ withName: String) -> String { 30 | return "UIImage(named: \"\(withName)\")!" 31 | } 32 | 33 | public var begin: String { 34 | return "extension UIImage {" 35 | } 36 | 37 | public var body: String { 38 | guard 39 | config.image.assetCatalog || config.image.projectResource 40 | else { 41 | return "" 42 | } 43 | if !config.image.assetCatalog { 44 | return resourcesOutputer.declaration 45 | } 46 | if !config.image.projectResource { 47 | return assetsOutputer.declaration 48 | } 49 | 50 | return assetsOutputer.declaration 51 | + Const.newLine 52 | + resourcesOutputer.declaration 53 | } 54 | 55 | public var end: String { 56 | return "}" + Const.newLine 57 | } 58 | } 59 | 60 | extension ImageOutputerImpl { 61 | public struct AssetsOutputer: ImageOutputer { 62 | let imageNames: [String] 63 | 64 | public var begin: String { 65 | return "\(Const.tab1)public struct Asset {" 66 | } 67 | public var body: String { 68 | let body = imageNames 69 | .flatMap { "\(Const.tab2)public static let \($0): UIImage = \(ImageOutputerImpl.imageFunction($0))" } 70 | .joined(separator: Const.newLine) 71 | return body 72 | } 73 | public var end: String { 74 | return "\(Const.tab1)}" + Const.newLine 75 | } 76 | } 77 | } 78 | 79 | extension ImageOutputerImpl { 80 | public struct ResourcesOutputer: ImageOutputer { 81 | let imageNames: [String] 82 | 83 | public var begin: String { 84 | return "\(Const.tab1)public struct Resource {" 85 | } 86 | public var body: String { 87 | let body = imageNames 88 | .flatMap { "\(Const.tab2)public static let \($0): UIImage = \(ImageOutputerImpl.imageFunction($0))" } 89 | .joined(separator: Const.newLine) 90 | return body 91 | } 92 | public var end: String { 93 | return "\(Const.tab1)}" + Const.newLine 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Documents/Examples.md: -------------------------------------------------------------------------------- 1 | ## ViewController from Storyboard 2 | 3 | #### initialViewController 4 | 5 | _Standard_ 6 | ```swift 7 | let storyboard = UIStoryboard(name: "Storyboard", bundle: nil) 8 | let viewController = storyboard.initialViewController() as! ViewController 9 | ``` 10 | 11 | _Use ResourceKit_ 12 | ```swift 13 | let viewController = ViewController.initialViewController() 14 | ``` 15 | 16 | #### instance from storyboard 17 | _Standard_ 18 | ```swift 19 | let storyboard = UIStoryboard(name: "Storyboard", bundle: nil) 20 | let viewController = storyboard.instantiateViewController(withIdentifier: "XXXX") as! ViewController 21 | ``` 22 | 23 | _Use ResourceKit_ 24 | ```swift 25 | let viewController = ViewController.instanceFromStoryboard() 26 | ``` 27 | 28 | #### if same class in instance from storyboard 29 | _standard_ 30 | ```swift 31 | let storyboard = UIStoryboard(name: "Storyboard", bundle: nil) 32 | let viewController1 = storyboard.instantiateViewController(withIdentifier: "XXXX") as! ViewController 33 | let viewController2 = storyboard.instantiateViewController(withIdentifier: "YYYY") as! ViewController 34 | ``` 35 | 36 | _Use ResourceKit_ 37 | ```swift 38 | let viewController1 = ViewController.instanceFromStoryboardXXXX() 39 | let viewController2 = ViewController.instanceFromStoryboardYYYY() 40 | ``` 41 | 42 | ## Use segue any UIViewController sub class 43 | 44 | _standard_ 45 | ```swift 46 | ... 47 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 48 | if segue.identifier == "Open" { 49 | // something... 50 | } 51 | } 52 | ... 53 | 54 | performSegueWithIdentifier("Open", sender: sender) 55 | ``` 56 | 57 | _Use ResourceKit_ 58 | ```swift 59 | // In CustomViewController class. 60 | ... 61 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 62 | if segue.identifier == CustomViewController.Segue.open { 63 | // something... 64 | } 65 | } 66 | ... 67 | 68 | performSegueOpen() // or performSegueOpen(sender: AnyObject?) 69 | ``` 70 | 71 | ## Nib 72 | #### create instance from .xib 73 | _standard_ 74 | ```swift 75 | let nib = UINib(nibName: "TableViewCell", bundle: nil) 76 | let cell nib.instantiate(withOwner: nil, options: nil)[0] as! TableViewCell 77 | ``` 78 | 79 | _Use ResourceKit_ 80 | ```swift 81 | let customView = CustomView.Xib.view() 82 | ``` 83 | #### for tableview or collectionview 84 | _standard_ 85 | ```swift 86 | let nib = UINib(nibName: "CollectionViewCell", bundle: nil) 87 | collectionView?.registerNib(nib, forCellWithReuseIdentifier: "ReusableIdentifier") 88 | 89 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ReusableIdentifier", forIndexPath: indexPath) as! CollectionViewCell 90 | 91 | ``` 92 | 93 | _Use ResourceKit_ 94 | ```swift 95 | collectionView?.registerNib(xib: CollectionViewCell.Xib.self) 96 | 97 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier(CollectionViewCell.Xib().name, forIndexPath: indexPath) as! CollectionViewCell 98 | ``` 99 | 100 | ## Reusalbes 101 | #### use storyboard 102 | _standard_ 103 | ```swift 104 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ReusableIdentifier", forIndexPath: indexPath) as! CollectionViewCell 105 | ``` 106 | 107 | _Use ResourceKit_ 108 | ```swift 109 | 110 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier(CollectionViewCell.Reusable.ReuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell 111 | ``` 112 | 113 | ## UIImage 114 | _Use Asset Catalog_ 115 | ```swift 116 | let image = UIImage.Asset.image_name 117 | ``` 118 | 119 | _Not use Asset Catalog_ 120 | ```swift 121 | let image = UIImage.Resource.image_name 122 | ``` 123 | 124 | ## LocalizedString 125 | ```swift 126 | let string = String.Localized.hello_world 127 | // == NSLocalizedString("hello world", comment: "") 128 | ``` 129 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/InstanceFromOverride.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/CollectionViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/OverrideViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ResourceKit 2 | [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) 3 | ![platform](https://cocoapod-badges.herokuapp.com/p/ResourceKit/badge.png) 4 | 5 | 6 | Enable autocomplete use resources in swift project. 7 | 8 | [まだハードコードで消耗してるの? ResourceKitで安全コーディング!](http://qiita.com/bannzai/items/e9bf5904940fb1ed5082) 9 | 10 | ## How does ResourceKit work? 11 | ResouceKit makes your code that uses write for resources: 12 | - `Becomes clear`, nessary to cast and guessing easy what a method will return. 13 | - `Checked`, the mistaken character doesn't enter your app code. 14 | - `Autocompleted`, never have to exist hard code when using resource. 15 | 16 | ##### Standard use resources. 17 | 18 | ```swift 19 | // Get ViewController 20 | let storyboard = UIStoryboard(name: "Storyboard", bundle: nil) 21 | let viewController = storyboard.instantiateViewController(withIdentifier: "XXXX") as! ViewController 22 | 23 | // PerformSegue 24 | performSegue(withIdentifier: "Open", sender: sender) 25 | 26 | // Nib 27 | let nib = UINib(nibName: "TableViewCell", bundle: nil) 28 | let cell = nib.instantiate(withOwner: nil, options: nil)[0] as! TableViewCell 29 | ``` 30 | Please see `ResouceKitDemo` for more information, or [Examples.md](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md) 31 | 32 | ##### Use ResourceKit. 33 | ```swift 34 | // Get ViewController 35 | let viewController = ViewController.instanceFromStoryboard() // <- viewController is ViewController class. 36 | 37 | // PerformSegue 38 | performSegueOpen() // <- can write to use autocomplete. 39 | 40 | // Nib 41 | let cell = TableViewCell.Xib.view() // <- easy get instance. 42 | ``` 43 | 44 | 45 | ## Features 46 | 47 | After installing ResourceKit into your project, and build it. 48 | ResourceKit will correct any missing/changed/added resources. 49 | 50 | ResouceKit supports resource types. 51 | - [Storyboards](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md#viewcontroller-from-storyboard) 52 | - [Segues](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md#use-segue-any-uiviewcontroller-sub-class) 53 | - [Nibs](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md#nib) 54 | - [Reusables](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md#reusalbes) 55 | - [Images](https://github.com/xcodeswift/xcproj/blob/master/Sources/xcproj/PBXProj%2BHelpers.swift#L122) 56 | - [LocalizedStrings](https://github.com/bannzai/ResourceKit/blob/master/Documents/Examples.md#localizedstring) 57 | 58 | ## Installation 59 | CocoaPods is the recommended way of installation, as this avoids including any binary files into your project. 60 | 61 | ### Cocoapods 62 | 1. Add `pod 'ResourceKit'` to your Podfile and run pod install. 63 | 2. In Xcode: Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab and add a New Run Script Phase by clicking the little plus icon in the top left. 64 | 3. Drag the new Run Script phase above the Compile Sources phase and below Check Pods Manifest.lock, expand it and paste the following script: ``"$PODS_ROOT/ResourceKit/ResourceKit"`` 65 | 4. Build your project, in Finder you will now see a ResourceKit.generated.swift in the $SRCROOT-folder, drag the ResourceKit.generated.swift files into your project and uncheck Copy items if needed 66 | 67 | ### Manual 68 | 1. Download a [ResourceKit](https://github.com/bannzai/ResourceKit/releases/) , unzip it and put it your source root directory. 69 | 2. In Xcode: Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab and add a New Run Script Phase by clicking the little plus icon in the top left 70 | 3. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script: "$SRCROOT/ResourceKit" 71 | 4. Build your project, in Finder you will now see a `ResourceKit.generated.swift` in the $SRCROOT-folder, drag the `ResourceKit.generated.swift` files into your project and uncheck Copy items if needed. 72 | 73 | ## TODO: 74 | - [x] Cocoapods support. 75 | - [x] Images support. 76 | - [x] LocaliazedString Support. 77 | - [x] Adjust indent. 78 | - [x] Collaboration [SegueAddition](https://github.com/bannzai/SegueAddition). 79 | - [x] User Chose Generate Resource Support. 80 | 81 | ## Help: 82 | ##### Q.When want to use a Third party UI Library, how should it be done 83 | A. You can write `import CustomView` to `ResourceKit.generated.swift`. 84 | And build again, but It's left `import CustomView`! 85 | 86 | 87 | 88 | ## License 89 | [ResourceKit](https://github.com/bannzai/ResourceKit) is released under the MIT license. See LICENSE.txt for details. 90 | 91 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/ViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo.xcodeproj/xcuserdata/kingkong999yhirose.xcuserdatad/xcschemes/ResourceKitDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Core/Config.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Config.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/05/05. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Config { 12 | var segue: ConfigType.Segue { get } 13 | var image: ConfigType.Image { get } 14 | var string: ConfigType.LocalizedString { get } 15 | var viewController: ConfigType.ViewController { get } 16 | var nib: ConfigType.Nib { get } 17 | var reusable: ConfigType.Reusable { get } 18 | var needGenerateSegue: Bool { get } 19 | } 20 | 21 | public struct ConfigImpl: Config { 22 | public private(set) var segue: ConfigType.Segue = ConfigType.Segue() 23 | public private(set) var image: ConfigType.Image = ConfigType.Image() 24 | public private(set) var string: ConfigType.LocalizedString = ConfigType.LocalizedString() 25 | public private(set) var viewController: ConfigType.ViewController = ConfigType.ViewController() 26 | public private(set) var nib: ConfigType.Nib = ConfigType.Nib() 27 | public private(set) var reusable: ConfigType.Reusable = ConfigType.Reusable() 28 | 29 | public var needGenerateSegue: Bool { 30 | return segue.addition || segue.standard 31 | } 32 | 33 | public init(outputPath: String) { 34 | if let dictionary = NSDictionary(contentsOfFile: outputPath + "/ResourceKitConfig.plist") as? [String: AnyObject] { 35 | dictionary.forEach { (key: String , value: AnyObject) in 36 | guard let item = ConfigType.Item(rawValue: key) else { 37 | return 38 | } 39 | switch item { 40 | case .Segue: 41 | segue = ConfigType.Segue(value as? [String: Bool] ?? [:]) 42 | case .Image: 43 | image = ConfigType.Image(value as? [String: Bool] ?? [:]) 44 | case .LocalizedString: 45 | string = ConfigType.LocalizedString(value as? [String: Bool] ?? [:]) 46 | case .ViewController: 47 | viewController = ConfigType.ViewController(value as? [String: Bool] ?? [:]) 48 | case .Nib: 49 | nib = ConfigType.Nib(value as? [String: Bool] ?? [:]) 50 | case .Reusable: 51 | reusable = ConfigType.Reusable(value as? [String: Bool] ?? [:]) 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | public struct ConfigType { 59 | public enum Item: Swift.String { 60 | case Segue 61 | case Image 62 | case LocalizedString 63 | case ViewController 64 | case Nib 65 | case Reusable 66 | } 67 | 68 | public struct Segue { 69 | let standard: Bool 70 | let addition: Bool 71 | 72 | init() { 73 | standard = true 74 | addition = false 75 | } 76 | init(_ dictionary: [Swift.String: Bool]) { 77 | standard = dictionary["Standard"] ?? false 78 | addition = dictionary["Addition"] ?? false 79 | } 80 | } 81 | 82 | public struct Image { 83 | let assetCatalog: Bool 84 | let projectResource: Bool 85 | 86 | init() { 87 | assetCatalog = true 88 | projectResource = true 89 | } 90 | init(_ dictionary: [Swift.String: Bool]) { 91 | assetCatalog = dictionary["AssetCatalog"] ?? false 92 | projectResource = dictionary["ProjectResource"] ?? false 93 | } 94 | } 95 | 96 | public struct LocalizedString { 97 | public let localized: Bool 98 | 99 | init() { 100 | localized = true 101 | } 102 | init(_ dictionary: [Swift.String: Bool]) { 103 | localized = dictionary["Localized"] ?? false 104 | } 105 | } 106 | 107 | public struct ViewController { 108 | let instantiateStoryboardForSwift: Bool 109 | let instantiateStoryboardForObjC: Bool 110 | 111 | var instantiateStoryboardAny: Bool { 112 | return instantiateStoryboardForSwift || instantiateStoryboardForObjC 113 | } 114 | 115 | init() { 116 | instantiateStoryboardForSwift = true 117 | instantiateStoryboardForObjC = true 118 | } 119 | init(_ dictionary: [Swift.String: Bool]) { 120 | instantiateStoryboardForSwift = dictionary["InstantiateStoryboardForSwift"] ?? false 121 | instantiateStoryboardForObjC = dictionary["InstantiateStoryboardForObjC"] ?? false 122 | } 123 | } 124 | 125 | public struct Nib { 126 | public let xib: Bool 127 | 128 | init() { 129 | xib = true 130 | } 131 | init(_ dictionary: [Swift.String: Bool]) { 132 | xib = dictionary["Xib"] ?? false 133 | } 134 | } 135 | 136 | public struct Reusable { 137 | public let identifier: Bool 138 | 139 | init() { 140 | identifier = true 141 | } 142 | init(_ dictionary: [Swift.String: Bool]) { 143 | identifier = dictionary["Identifier"] ?? false 144 | } 145 | } 146 | } 147 | 148 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/SecondTableViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Parser/StoryboardParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoryboardParser.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/05/03. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol StoryboardParser: Parsable { 12 | 13 | } 14 | 15 | public final class StoryboardParserImpl: NSObject, StoryboardParser { 16 | let url: URL 17 | let resource: AppendableForStoryboard 18 | 19 | fileprivate var name: String = "" 20 | fileprivate var initialViewControllerIdentifier: String? 21 | fileprivate var currentViewControllerInfoForSegue: ViewControllerInfoOfStoryboard? 22 | let config: Config 23 | 24 | public init(url: URL, writeResource resource: AppendableForStoryboard, config: Config) throws { 25 | self.url = url 26 | self.resource = resource 27 | self.config = config 28 | super.init() 29 | } 30 | 31 | public func parse() throws { 32 | guard url.pathExtension == "storyboard" else { 33 | throw ResourceKitErrorType.spcifiedPathError(path: url.absoluteString, errorInfo: ResourceKitErrorType.createErrorInfo()) 34 | } 35 | 36 | name = url.deletingPathExtension().lastPathComponent 37 | // Don't create ipad resources 38 | if name.contains("~") { 39 | return 40 | } 41 | 42 | guard let parser = XMLParser(contentsOf: url) else { 43 | throw ResourceKitErrorType.spcifiedPathError(path: url.absoluteString, errorInfo: ResourceKitErrorType.createErrorInfo()) 44 | } 45 | parser.delegate = self 46 | parser.parse() 47 | } 48 | 49 | public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 50 | if elementName == "document" { 51 | initialViewControllerIdentifier = attributeDict["initialViewController"] 52 | return 53 | } 54 | 55 | if ResourceType.isViewControllerStandardType(elementName) { 56 | generateViewControllerResourceType(attributeDict, elementName: elementName) 57 | } 58 | 59 | if ResourceType.isSegue(elementName) { 60 | extranctionForSegue(attributeDict, elementName: elementName) 61 | } 62 | 63 | if ResourceType.isTableViewCell(elementName) { 64 | generateTableViewCells(attributeDict, elementName: elementName) 65 | } 66 | 67 | if ResourceType.isCollectionViewCell(elementName) { 68 | generateCollectionViewCells(attributeDict, elementName: elementName) 69 | } 70 | } 71 | 72 | fileprivate func generateViewControllerResourceType(_ attributes: [String: String], elementName: String) { 73 | guard let viewControllerId = attributes["id"] else { 74 | return 75 | } 76 | 77 | if !config.viewController.instantiateStoryboardAny { 78 | return 79 | } 80 | 81 | let storyboardIdentifier = attributes["storyboardIdentifier"] ?? "" 82 | let viewControllerName = try? ResourceType(viewController: attributes["customClass"] ?? elementName).name 83 | 84 | let currentViewControllerInfo = ViewControllerInfoOfStoryboard ( 85 | viewControllerId: viewControllerId, 86 | storyboardName: name, 87 | initialViewControllerId: initialViewControllerIdentifier, 88 | storyboardIdentifier: storyboardIdentifier 89 | ) 90 | 91 | resource 92 | .appendViewControllerInfoReference( 93 | viewControllerName, 94 | viewControllerInfo: currentViewControllerInfo 95 | ) 96 | 97 | // store for extranctionForSegue(_:, elementName:) 98 | currentViewControllerInfoForSegue = currentViewControllerInfo 99 | } 100 | 101 | fileprivate func extranctionForSegue(_ attributes: [String: String], elementName: String) { 102 | guard let segueIdentifier = attributes["identifier"] else { 103 | return 104 | } 105 | 106 | if !config.needGenerateSegue { 107 | return 108 | } 109 | 110 | currentViewControllerInfoForSegue?.segues.append(segueIdentifier) 111 | } 112 | 113 | fileprivate func generateTableViewCells(_ attributes: [String: String], elementName: String) { 114 | guard let reusableIdentifier = attributes["reuseIdentifier"] else { 115 | return 116 | } 117 | 118 | if !config.reusable.identifier { 119 | return 120 | } 121 | 122 | guard let className = try? ResourceType(reusable: attributes["customClass"] ?? elementName).name else { 123 | return 124 | } 125 | 126 | resource 127 | .appendTableViewCell( 128 | className, 129 | reusableIdentifier: reusableIdentifier 130 | ) 131 | } 132 | 133 | fileprivate func generateCollectionViewCells(_ attributes: [String: String], elementName: String) { 134 | guard let reusableIdentifier = attributes["reuseIdentifier"] else { 135 | return 136 | } 137 | 138 | if !config.reusable.identifier { 139 | return 140 | } 141 | 142 | guard let className = try? ResourceType(reusable: attributes["customClass"] ?? elementName).name else { 143 | return 144 | } 145 | 146 | resource 147 | .appendCollectionViewCell( 148 | className, 149 | reusableIdentifier: reusableIdentifier 150 | ) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Parser/ProjectResourceParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectParser.swift 3 | // ResourceKit 4 | // 5 | // Created by kingkong999yhirose on 2016/05/03. 6 | // Copyright © 2016年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XcodeProject 11 | 12 | public struct ProjectResourceParser { 13 | 14 | let config: Config 15 | 16 | public init(xcodeURL: URL, target: String, writeResource resource: AppendableForPaths, config: Config) throws { 17 | guard let projectFile = try? XcodeProject(for: xcodeURL) else { 18 | throw ResourceKitErrorType.xcodeProjectError(xcodeURL: xcodeURL, target: target, errorInfo: ResourceKitErrorType.createErrorInfo()) 19 | } 20 | 21 | let allTarget = projectFile.project.targets 22 | guard let _target = allTarget.filter({ $0.name == target }).first else { 23 | throw ResourceKitErrorType.xcodeProjectAllTargetError(xcodeURL: xcodeURL, target: target, allTargetName: "\(allTarget.flatMap { $0.name }.joined(separator: ", "))", errorInfo: ResourceKitErrorType.createErrorInfo()) 24 | } 25 | 26 | self.config = config 27 | resource.appendFileReferencePaths(urls: generateFileRefPaths(_target).flatMap(Environment.pathFrom)) 28 | resource.appendLocalizedPaths(urls: generateLocalizablePaths(_target).flatMap(Environment.pathFrom)) 29 | 30 | setupSuffixViewControllers() 31 | } 32 | 33 | fileprivate func generateLocalizablePaths(_ target: PBX.NativeTarget) -> [PathComponent] { 34 | let resourcesFileRefs = target.buildPhases 35 | .flatMap { $0 as? PBX.ResourcesBuildPhase } 36 | .flatMap { $0.files } 37 | .map { $0.fileRef } 38 | 39 | let localizablePaths = resourcesFileRefs 40 | .flatMap { $0 as? PBX.VariantGroup } 41 | .flatMap { $0.fileRefs } 42 | .map { $0.fullPath } 43 | 44 | return localizablePaths 45 | } 46 | 47 | fileprivate func generateFileRefPaths(_ target: PBX.NativeTarget) -> [PathComponent] { 48 | return target.buildPhases 49 | .flatMap { $0.files } 50 | .flatMap { $0.fileRef } 51 | .flatMap { $0 as? PBX.FileReference } 52 | .flatMap { $0.fullPath } 53 | } 54 | 55 | fileprivate mutating func setupSuffixViewControllers() { 56 | func append(_ viewControllers: [ViewController]) { 57 | ProjectResource 58 | .shared 59 | .viewControllers 60 | .append( 61 | contentsOf: viewControllers 62 | ) 63 | } 64 | if config.viewController.instantiateStoryboardForSwift { 65 | append( 66 | viewControllerInfoWith( 67 | filterPaths(withExtension: "swift", suffixs: "ViewController"), 68 | suffix: "ViewController", 69 | pattern: ".*class\\s+.*ViewController\\s*:\\s*.*ViewController" 70 | ) 71 | ) 72 | } 73 | if config.viewController.instantiateStoryboardForObjC { 74 | append( 75 | viewControllerInfoWith( 76 | filterPaths(withExtension: "h", suffixs: "ViewController"), 77 | suffix: "ViewController", 78 | pattern: "\\s*@interface\\s+.*ViewController\\s*:\\s*.*ViewController" 79 | ) 80 | ) 81 | 82 | } 83 | if config.viewController.instantiateStoryboardAny { 84 | append( 85 | ViewControllerResourceType.standards().flatMap { try? ViewController(className: $0.rawValue) } 86 | ) 87 | } 88 | 89 | } 90 | 91 | fileprivate func viewControllerInfoWith(_ path: URL, suffix: String, pattern: String) -> ViewController? { 92 | guard let content = try? String(contentsOf: path), 93 | let regex = try? NSRegularExpression(pattern: pattern, options: .useUnixLineSeparators) else { 94 | return nil 95 | } 96 | let results = regex.matches(in: content, options: [], range: NSMakeRange(0, content.characters.count)) 97 | 98 | return results 99 | .flatMap { (result) -> ViewController? in 100 | if result.range.location == NSNotFound { 101 | return nil 102 | } 103 | 104 | let matchingString = (content as NSString).substring(with: result.range) as String 105 | let classes = matchingString 106 | .replacingOccurrences(of: "\\s*@interface", with: "", options: .regularExpression, range: nil) 107 | .replacingOccurrences(of: ".*class", with: "", options: .regularExpression, range: nil) 108 | .replacingOccurrences(of: "{", with: "") 109 | .replacingOccurrences(of: "}", with: "") 110 | .replacingOccurrences(of: " ", with: "") 111 | .replacingOccurrences(of: ":", with: " ") 112 | .components(separatedBy: " ") 113 | .filter { $0.hasSuffix(suffix) } 114 | 115 | 116 | return try? ViewController(className: classes[0], superClassName: classes[1]) 117 | } 118 | .first 119 | } 120 | 121 | fileprivate func viewControllerInfoWith(_ paths: [URL], suffix: String, pattern: String) -> [ViewController] { 122 | return paths.flatMap { 123 | viewControllerInfoWith($0, suffix: suffix, pattern: pattern) 124 | } 125 | } 126 | 127 | fileprivate func filterPaths(withExtension ex: String, suffixs: String...) -> [URL] { 128 | return ProjectResource.shared.paths.filter { url in 129 | guard url.pathExtension == ex 130 | else { 131 | return false 132 | } 133 | guard let fileName = Optional(url.deletingPathExtension().lastPathComponent), 134 | suffixs.contains(where: {fileName.hasSuffix($0)}) 135 | else { 136 | return false 137 | } 138 | return true 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Sources/ResourceKit/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // ResourceKit 4 | // 5 | // Created by Hirose.Yudai on 2016/01/27. 6 | // Copyright © 2016年 Hirose.Yudai. All rights reserved. 7 | // 8 | import Foundation 9 | import XcodeProject 10 | import ResourceKitCore 11 | import Commander 12 | 13 | let projectFilePath = ResourceKitConfig.Debug.projectFilePath != nil ? ResourceKitConfig.Debug.projectFilePath! : Environment.PROJECT_FILE_PATH.element! 14 | let projectTarget = ResourceKitConfig.Debug.projectTarget ?? Environment.TARGET_NAME.element ?? "" 15 | 16 | let main = command( 17 | Option("project-file-path", default: projectFilePath), 18 | Option("project-target", default: projectTarget) 19 | ) { projectFilePath, projectTarget in 20 | if !ResourceKitConfig.Debug.isDebug { 21 | do { 22 | try Environment.verifyUseEnvironment() 23 | } catch { 24 | print("verify use environtment") 25 | exit(1) 26 | } 27 | } 28 | 29 | let outputPath = ResourceKitConfig.outputPath 30 | let config: Config = ConfigImpl(outputPath: outputPath) 31 | 32 | do { 33 | let outputUrl = URL(fileURLWithPath: outputPath) 34 | var resourceValue: AnyObject? 35 | try (outputUrl as NSURL).getResourceValue(&resourceValue, forKey: URLResourceKey.isDirectoryKey) 36 | 37 | let writeUrl: URL = outputUrl.appendingPathComponent(ResourceKitConfig.outputFileName, isDirectory: false) 38 | 39 | let projectFileURL = URL(fileURLWithPath: projectFilePath) 40 | guard let pbxprojectPath = URL(string: projectFileURL.absoluteString + "project.pbxproj") else { 41 | throw ResourceKitErrorType.xcodeProjectError(xcodeURL: projectFileURL, target: "Unknown", errorInfo: "Can't find project.pbxproj") 42 | } 43 | let parser = try ProjectResourceParser(xcodeURL: pbxprojectPath, target: projectTarget, writeResource: ProjectResource.shared, config: config) 44 | let paths = ProjectResource.shared.paths 45 | 46 | paths 47 | .filter { $0.pathExtension == "storyboard" } 48 | .forEach { try? StoryboardParserImpl(url: $0, writeResource: ProjectResource.shared, config: config).parse() } 49 | 50 | paths 51 | .filter { $0.pathExtension == "xib" } 52 | .forEach { try? XibPerserImpl(url: $0, writeResource: ProjectResource.shared).parse() } 53 | 54 | let importsContent = ImportOutputImpl(writeUrl: writeUrl, config: config).declaration 55 | 56 | let viewControllerContent = try ProjectResource 57 | .shared 58 | .viewControllers 59 | .map { (viewController) in 60 | try ViewControllerTranslator(config: config, viewControllers: ProjectResource.shared.viewControllers).translate(for: viewController).declaration 61 | } 62 | .joined() 63 | 64 | let tableViewCellContent: String 65 | let collectionViewCellContent: String 66 | 67 | if config.reusable.identifier { 68 | tableViewCellContent = try ProjectResource.shared.tableViewCells 69 | .flatMap { try ReusableTranslator().translate(for: $0).declaration + Const.newLine } 70 | .joined(separator: Const.newLine) 71 | .appendNewLineIfNotEmpty() 72 | 73 | collectionViewCellContent = try ProjectResource.shared.collectionViewCells 74 | .flatMap { try ReusableTranslator().translate(for: $0).declaration + Const.newLine } 75 | .joined(separator: Const.newLine) 76 | .appendNewLineIfNotEmpty() 77 | 78 | } else { 79 | tableViewCellContent = "" 80 | collectionViewCellContent = "" 81 | } 82 | 83 | let xibContent: String 84 | if config.nib.xib { 85 | xibContent = try ProjectResource.shared.xibs 86 | .flatMap { try XibTranslator().translate(for: $0).declaration } 87 | .joined(separator: Const.newLine) 88 | .appendNewLineIfNotEmpty() 89 | } else { 90 | xibContent = "" 91 | } 92 | 93 | let imageContent = try ImageTranslator(config: config).translate( 94 | for: ( 95 | assets: ImageAssetRepositoryImpl().load(), 96 | resources: ImageResourcesRepositoryImpl().load()) 97 | ) 98 | .declaration 99 | 100 | let stringContent: String 101 | 102 | if config.string.localized { 103 | stringContent = try LocalizedStringTranslator() 104 | .translate( 105 | for: LocalizedStringRepositoryImpl(urls: ProjectResource.shared.localizablePaths).load() 106 | ) 107 | .declaration 108 | } else { 109 | stringContent = "" 110 | } 111 | 112 | let content = ( 113 | Const.Header 114 | + importsContent + Const.newLine 115 | + ExtensionsOutputImpl().reusableProtocolContent + Const.newLine + Const.newLine 116 | + ExtensionsOutputImpl().xibProtocolContent + Const.newLine + Const.newLine 117 | + ExtensionsOutputImpl().tableViewExtensionContent + Const.newLine + Const.newLine 118 | + ExtensionsOutputImpl().collectionViewExtensionContent + Const.newLine + Const.newLine 119 | + viewControllerContent + Const.newLine 120 | + tableViewCellContent + Const.newLine 121 | + collectionViewCellContent + Const.newLine 122 | + xibContent + Const.newLine 123 | + imageContent + Const.newLine 124 | + stringContent + Const.newLine 125 | ) 126 | 127 | func write(_ code: String, fileURL: URL) throws { 128 | try code.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8) 129 | } 130 | 131 | try write(content, fileURL: writeUrl) 132 | } catch { 133 | if let e = error as? ResourceKitErrorType { 134 | print(e.description()) 135 | 136 | } else { 137 | print(error) 138 | } 139 | 140 | print("missing write content") 141 | exit(3) 142 | } 143 | } 144 | 145 | 146 | main.run() 147 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKit.log.swift: -------------------------------------------------------------------------------- 1 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.m 2 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewCell.swift 3 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ViewController.swift 4 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CustomView.swift 5 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/AppDelegate.swift 6 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOveerrideViewController.h 7 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo/Resource.generated.swift 8 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewCell.swift 9 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewCell.swift 10 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewController.swift 11 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondCollectionViewCell.swift 12 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/OverrideViewController.swift 13 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewController.swift 14 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewController.swift 15 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.h 16 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOveerrideViewController.m 17 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondCollectionViewController.swift 18 | /Users/kingkong999yhirose/Library/Developer/Xcode/DerivedData/ResourceKitDemo-gszbvekyazxhngcamocghxlxcilk/Build/Products/Debug-iphonesimulator/Pods.framework 19 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.storyboard 20 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/InstanceFromOverride.storyboard 21 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewCell.xib 22 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo/ResourceKit 23 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Resources/swift_logo@2x.png 24 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/OverrideViewController.storyboard 25 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewCell.xib 26 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Assets.xcassets 27 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOverrideViewController.storyboard 28 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TabBarController.storyboard 29 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ViewController.storyboard 30 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Resources/swift_logo.png 31 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewController.storyboard 32 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CustomView.xib/Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.m 33 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewCell.swift 34 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ViewController.swift 35 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CustomView.swift 36 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/AppDelegate.swift 37 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOveerrideViewController.h 38 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo/Resource.generated.swift 39 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewCell.swift 40 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewCell.swift 41 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewController.swift 42 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondCollectionViewCell.swift 43 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/OverrideViewController.swift 44 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewController.swift 45 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewController.swift 46 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.h 47 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOveerrideViewController.m 48 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondCollectionViewController.swift 49 | /Users/kingkong999yhirose/Library/Developer/Xcode/DerivedData/ResourceKitDemo-gszbvekyazxhngcamocghxlxcilk/Build/Products/Debug-iphonesimulator/Pods.framework 50 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCViewController.storyboard 51 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/InstanceFromOverride.storyboard 52 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TableViewCell.xib 53 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo/ResourceKit 54 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Resources/swift_logo@2x.png 55 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/OverrideViewController.storyboard 56 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CollectionViewCell.xib 57 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Assets.xcassets 58 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ObjCOverrideViewController.storyboard 59 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/TabBarController.storyboard 60 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/ViewController.storyboard 61 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/Resources/swift_logo.png 62 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/SecondTableViewController.storyboard 63 | /Users/kingkong999yhirose/Desktop/MyApps/swift/ResourceKit/ResourceKitDemo//ResourceKitDemo/CustomView.xib -------------------------------------------------------------------------------- /Sources/ResourceKitCore/Storyboard/ViewController/ViewControllerOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerOutput.swift 3 | // ResourceKit 4 | // 5 | // Created by Yudai.Hirose on 2017/09/23. 6 | // Copyright © 2017年 kingkong999yhirose. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ViewControllerOutput: Output { 12 | 13 | } 14 | 15 | public struct ViewControllerOutputImpl: ViewControllerOutput { 16 | let name: String 17 | let storyboardInfos: [ViewControllerInfoOfStoryboard] 18 | let hasSuperClass: Bool 19 | let superClassStoryboardInfos: [ViewControllerInfoOfStoryboard] 20 | let config: Config 21 | 22 | public fileprivate(set) var declaration: String = "" 23 | var seguesForGenerateStruct: [String] { 24 | return storyboardInfos.flatMap { $0.segues } 25 | } 26 | 27 | init( 28 | name: String, 29 | storyboardInfos: [ViewControllerInfoOfStoryboard], 30 | hasSuperClass: Bool, 31 | superClassStoryboardInfos: [ViewControllerInfoOfStoryboard], 32 | config: Config 33 | ) { 34 | self.name = name 35 | self.storyboardInfos = storyboardInfos 36 | self.hasSuperClass = hasSuperClass 37 | self.superClassStoryboardInfos = superClassStoryboardInfos 38 | self.config = config 39 | 40 | self.declaration = generateDeclarationIfStoryboardInfoExists() 41 | } 42 | } 43 | 44 | // MARK: - Private 45 | fileprivate extension ViewControllerOutputImpl { 46 | func generateDeclarationIfStoryboardInfoExists() -> String { 47 | if storyboardInfos.isEmpty { 48 | return "" 49 | } 50 | 51 | return generateDeclaration() 52 | } 53 | 54 | func generateDeclaration() -> String { 55 | let begin = "extension \(name) {" + Const.newLine 56 | let viewControllerAndPerformSegueFunctions = storyboardInfos 57 | .flatMap { 58 | let viewControllerFunctions = generateForInsitantiateViewController(from: $0) 59 | let performSeguesFunctions = generateForPerformSegue(from: $0) 60 | 61 | if viewControllerFunctions.isEmpty { 62 | return performSeguesFunctions.appendNewLineIfNotEmpty() 63 | } 64 | 65 | if performSeguesFunctions.isEmpty { 66 | return viewControllerFunctions.appendNewLineIfNotEmpty() 67 | } 68 | 69 | return viewControllerFunctions.appendNewLineIfNotEmpty().appendNewLineIfNotEmpty() 70 | + performSeguesFunctions.appendNewLineIfNotEmpty().appendNewLineIfNotEmpty() 71 | } 72 | .joined() 73 | let segueStruct = generateForSegueStruct() 74 | let body = viewControllerAndPerformSegueFunctions + segueStruct.appendNewLineIfNotEmpty() 75 | let end = "}" + Const.newLine 76 | 77 | return [begin, body, end].joined().appendNewLineIfNotEmpty() 78 | } 79 | 80 | func generateForSegueStruct() -> String { 81 | if !config.segue.standard { 82 | return "" 83 | } 84 | if seguesForGenerateStruct.isEmpty { 85 | return "" 86 | } 87 | 88 | let begin = "\(Const.tab1)public struct Segue {" 89 | let body: String = seguesForGenerateStruct 90 | .flatMap { 91 | "\(Const.tab2)public static let \($0.lowerFirst): String = \"\($0)\"" 92 | } 93 | .joined(separator: Const.newLine) 94 | let end = "\(Const.tab1)}" 95 | return [begin, body, end].joined(separator: Const.newLine) 96 | } 97 | 98 | func generateForInsitantiateViewController(from storyboard: ViewControllerInfoOfStoryboard) -> String { 99 | if !config.viewController.instantiateStoryboardAny { 100 | return "" 101 | } 102 | 103 | return storyboard.isInitial ? fromStoryboardForInitial(from: storyboard) : fromStoryboard(from: storyboard) 104 | } 105 | 106 | func generateForPerformSegue(from storyboard: ViewControllerInfoOfStoryboard) -> String { 107 | if !config.needGenerateSegue { 108 | return "" 109 | } 110 | 111 | return generatePerformSegues(from: storyboard) 112 | } 113 | 114 | func generatePerformSegues(from storyboard: ViewControllerInfoOfStoryboard) -> String { 115 | if !config.needGenerateSegue { 116 | return "" 117 | } 118 | 119 | if storyboard.segues.isEmpty { 120 | return "" 121 | } 122 | 123 | if seguesForGenerateStruct.isEmpty { 124 | return "" 125 | } 126 | 127 | return seguesForGenerateStruct 128 | .flatMap { 129 | generatePerformSegue(from: storyboard, and: $0) 130 | } 131 | .joined(separator: Const.newLine) 132 | } 133 | 134 | func generatePerformSegue(from storyboard: ViewControllerInfoOfStoryboard, and segueIdentifier: String) -> String { 135 | let overrideOrNil = makeOverrideIfNeededForPerformSegue(from: storyboard) 136 | let overrideOrObjC = overrideOrNil == nil ? "@objc " : overrideOrNil! + " " 137 | let head = "\(Const.tab1)\(overrideOrObjC)" 138 | if config.segue.addition { 139 | return [ 140 | "\(head)open func performSegue\(segueIdentifier)(closure: ((UIStoryboardSegue) -> Void)? = nil) {", 141 | "\(Const.tab2)performSegue(\"\(segueIdentifier)\", closure: closure)", 142 | "\(Const.tab1)}", 143 | ] 144 | .joined(separator: Const.newLine) 145 | } 146 | return [ 147 | "\(head)open func performSegue\(segueIdentifier)(sender: AnyObject? = nil) {", 148 | "\(Const.tab2)performSegue(withIdentifier: \"\(segueIdentifier)\", sender: sender)", 149 | "\(Const.tab1)}", 150 | ] 151 | .joined(separator: Const.newLine) 152 | } 153 | 154 | func fromStoryboard(from storyboard: ViewControllerInfoOfStoryboard) -> String { 155 | if storyboard.storyboardIdentifier.isEmpty { 156 | return "" 157 | } 158 | 159 | let overrideOrNil = makeOverrideIfNeededForFromStoryboardFunction(from: storyboard) 160 | let overrideOrObjC = overrideOrNil == nil ? "@objc " : overrideOrNil! + " " 161 | let head = "\(Const.tab1)\(overrideOrObjC)open class func " 162 | if storyboardInfos.filter({ $0.storyboardName == storyboard.storyboardName }).count > 1 { 163 | return [ 164 | head + "instanceFrom\(storyboard.storyboardName + storyboard.storyboardIdentifier)() -> \(name) {", 165 | "\(Const.tab2)let storyboard = UIStoryboard(name: \"\(storyboard.storyboardName)\", bundle: nil) ", 166 | "\(Const.tab2)let viewController = storyboard.instantiateViewController(withIdentifier: \"\(storyboard.storyboardIdentifier)\") as! \(name)", 167 | "\(Const.tab2)return viewController", 168 | "\(Const.tab1)}" 169 | ] 170 | .joined(separator: Const.newLine) 171 | } 172 | 173 | return [ 174 | head + "instanceFrom\(storyboard.storyboardName)() -> \(name) {", 175 | "\(Const.tab2)let storyboard = UIStoryboard(name: \"\(storyboard.storyboardName)\", bundle: nil) ", 176 | "\(Const.tab2)let viewController = storyboard.instantiateViewController(withIdentifier: \"\(storyboard.storyboardIdentifier)\") as! \(name)", 177 | "\(Const.tab2)return viewController", 178 | "\(Const.tab1)}", 179 | ] 180 | .joined(separator: Const.newLine) 181 | } 182 | 183 | func fromStoryboardForInitial(from storyboard: ViewControllerInfoOfStoryboard) -> String { 184 | let overrideOrNil = makeOverrideIfNeededForFromStoryboardFunction(from: storyboard) 185 | let overrideOrObjC = overrideOrNil == nil ? "@objc " : overrideOrNil! + " " 186 | let head = "\(Const.tab1)\(overrideOrObjC)open class func " 187 | 188 | if storyboardInfos.filter ({ $0.isInitial }).count > 1 { 189 | return [ 190 | head + "initialFrom\(storyboard.storyboardName)() -> \(name) {", 191 | "\(Const.tab2)let storyboard = UIStoryboard(name: \"\(storyboard.storyboardName)\", bundle: nil) ", 192 | "\(Const.tab2)let viewController = storyboard.instantiateInitialViewController() as! \(name)", 193 | "\(Const.tab2)return viewController", 194 | "\(Const.tab1)}" 195 | ] 196 | .joined(separator: Const.newLine) 197 | } 198 | 199 | return [ 200 | head + "initialViewController() -> \(name) {", 201 | "\(Const.tab2)let storyboard = UIStoryboard(name: \"\(storyboard.storyboardName)\", bundle: nil) ", 202 | "\(Const.tab2)let viewController = storyboard.instantiateInitialViewController() as! \(name)", 203 | "\(Const.tab2)return viewController", 204 | "\(Const.tab1)}" 205 | ] 206 | .joined(separator: Const.newLine) 207 | } 208 | 209 | func needOverrideForStoryboard(_ storyboard: ViewControllerInfoOfStoryboard) -> Bool { 210 | if !hasSuperClass { 211 | return false 212 | } 213 | 214 | // For initialViewController() 215 | let hasInitialOfSuperClass = superClassStoryboardInfos.filter({ $0.isInitial }).count > 0 216 | let needOverrideForInitial = hasInitialOfSuperClass && storyboard.isInitial 217 | if needOverrideForInitial { 218 | return true 219 | } 220 | 221 | if storyboard.storyboardIdentifier.isEmpty { 222 | return false 223 | } 224 | 225 | // For not initialViewController() 226 | let storyboardsForIsNotInitial = superClassStoryboardInfos.filter({ !$0.isInitial }) 227 | return storyboardsForIsNotInitial.filter({ $0.storyboardName == storyboard.storyboardName }).count > 1 228 | } 229 | 230 | func needOverrideForSegue(_ storyboard: ViewControllerInfoOfStoryboard) -> Bool { 231 | if !hasSuperClass { 232 | return false 233 | } 234 | 235 | let superClassSegues = superClassStoryboardInfos.flatMap { $0.segues } 236 | let segues = storyboardInfos.flatMap { $0.segues } 237 | 238 | return superClassSegues.contains { superClassSegue in 239 | segues.contains { segue in 240 | segue == superClassSegue 241 | } 242 | } 243 | } 244 | 245 | func makeOverrideIfNeededForFromStoryboardFunction(from storyboard: ViewControllerInfoOfStoryboard) -> String? { 246 | return needOverrideForStoryboard(storyboard) ? "override" : nil 247 | } 248 | 249 | func makeOverrideIfNeededForPerformSegue(from storyboard: ViewControllerInfoOfStoryboard) -> String? { 250 | return needOverrideForSegue(storyboard) ? "override" : nil 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /ResourceKitDemo/Resource.generated.swift: -------------------------------------------------------------------------------- 1 | // This is a generated file 2 | // Generated by ResouceKit 3 | // You can write custom imoprt XXXX logic 4 | import UIKit 5 | import SegueAddition 6 | public protocol ReusableProtocol { 7 | associatedtype View 8 | static var name: String { get } 9 | } 10 | 11 | public protocol XibProtocol: ReusableProtocol { 12 | static func nib() -> UINib 13 | static func view() -> View 14 | } 15 | 16 | public extension UITableView { 17 | public func register(xib: X.Type) -> Void where X.View: UITableViewCell { 18 | register(xib.nib(), forCellReuseIdentifier: xib.name) 19 | } 20 | 21 | public func register(xibs: [X.Type]) -> Void where X.View: UITableViewCell { 22 | xibs.forEach { register(xib: $0) } 23 | } 24 | 25 | public func dequeueReusableCell(with reusable: R.Type, for indexPath: IndexPath) -> R.View where R.View: UITableViewCell { 26 | return dequeueReusableCell(withIdentifier: reusable.name, for: indexPath) as! R.View 27 | } 28 | } 29 | 30 | extension UICollectionView { 31 | public func register(xib: X.Type) -> Void where X.View: UICollectionViewCell { 32 | register(xib.nib(), forCellWithReuseIdentifier: xib.name) 33 | } 34 | 35 | public func register(xibs: [X.Type]) -> Void where X.View: UICollectionViewCell { 36 | xibs.forEach { register(xib: $0) } 37 | } 38 | 39 | public func dequeueReusableCell(with reusable: R.Type, for indexPath: IndexPath) -> R.View where R.View: UICollectionViewCell { 40 | return dequeueReusableCell(withReuseIdentifier: reusable.name, for: indexPath) as! R.View 41 | } 42 | } 43 | 44 | extension ViewController { 45 | @objc open class func instanceFromInstanceFromOverride() -> ViewController { 46 | let storyboard = UIStoryboard(name: "InstanceFromOverride", bundle: nil) 47 | let viewController = storyboard.instantiateViewController(withIdentifier: "BaseInstance") as! ViewController 48 | return viewController 49 | } 50 | @objc open class func initialViewController() -> ViewController { 51 | let storyboard = UIStoryboard(name: "ViewController", bundle: nil) 52 | let viewController = storyboard.instantiateInitialViewController() as! ViewController 53 | return viewController 54 | } 55 | 56 | @objc open func performSegueShowSecondTable(closure: ((UIStoryboardSegue) -> Void)? = nil) { 57 | performSegue("ShowSecondTable", closure: closure) 58 | } 59 | 60 | public struct Segue { 61 | public static let showSecondTable: String = "ShowSecondTable" 62 | } 63 | } 64 | 65 | extension TableViewController { 66 | @objc open class func instanceFromTabBarController() -> TableViewController { 67 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 68 | let viewController = storyboard.instantiateViewController(withIdentifier: "TableView") as! TableViewController 69 | return viewController 70 | } 71 | 72 | @objc open func performSegueShowViewController(closure: ((UIStoryboardSegue) -> Void)? = nil) { 73 | performSegue("ShowViewController", closure: closure) 74 | } 75 | 76 | public struct Segue { 77 | public static let showViewController: String = "ShowViewController" 78 | } 79 | } 80 | 81 | extension OverrideViewController { 82 | @objc open class func instanceFromInstanceFromOverrideOtherIdentifier() -> OverrideViewController { 83 | let storyboard = UIStoryboard(name: "InstanceFromOverride", bundle: nil) 84 | let viewController = storyboard.instantiateViewController(withIdentifier: "OtherIdentifier") as! OverrideViewController 85 | return viewController 86 | } 87 | @objc open class func instanceFromInstanceFromOverrideOverrideInstance() -> OverrideViewController { 88 | let storyboard = UIStoryboard(name: "InstanceFromOverride", bundle: nil) 89 | let viewController = storyboard.instantiateViewController(withIdentifier: "OverrideInstance") as! OverrideViewController 90 | return viewController 91 | } 92 | override open class func initialViewController() -> OverrideViewController { 93 | let storyboard = UIStoryboard(name: "OverrideViewController", bundle: nil) 94 | let viewController = storyboard.instantiateInitialViewController() as! OverrideViewController 95 | return viewController 96 | } 97 | 98 | override open func performSegueShowSecondTable(closure: ((UIStoryboardSegue) -> Void)? = nil) { 99 | performSegue("ShowSecondTable", closure: closure) 100 | } 101 | 102 | public struct Segue { 103 | public static let showSecondTable: String = "ShowSecondTable" 104 | } 105 | } 106 | 107 | extension SecondTableViewController { 108 | @objc open class func initialViewController() -> SecondTableViewController { 109 | let storyboard = UIStoryboard(name: "SecondTableViewController", bundle: nil) 110 | let viewController = storyboard.instantiateInitialViewController() as! SecondTableViewController 111 | return viewController 112 | } 113 | 114 | @objc open func performSegueShowOverride(closure: ((UIStoryboardSegue) -> Void)? = nil) { 115 | performSegue("ShowOverride", closure: closure) 116 | } 117 | 118 | public struct Segue { 119 | public static let showOverride: String = "ShowOverride" 120 | } 121 | } 122 | 123 | extension CollectionViewController { 124 | @objc open class func instanceFromTabBarController() -> CollectionViewController { 125 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 126 | let viewController = storyboard.instantiateViewController(withIdentifier: "CollectionView") as! CollectionViewController 127 | return viewController 128 | } 129 | 130 | @objc open func performSegueShowViewController(closure: ((UIStoryboardSegue) -> Void)? = nil) { 131 | performSegue("ShowViewController", closure: closure) 132 | } 133 | 134 | public struct Segue { 135 | public static let showViewController: String = "ShowViewController" 136 | } 137 | } 138 | 139 | extension SecondCollectionViewController { 140 | @objc open class func instanceFromTabBarController() -> SecondCollectionViewController { 141 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 142 | let viewController = storyboard.instantiateViewController(withIdentifier: "SecondCollectionView") as! SecondCollectionViewController 143 | return viewController 144 | } 145 | } 146 | 147 | extension ObjCOveerrideViewController { 148 | override open class func initialViewController() -> ObjCOveerrideViewController { 149 | let storyboard = UIStoryboard(name: "ObjCOverrideViewController", bundle: nil) 150 | let viewController = storyboard.instantiateInitialViewController() as! ObjCOveerrideViewController 151 | return viewController 152 | } 153 | } 154 | 155 | extension ObjCViewController { 156 | @objc open class func initialViewController() -> ObjCViewController { 157 | let storyboard = UIStoryboard(name: "ObjCViewController", bundle: nil) 158 | let viewController = storyboard.instantiateInitialViewController() as! ObjCViewController 159 | return viewController 160 | } 161 | } 162 | 163 | extension UITabBarController { 164 | @objc open class func initialViewController() -> UITabBarController { 165 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 166 | let viewController = storyboard.instantiateInitialViewController() as! UITabBarController 167 | return viewController 168 | } 169 | } 170 | 171 | extension UINavigationController { 172 | @objc open class func instanceFromTabBarControllerNav1() -> UINavigationController { 173 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 174 | let viewController = storyboard.instantiateViewController(withIdentifier: "Nav1") as! UINavigationController 175 | return viewController 176 | } 177 | @objc open class func instanceFromTabBarControllerNav2() -> UINavigationController { 178 | let storyboard = UIStoryboard(name: "TabBarController", bundle: nil) 179 | let viewController = storyboard.instantiateViewController(withIdentifier: "Nav2") as! UINavigationController 180 | return viewController 181 | } 182 | } 183 | 184 | 185 | extension SecondTableViewCell { 186 | public struct Reusable: ReusableProtocol { 187 | public typealias View = SecondTableViewCell 188 | public static let name: String = "ReuseIdentifier" 189 | } 190 | } 191 | 192 | 193 | extension SecondCollectionViewCell { 194 | public struct Reusable: ReusableProtocol { 195 | public typealias View = SecondCollectionViewCell 196 | public static let name: String = "ReuseIdentifier" 197 | } 198 | } 199 | 200 | 201 | extension ObjectiveCTableViewCell { 202 | public struct Xib: XibProtocol { 203 | public typealias View = ObjectiveCTableViewCell 204 | public static let name: String = "ObjectiveCTableViewCell" 205 | 206 | public static func nib() -> UINib { 207 | return UINib(nibName: "ObjectiveCTableViewCell", bundle: Bundle(for: ObjectiveCTableViewCell.classForCoder())) 208 | } 209 | 210 | public static func view() -> ObjectiveCTableViewCell { 211 | return nib().instantiate(withOwner: nil, options: nil)[0] as! ObjectiveCTableViewCell 212 | } 213 | 214 | } 215 | } 216 | extension TableViewCell { 217 | public struct Xib: XibProtocol { 218 | public typealias View = TableViewCell 219 | public static let name: String = "TableViewCell" 220 | 221 | public static func nib() -> UINib { 222 | return UINib(nibName: "TableViewCell", bundle: Bundle(for: TableViewCell.classForCoder())) 223 | } 224 | 225 | public static func view() -> TableViewCell { 226 | return nib().instantiate(withOwner: nil, options: nil)[0] as! TableViewCell 227 | } 228 | 229 | } 230 | } 231 | extension CollectionViewCell { 232 | public struct Xib: XibProtocol { 233 | public typealias View = CollectionViewCell 234 | public static let name: String = "CollectionViewCell" 235 | 236 | public static func nib() -> UINib { 237 | return UINib(nibName: "CollectionViewCell", bundle: Bundle(for: CollectionViewCell.classForCoder())) 238 | } 239 | 240 | public static func view() -> CollectionViewCell { 241 | return nib().instantiate(withOwner: nil, options: nil)[0] as! CollectionViewCell 242 | } 243 | 244 | } 245 | } 246 | extension CustomView { 247 | public struct Xib: XibProtocol { 248 | public typealias View = CustomView 249 | public static let name: String = "CustomView" 250 | 251 | public static func nib() -> UINib { 252 | return UINib(nibName: "CustomView", bundle: Bundle(for: CustomView.classForCoder())) 253 | } 254 | 255 | public static func view() -> CustomView { 256 | return nib().instantiate(withOwner: nil, options: nil)[0] as! CustomView 257 | } 258 | 259 | } 260 | } 261 | 262 | extension UIImage { 263 | public struct Asset { 264 | public static let curry: UIImage = UIImage(named: "curry")! 265 | public static let kaki: UIImage = UIImage(named: "kaki")! 266 | public static let ebi: UIImage = UIImage(named: "ebi")! 267 | public static let marudaizu: UIImage = UIImage(named: "marudaizu")! 268 | public static let kikkoman: UIImage = UIImage(named: "kikkoman")! 269 | public static let koumi: UIImage = UIImage(named: "koumi")! 270 | public static let ninniku: UIImage = UIImage(named: "ninniku")! 271 | public static let kake: UIImage = UIImage(named: "kake")! 272 | public static let koori: UIImage = UIImage(named: "koori")! 273 | public static let inaka: UIImage = UIImage(named: "inaka")! 274 | public static let siro: UIImage = UIImage(named: "siro")! 275 | public static let ususio: UIImage = UIImage(named: "ususio")! 276 | } 277 | 278 | public struct Resource { 279 | public static let swift_logo: UIImage = UIImage(named: "swift_logo")! 280 | } 281 | 282 | } 283 | 284 | extension String { 285 | public struct Localized { 286 | public static let helloworld = NSLocalizedString("helloworld", comment: "") 287 | public static let hello_world_3 = NSLocalizedString("hello world 3", comment: "") 288 | public static let hello_world_09 = NSLocalizedString("hello(world 09", comment: "") 289 | public static let hello_world_06 = NSLocalizedString("hello!world 06", comment: "") 290 | public static let hello_world_07 = NSLocalizedString("hello?world 07", comment: "") 291 | public static let hello_world_08 = NSLocalizedString("hello,world 08", comment: "") 292 | public static let hello_world_1 = NSLocalizedString("hello world 1", comment: "") 293 | public static let hello_world_11___ = NSLocalizedString("hello}world 11 %@", comment: "") 294 | public static let hello_world_12___ = NSLocalizedString("hello}world 12 %@", comment: "") 295 | public static let hello_world_10 = NSLocalizedString("hello}world 10", comment: "") 296 | public static let hello_world_4 = NSLocalizedString("hello world 4", comment: "") 297 | public static let hello_world_2 = NSLocalizedString("hello world 2", comment: "") 298 | public static let hello_world_05 = NSLocalizedString("hello.world 05", comment: "") 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /ResourceKitDemo/ResourceKitDemo/TabBarController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | --------------------------------------------------------------------------------