├── Gemfile ├── README └── Edit_and_Menubar.png ├── .gitmodules ├── Example └── iOS │ ├── Base.lproj │ ├── Main_iPhone.seguecode.json │ └── Main_iPhone.storyboard │ ├── iOSExample-Bridging-Header.h │ ├── Segues │ ├── TestCustomSegue.h │ ├── TestCustomReverseSegue.h │ ├── TestCustomReverseSegue.m │ └── TestCustomSegue.m │ ├── ThirdViewController.swift │ ├── FirstViewController.h │ ├── AppDelegate.swift │ ├── FirstViewController.m │ ├── Generated │ ├── UIViewController+Main_iPhone.swift │ ├── FirstViewController+Main_iPhone.swift │ ├── SecondViewController+Main_iPhone.swift │ ├── UIViewController+seguecode.swift │ └── Main_iPhone.swift │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── SecondViewController.swift │ └── Info.plist ├── seguecode.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── seguecodeKit.xcscheme │ ├── seguecodeiOSExample.xcscheme │ ├── seguecode.xcscheme │ └── seguecodeBundle.xcscheme ├── seguecodePlugin.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── seguecodePlugin.xccheckout ├── xcshareddata │ └── xcschemes │ │ ├── seguecodePluginLocal.xcscheme │ │ └── seguecodePlugin.xcscheme └── project.pbxproj ├── .travis.yml ├── Tools ├── git hooks │ └── post-checkout ├── xcode-build-bump.sh └── setVersion.sh ├── seguecodePlugin ├── seguecodePlugin.h ├── Utility │ ├── NSURL+Utility.h │ ├── NSObject+Utility.h │ ├── NSNotification+Utility.h │ ├── NSMutableDictionary+RunConfig.h │ ├── NSURL+Utility.m │ ├── NSNotification+Utility.m │ ├── NSMutableDictionary+RunConfig.m │ └── NSObject+Utility.m ├── Info.plist └── seguecodePlugin.m ├── seguecode.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── seguecode.xccheckout ├── seguecode ├── main.m ├── SeguecodeCLIApp.h └── SeguecodeCLIApp.m ├── .gitignore ├── Podfile ├── Podfile.lock ├── seguecodeKit ├── seguecodeKit.h ├── Info.plist ├── StoryboardKit │ ├── TableViewCellPrototype+seguecode.swift │ ├── CollectionViewCellPrototype+seguecode.swift │ ├── ViewControllerInstanceInfo+seguecode.swift │ ├── SegueInstanceInfo+seguecode.swift │ └── ViewControllerClassInfo+seguecode.swift ├── Stencil │ └── Template+seguecode.swift ├── seguecode.swift └── DefaultTemplate.swift ├── seguecodeBundle └── Info.plist ├── LICENSE.md ├── Gemfile.lock └── README.md /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods' 4 | -------------------------------------------------------------------------------- /README/Edit_and_Menubar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adorkable/seguecode/master/README/Edit_and_Menubar.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Library/ddcli"] 2 | path = Library/ddcli 3 | url = https://github.com/ddribin/ddcli.git 4 | -------------------------------------------------------------------------------- /Example/iOS/Base.lproj/Main_iPhone.seguecode.json: -------------------------------------------------------------------------------- 1 | { 2 | "combine": true, 3 | "outputPath": "../Generated", 4 | "projectName": "Example" 5 | } -------------------------------------------------------------------------------- /Example/iOS/iOSExample-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 "FirstViewController.h" 6 | -------------------------------------------------------------------------------- /seguecode.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /seguecodePlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7 3 | xcode_workspace: seguecode.xcworkspace 4 | xcode_scheme: 5 | - seguecodePluginLocal 6 | - seguecodePlugin 7 | before_install: 8 | - gem install cocoapods 9 | - git submodule init 10 | - git submodule update -------------------------------------------------------------------------------- /Tools/git hooks/post-checkout: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $3 == '1' ] 4 | then 5 | branch=$(git rev-parse --abbrev-ref HEAD) 6 | if [[ $branch == release/* ]] 7 | then 8 | if [[ $branch =~ release/([0-9.]*)$ ]] 9 | then 10 | ./Tools/setVersion.sh ${BASH_REMATCH[1]} ./ 11 | fi 12 | fi 13 | fi -------------------------------------------------------------------------------- /Example/iOS/Segues/TestCustomSegue.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestCustomSegue.h 3 | // TestStoryboard 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestCustomSegue : UIStoryboardSegue 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/iOS/ThirdViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThirdViewController.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 9/11/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ThirdViewController: UIViewController { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Example/iOS/Segues/TestCustomReverseSegue.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestCustomReverseSegue.h 3 | // TestStoryboard 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "TestCustomSegue.h" 10 | 11 | @interface TestCustomReverseSegue : TestCustomSegue 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/iOS/FirstViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SegueCodeExample 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FirstViewController : UIViewController 12 | 13 | @property (nonatomic, weak) IBOutlet UILabel *label; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /seguecodePlugin/seguecodePlugin.h: -------------------------------------------------------------------------------- 1 | // 2 | // seguecodePlugin.h 3 | // seguecodePlugin 4 | // 5 | // Created by Ian on 11/4/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface seguecodePlugin : NSObject 12 | 13 | + (instancetype)sharedPlugin; 14 | 15 | @property (nonatomic, strong, readonly) NSBundle* bundle; 16 | @end -------------------------------------------------------------------------------- /seguecode.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /seguecode/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/22/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | int main(int argc, const char * argv[]) { 14 | 15 | @autoreleasepool { 16 | return DDCliAppRunWithDefaultClass(); 17 | } 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .ruby-version 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | *.xcscmblueprint 24 | 25 | # Cocoapods 26 | # 27 | Pods/ 28 | 29 | # Carthage 30 | # 31 | Carthage/Checkouts 32 | Carthage/Build 33 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSURL+Utility.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+Utility.h 3 | // seguecodePlugin 4 | // 5 | // Created by Ian Grossberg on 11/17/15. 6 | // Copyright © 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSURL (Utility) 12 | 13 | + (NSURL *)URLWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); 14 | 15 | - (NSRange)rangeOfString:(NSString *)searchString; 16 | 17 | - (NSString *)pathWithSlashedSpaces; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example/iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // seguecodeiOSExample 4 | // 5 | // Created by Ian on 5/4/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | class func sharedInstance() -> AppDelegate { 17 | return UIApplication.sharedApplication().delegate as! AppDelegate 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | xcodeproj 'seguecode.xcodeproj' 2 | # platform :ios, '6.0' 3 | 4 | use_frameworks! 5 | 6 | target 'seguecode' do 7 | 8 | end 9 | 10 | target 'seguecodeBundle' do 11 | pod 'StoryboardKit', '~> 0.5' 12 | 13 | pod 'PathKit', '~> 0.5' 14 | pod 'Stencil', '~> 0.3' 15 | end 16 | 17 | target 'seguecodeKit' do 18 | pod 'StoryboardKit', '~> 0.5' 19 | 20 | pod 'PathKit', '~> 0.5' 21 | pod 'Stencil', '~> 0.3' 22 | end 23 | 24 | target 'iOSExample' do 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /Example/iOS/FirstViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SegueCodeExample 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "FirstViewController.h" 10 | 11 | #import "iOSExample-Swift.h" 12 | 13 | @interface FirstViewController () 14 | 15 | @end 16 | 17 | @implementation FirstViewController 18 | 19 | - (IBAction)goToUIViewController:(id)sender 20 | { 21 | [self performFirstForwardToUIVC:sender]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSObject+Utility.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Utility.h 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | @interface NSObject (Utility) 14 | 15 | + (NSDictionary *)classInfoForClass:(Class)class; 16 | + (NSDictionary *)classInfoForClassName:(NSString *)name; 17 | - (NSDictionary *)classInfo; 18 | - (NSDictionary *)instanceInfo; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/iOS/Generated/UIViewController+Main_iPhone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Main_iPhone.swift 3 | // Example 4 | // 5 | // Generated by seguecode [http://bit.ly/seguecode] 6 | // 7 | 8 | import UIKit 9 | 10 | extension UIViewController { 11 | 12 | struct Segues { 13 | static let BackToFirst = Segue(identifier: "BackTo") 14 | } 15 | 16 | @IBAction func performBackToFirst(sender : AnyObject? = nil) { 17 | self.performSegue(UIViewController.Segues.BackToFirst, sender: sender) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PathKit (0.5.0) 3 | - Stencil (0.3.0): 4 | - PathKit (~> 0.5.0) 5 | - StoryboardKit (0.5.0): 6 | - SWXMLHash 7 | - SWXMLHash (2.0.2) 8 | 9 | DEPENDENCIES: 10 | - PathKit (~> 0.5) 11 | - Stencil (~> 0.3) 12 | - StoryboardKit (~> 0.5) 13 | 14 | SPEC CHECKSUMS: 15 | PathKit: 64e70cb924d6faed9251049f5f28662855524baf 16 | Stencil: 90ce766d6dba53380832692541403e27297337db 17 | StoryboardKit: 2c5f76934d897174852c3e4dab897b515bcf4b85 18 | SWXMLHash: 9e6bd7db2e8275eaf3d2082265623d6e749e169d 19 | 20 | COCOAPODS: 0.39.0 21 | -------------------------------------------------------------------------------- /seguecode/SeguecodeCLIApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // SeguecodeCLIApp.h 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/24/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | @interface SeguecodeCLIApp : NSObject 14 | 15 | @property (readwrite, assign) NSString *outputPath; 16 | 17 | @property (readwrite, assign) NSString *projectName; 18 | 19 | @property (readonly) BOOL combine; 20 | 21 | @property (readonly) BOOL verbose; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSNotification+Utility.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotification+Utility.h 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSNotification (Utility) 12 | 13 | - (BOOL)isXcodeEvent; 14 | 15 | + (NSString *)transitionFromOneFileToAnotherName; 16 | - (BOOL)isTransitionFromOneFileToAnother; 17 | - (NSURL *)transitionFromOneFileToAnotherNextDocumentURL; 18 | 19 | + (NSString *)ideEditorDocumentDidSaveName; 20 | - (BOOL)isIDEEditorDocumentDidSave; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /seguecodeKit/seguecodeKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // seguecodeKit.h 3 | // seguecodeKit 4 | // 5 | // Created by Ian Grossberg on 8/22/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for seguecodeKit. 12 | FOUNDATION_EXPORT double seguecodeKitVersionNumber; 13 | 14 | //! Project version string for seguecodeKit. 15 | FOUNDATION_EXPORT const unsigned char seguecodeKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Tools/xcode-build-bump.sh: -------------------------------------------------------------------------------- 1 | # xcode-build-bump.sh 2 | # https://gist.github.com/sekati/3172554 3 | # @desc Auto-increment the build number every time the project is run. 4 | # @usage 5 | # 1. Select: your Target in Xcode 6 | # 2. Select: Build Phases Tab 7 | # 3. Select: Add Build Phase -> Add Run Script 8 | # 4. Paste code below in to new "Run Script" section 9 | # 5. Drag the "Run Script" below "Link Binaries With Libraries" 10 | # 6. Insure that your starting build number is set to a whole integer and not a float (e.g. 1, not 1.0) 11 | 12 | buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}") 13 | buildNumber=$(($buildNumber + 1)) 14 | /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}" 15 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSMutableDictionary+RunConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+RunConfig.h 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableDictionary (RunConfig) 12 | 13 | + (NSMutableDictionary *)dictionaryWithContentsOfJSONURL:(NSURL *)url; 14 | 15 | + (NSMutableDictionary *)runConfigForStoryboardAtURL:(NSURL *)storyboardURL; 16 | 17 | @property (readwrite) NSString *outputPath; 18 | @property (readwrite) BOOL combine; 19 | 20 | @property (readwrite) NSString *projectName; 21 | 22 | - (BOOL)writeContentsToJSONURL:(NSURL *)url; 23 | - (BOOL)writeRunConfigForStoryboardAtURL:(NSURL *)storyboardURL; 24 | 25 | + (BOOL)removeRunConfigForStoryboardAtURL:(NSURL *)storyboardURL; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /seguecodeBundle/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 | 2.3.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 12 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Adorkable. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSURL+Utility.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+Utility.h 3 | // seguecodePlugin 4 | // 5 | // Created by Ian Grossberg on 11/17/15. 6 | // Copyright © 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @implementation NSURL (Utility) 13 | 14 | + (NSURL *)URLWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) 15 | { 16 | va_list args; 17 | va_start(args, format); 18 | NSString *resultingString = [ [NSString alloc] initWithFormat:format arguments:args]; 19 | va_end(args); 20 | return [NSURL URLWithString:resultingString]; 21 | } 22 | 23 | - (NSRange)rangeOfString:(NSString *)searchString 24 | { 25 | NSString *selfAsString = [self absoluteString]; 26 | return [selfAsString rangeOfString:searchString]; 27 | } 28 | 29 | - (NSString *)pathWithSlashedSpaces 30 | { 31 | NSString *path = [self path]; 32 | 33 | return [path stringByReplacingOccurrencesOfString:@" " withString:@"\\\\ "]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /seguecodeKit/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 | FMWK 17 | CFBundleShortVersionString 18 | 2.3.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Adorkable. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Ian Grossberg 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 | 24 | 25 | -------------------------------------------------------------------------------- /Example/iOS/Generated/FirstViewController+Main_iPhone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController+Main_iPhone.swift 3 | // Example 4 | // 5 | // Generated by seguecode [http://bit.ly/seguecode] 6 | // 7 | 8 | import UIKit 9 | 10 | extension FirstViewController { 11 | 12 | struct StoryboardInstances { 13 | static let First = StoryboardInstance(identifier: "First") 14 | } 15 | 16 | struct Segues { 17 | static let FirstForwardToUIVC = Segue(identifier: "ForwardToUIVC") 18 | static let FirstGoToSecondSecond = Segue(identifier: "GoTo") 19 | static let FirstForwardToFirstSecond = Segue(identifier: "ForwardTo") 20 | } 21 | 22 | @IBAction func performFirstForwardToUIVC(sender : AnyObject? = nil) { 23 | self.performSegue(FirstViewController.Segues.FirstForwardToUIVC, sender: sender) 24 | } 25 | 26 | @IBAction func performFirstGoToSecondSecond(sender : AnyObject? = nil) { 27 | self.performSegue(FirstViewController.Segues.FirstGoToSecondSecond, sender: sender) 28 | } 29 | 30 | @IBAction func performFirstForwardToFirstSecond(sender : AnyObject? = nil) { 31 | self.performSegue(FirstViewController.Segues.FirstForwardToFirstSecond, sender: sender) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /seguecodeKit/StoryboardKit/TableViewCellPrototype+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCellPrototype+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/26/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | extension TableViewInstanceInfo.TableViewCellPrototypeInfo 14 | { 15 | func cellPrototypeStencilContext() -> [String : String]? { 16 | var result : [String : String]? 17 | 18 | if let reuseIdentifier = self.reuseIdentifier 19 | { 20 | let context = [DefaultTemplate.Keys.ViewController.TableViewCellPrototype.ReuseIdentifier : reuseIdentifier] 21 | result = context 22 | } 23 | 24 | return result 25 | } 26 | 27 | func dequeueFunctionStencilContext() -> [String : String]? { 28 | var result : [String : String]? 29 | 30 | if let reuseIdentifier = self.reuseIdentifier 31 | { 32 | let context = [DefaultTemplate.Keys.ViewController.DequeueTableViewCellFunction.ReuseIdentifier : reuseIdentifier] 33 | result = context 34 | } 35 | 36 | return result 37 | } 38 | } -------------------------------------------------------------------------------- /seguecodeKit/StoryboardKit/CollectionViewCellPrototype+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewCellPrototype+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 10/30/15. 6 | // Copyright © 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | extension CollectionViewInstanceInfo.CollectionViewCellPrototypeInfo 14 | { 15 | func cellPrototypeStencilContext() -> [String : String]? { 16 | var result : [String : String]? 17 | 18 | if let reuseIdentifier = self.reuseIdentifier 19 | { 20 | let context = [DefaultTemplate.Keys.ViewController.CollectionViewCellPrototype.ReuseIdentifier : reuseIdentifier] 21 | result = context 22 | } 23 | 24 | return result 25 | } 26 | 27 | func dequeueFunctionStencilContext() -> [String : String]? { 28 | var result : [String : String]? 29 | 30 | if let reuseIdentifier = self.reuseIdentifier 31 | { 32 | let context = [DefaultTemplate.Keys.ViewController.DequeueCollectionViewCellFunction.ReuseIdentifier : reuseIdentifier] 33 | result = context 34 | } 35 | 36 | return result 37 | } 38 | } -------------------------------------------------------------------------------- /seguecodeKit/StoryboardKit/ViewControllerInstanceInfo+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerInstanceInfo+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 10/30/15. 6 | // Copyright © 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | import Stencil 14 | 15 | extension ViewControllerInstanceInfo 16 | { 17 | var storyboardInstanceIdentifier : String? { 18 | return self.storyboardIdentifier 19 | } 20 | 21 | var storyboardInstanceValue : String? { 22 | return self.storyboardIdentifier 23 | } 24 | 25 | func storyboardInstanceStencilContext() -> [String : String]? { 26 | 27 | var result : [String : String]? 28 | 29 | if let storyboardInstanceIdentifier = self.storyboardInstanceIdentifier, 30 | let storyboardInstanceValue = self.storyboardInstanceValue 31 | { 32 | let context = [ 33 | DefaultTemplate.Keys.ViewController.StoryboardInstance.Identifier : storyboardInstanceIdentifier, 34 | DefaultTemplate.Keys.ViewController.StoryboardInstance.Value : storyboardInstanceValue] 35 | 36 | result = context 37 | } 38 | 39 | return result 40 | } 41 | } -------------------------------------------------------------------------------- /Example/iOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Example/iOS/SecondViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.swift 3 | // seguecode 4 | // 5 | // Created by Ian on 5/11/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SecondViewController: UIViewController { 12 | 13 | @IBAction func instanciateSecondSecond(sender : AnyObject) { 14 | AppDelegate.sharedInstance().window?.rootViewController = self.storyboard?.instantiateViewController(SecondViewController.StoryboardInstances.SecondSecond) 15 | } 16 | } 17 | 18 | extension SecondViewController : UITableViewDelegate, UITableViewDataSource { 19 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 20 | return 2 21 | } 22 | 23 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 24 | return self.dequeueReusableSecondTableCell(tableView, forIndexPath : indexPath) 25 | } 26 | } 27 | 28 | extension SecondViewController : UICollectionViewDelegate, UICollectionViewDataSource { 29 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 30 | return 2 31 | } 32 | 33 | func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 34 | return self.dequeueReusableSecondCollectionCell(collectionView, forIndexPath: indexPath) 35 | } 36 | } -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (4.2.4) 5 | i18n (~> 0.7) 6 | json (~> 1.7, >= 1.7.7) 7 | minitest (~> 5.1) 8 | thread_safe (~> 0.3, >= 0.3.4) 9 | tzinfo (~> 1.1) 10 | claide (0.9.1) 11 | cocoapods (0.39.0) 12 | activesupport (>= 4.0.2) 13 | claide (~> 0.9.1) 14 | cocoapods-core (= 0.39.0) 15 | cocoapods-downloader (~> 0.9.3) 16 | cocoapods-plugins (~> 0.4.2) 17 | cocoapods-search (~> 0.1.0) 18 | cocoapods-stats (~> 0.6.2) 19 | cocoapods-trunk (~> 0.6.4) 20 | cocoapods-try (~> 0.5.1) 21 | colored (~> 1.2) 22 | escape (~> 0.0.4) 23 | molinillo (~> 0.4.0) 24 | nap (~> 1.0) 25 | xcodeproj (~> 0.28.2) 26 | cocoapods-core (0.39.0) 27 | activesupport (>= 4.0.2) 28 | fuzzy_match (~> 2.0.4) 29 | nap (~> 1.0) 30 | cocoapods-downloader (0.9.3) 31 | cocoapods-plugins (0.4.2) 32 | nap 33 | cocoapods-search (0.1.0) 34 | cocoapods-stats (0.6.2) 35 | cocoapods-trunk (0.6.4) 36 | nap (>= 0.8, < 2.0) 37 | netrc (= 0.7.8) 38 | cocoapods-try (0.5.1) 39 | colored (1.2) 40 | escape (0.0.4) 41 | fuzzy_match (2.0.4) 42 | i18n (0.7.0) 43 | json (1.8.3) 44 | minitest (5.8.1) 45 | molinillo (0.4.0) 46 | nap (1.0.0) 47 | netrc (0.7.8) 48 | thread_safe (0.3.5) 49 | tzinfo (1.2.2) 50 | thread_safe (~> 0.1) 51 | xcodeproj (0.28.2) 52 | activesupport (>= 3) 53 | claide (~> 0.9.1) 54 | colored (~> 1.2) 55 | 56 | PLATFORMS 57 | ruby 58 | 59 | DEPENDENCIES 60 | cocoapods 61 | 62 | BUNDLED WITH 63 | 1.10.5 64 | -------------------------------------------------------------------------------- /Example/iOS/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 | UIMainStoryboardFile 28 | Main_iPhone 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /seguecodePlugin.xcodeproj/project.xcworkspace/xcshareddata/seguecodePlugin.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 84B5ACA0-66C0-4397-A643-ADFDE332E07E 9 | IDESourceControlProjectName 10 | seguecodePlugin 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 135769308420168AF7DDF8DC60BCB834AAD3928B 14 | github.com:yoiang/seguecode.git 15 | 16 | IDESourceControlProjectPath 17 | seguecodePlugin.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 135769308420168AF7DDF8DC60BCB834AAD3928B 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:yoiang/seguecode.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 135769308420168AF7DDF8DC60BCB834AAD3928B 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 135769308420168AF7DDF8DC60BCB834AAD3928B 36 | IDESourceControlWCCName 37 | seguecode 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /seguecodePlugin/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 2.3.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DVTPlugInCompatibilityUUIDs 26 | 27 | C4A681B0-4A26-480E-93EC-1218098B9AA0 28 | AD68E85B-441B-4301-B564-A45E4919A6AD 29 | A16FF353-8441-459E-A50C-B071F53F51B7 30 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7 31 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90 32 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3 33 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13 34 | 7265231C-39B4-402C-89E1-16167C4CC990 35 | F41BD31E-2683-44B8-AE7F-5F09E919790E 36 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C 37 | 38 | LSMinimumSystemVersion 39 | $(MACOSX_DEPLOYMENT_TARGET) 40 | NSPrincipalClass 41 | seguecodePlugin 42 | XC4Compatible 43 | 44 | XCPluginHasUI 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Example/iOS/Segues/TestCustomReverseSegue.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestCustomReverseSegue.m 3 | // TestStoryboard 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "TestCustomReverseSegue.h" 10 | 11 | #import "iOSExample-Swift.h" 12 | 13 | @implementation TestCustomReverseSegue 14 | 15 | - (void)perform 16 | { 17 | UIViewController *sourceViewController = self.sourceViewController; 18 | UIViewController *destinationViewController = self.destinationViewController; 19 | 20 | [sourceViewController.view.superview addSubview:destinationViewController.view]; 21 | 22 | destinationViewController.view.frame = CGRectMake( 23 | 0.0f - destinationViewController.view.frame.size.width, 24 | 0.0f, 25 | destinationViewController.view.frame.size.width, 26 | destinationViewController.view.frame.size.height 27 | ); 28 | [UIView animateWithDuration:0.2f 29 | delay:0.0f 30 | options:UIViewAnimationOptionCurveEaseInOut 31 | animations:^ 32 | { 33 | sourceViewController.view.transform = CGAffineTransformMakeTranslation(sourceViewController.view.frame.size.width, 0.f); 34 | destinationViewController.view.transform = CGAffineTransformMakeTranslation(destinationViewController.view.frame.size.width, 0.0f); 35 | } 36 | completion:^(BOOL finished) 37 | { 38 | [AppDelegate sharedInstance].window.rootViewController = destinationViewController; 39 | 40 | [sourceViewController dismissViewControllerAnimated:NO completion:nil]; 41 | }]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/iOS/Segues/TestCustomSegue.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestCustomSegue.m 3 | // TestStoryboard 4 | // 5 | // Created by Ian on 12/9/13. 6 | // Copyright (c) 2013 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "TestCustomSegue.h" 10 | 11 | #import "iOSExample-Swift.h" 12 | 13 | @implementation TestCustomSegue 14 | 15 | - (void)perform 16 | { 17 | UIViewController *sourceViewController = self.sourceViewController; 18 | UIViewController *destinationViewController = self.destinationViewController; 19 | 20 | [sourceViewController.view.superview addSubview:destinationViewController.view]; 21 | 22 | destinationViewController.view.frame = CGRectMake( 23 | sourceViewController.view.frame.origin.x + sourceViewController.view.frame.size.width, 24 | 0.0f, 25 | destinationViewController.view.frame.size.width, 26 | destinationViewController.view.frame.size.height 27 | ); 28 | [UIView animateWithDuration:0.2f 29 | delay:0.0f 30 | options:UIViewAnimationOptionCurveEaseInOut 31 | animations:^ 32 | { 33 | sourceViewController.view.transform = CGAffineTransformMakeTranslation(-sourceViewController.view.frame.size.width, 0.f); 34 | destinationViewController.view.transform = CGAffineTransformMakeTranslation(-destinationViewController.view.frame.size.width, 0.0f); 35 | } 36 | completion:^(BOOL finished) 37 | { 38 | [AppDelegate sharedInstance].window.rootViewController = destinationViewController; 39 | 40 | [sourceViewController dismissViewControllerAnimated:NO completion:nil]; 41 | }];} 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Tools/setVersion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "setVersion [version]" >&2 6 | exit -1 7 | fi 8 | version=$1 9 | 10 | if [ -z "$2" ] 11 | then 12 | root='../' 13 | else 14 | root=$2 15 | fi 16 | 17 | echo "Set Version to $version, using root $root" 18 | 19 | function updatePlist() 20 | { 21 | if [ -z "$1" ] 22 | then 23 | echo "updatePlist() expects a version for first parameter" >&2 24 | return -1 25 | fi 26 | version=$1 27 | 28 | if [ -z "$2" ] 29 | then 30 | echo "updatePlist() expects a file name for second parameter" >&2 31 | return -1 32 | fi 33 | plistFile=$2 34 | 35 | # TODO: support both PlistBuddy and plutil, test for which available 36 | #PlistBuddy "$2" Set "CFBundleShortVersionString" "$1" 37 | if plutil -replace "CFBundleShortVersionString" -string "$version" "$root/$plistFile" 38 | then 39 | echo "Updated plist file $plistFile to version $version" 40 | else 41 | return -1 42 | fi 43 | 44 | return 0 45 | } 46 | 47 | plistFiles=("seguecodeBundle/Info.plist" "seguecodeKit/Info.plist" "seguecodePlugin/Info.plist") 48 | for plistFile in ${plistFiles[@]} 49 | do 50 | if !(updatePlist "$version" "$plistFile") 51 | then 52 | echo "Error while updatingPlist($version, $plistFile)" >&2 53 | exit -1 54 | fi 55 | done 56 | 57 | function updateSourceFile() 58 | { 59 | if [ -z "$1" ] 60 | then 61 | echo "updatePlist() expects a version for first parameter" 62 | return -1 63 | fi 64 | version=$1 65 | 66 | sourceFile="seguecode/SeguecodeCLIApp.m" 67 | search="s/#define SegueCodeAppVersion @\"[0-9.]*\"/#define SegueCodeAppVersion @\"$version\"/g" 68 | if sed -i -e "$search" "$root/$sourceFile" 69 | then 70 | echo "Updated source file $sourceFile to version $version" 71 | else 72 | return -1 73 | fi 74 | return 0 75 | } 76 | 77 | if !(updateSourceFile "$version") 78 | then 79 | echo "Error while updateSourceFile($version)" >&2 80 | exit -1 81 | fi 82 | -------------------------------------------------------------------------------- /seguecodeKit/Stencil/Template+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Template+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/22/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import Stencil 12 | 13 | extension Template 14 | { 15 | class func write(templateString templateString : String, outputPath : NSURL, fileName : String, context : Context) { 16 | 17 | let template = Template(templateString: templateString) 18 | template.write(outputPath: outputPath, fileName: fileName, context: context) 19 | } 20 | 21 | func write(outputPath outputPath : NSURL, fileName : String, context : Context) { 22 | do 23 | { 24 | let contents = try self.render(context) 25 | Template.writeContents(outputPath: outputPath, fileName: fileName, contents: contents) 26 | 27 | } catch let error as NSError 28 | { 29 | NSLog("Error while rendering contents: \(error).") 30 | } 31 | } 32 | 33 | private class func writeContents(outputPath outputPath : NSURL, fileName : String, contents : String) { 34 | 35 | do 36 | { 37 | try NSFileManager.defaultManager().createDirectoryAtURL(outputPath, withIntermediateDirectories: true, attributes: nil) 38 | } catch let error as NSError 39 | { 40 | NSLog("Error while creating output directory \(outputPath): \(error)") 41 | } 42 | 43 | if let path = outputPath.path 44 | { 45 | let fullFilePath = path + "/" + fileName 46 | 47 | do 48 | { 49 | try contents.writeToFile(fullFilePath, atomically: true, encoding: NSUTF8StringEncoding) 50 | NSLog("Exported \(fileName)") 51 | } catch let error as NSError 52 | { 53 | NSLog("Error while writing to file \(fullFilePath): \(error)") 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Example/iOS/Generated/SecondViewController+Main_iPhone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController+Main_iPhone.swift 3 | // Example 4 | // 5 | // Generated by seguecode [http://bit.ly/seguecode] 6 | // 7 | 8 | import UIKit 9 | 10 | extension SecondViewController { 11 | 12 | struct StoryboardInstances { 13 | static let FirstSecond = StoryboardInstance(identifier: "FirstSecond") 14 | static let SecondSecond = StoryboardInstance(identifier: "SecondSecond") 15 | } 16 | 17 | struct Segues { 18 | static let FirstSecondBackToFirst = Segue(identifier: "BackTo") 19 | static let SecondSecondBackToFirst = Segue(identifier: "BackTo") 20 | } 21 | 22 | @IBAction func performFirstSecondBackToFirst(sender : AnyObject? = nil) { 23 | self.performSegue(SecondViewController.Segues.FirstSecondBackToFirst, sender: sender) 24 | } 25 | 26 | @IBAction func performSecondSecondBackToFirst(sender : AnyObject? = nil) { 27 | self.performSegue(SecondViewController.Segues.SecondSecondBackToFirst, sender: sender) 28 | } 29 | 30 | struct TableViewCellPrototypes { 31 | static let SecondTableCell = UITableView.TableViewCellPrototype(reuseIdentifier: "SecondTableCell") 32 | } 33 | 34 | func dequeueReusableSecondTableCell(tableView : UITableView) -> UITableViewCell? { 35 | return tableView.dequeueReusableCell(SecondViewController.TableViewCellPrototypes.SecondTableCell) 36 | } 37 | 38 | func dequeueReusableSecondTableCell(tableView : UITableView, forIndexPath indexPath : NSIndexPath) -> UITableViewCell { 39 | return tableView.dequeueReusableCell(SecondViewController.TableViewCellPrototypes.SecondTableCell, forIndexPath : indexPath) 40 | } 41 | 42 | struct CollectionViewCellPrototypes { 43 | static let SecondCollectionCell = UICollectionView.CollectionViewCellPrototype(reuseIdentifier: "SecondCollectionCell") 44 | } 45 | 46 | func dequeueReusableSecondCollectionCell(collectionView : UICollectionView, forIndexPath indexPath : NSIndexPath) -> UICollectionViewCell { 47 | return collectionView.dequeueReusableCell(SecondViewController.CollectionViewCellPrototypes.SecondCollectionCell, forIndexPath : indexPath) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Example/iOS/Generated/UIViewController+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+seguecode.swift 3 | // Example 4 | // 5 | // Generated by seguecode [http://bit.ly/seguecode] 6 | // 7 | 8 | import UIKit 9 | 10 | extension UIViewController { 11 | class Segue : NSObject 12 | { 13 | let identifier : String 14 | 15 | init(identifier : String) { 16 | self.identifier = identifier 17 | } 18 | } 19 | 20 | func performSegue(segue : Segue, sender : AnyObject?) { 21 | self.performSegueWithIdentifier(segue.identifier, sender: sender) 22 | } 23 | 24 | class StoryboardInstance : NSObject 25 | { 26 | let identifier : String 27 | 28 | init(identifier : String) { 29 | self.identifier = identifier 30 | } 31 | } 32 | } 33 | 34 | extension UIStoryboard { 35 | func instantiateViewController(instance : UIViewController.StoryboardInstance) -> UIViewController { 36 | 37 | return self.instantiateViewControllerWithIdentifier(instance.identifier) 38 | } 39 | } 40 | 41 | extension UITableView { 42 | class TableViewCellPrototype : NSObject 43 | { 44 | let reuseIdentifier : String 45 | 46 | init(reuseIdentifier : String) { 47 | self.reuseIdentifier = reuseIdentifier 48 | } 49 | } 50 | 51 | func dequeueReusableCell(cellPrototype : TableViewCellPrototype) -> UITableViewCell? { 52 | return self.dequeueReusableCellWithIdentifier(cellPrototype.reuseIdentifier) 53 | } 54 | 55 | func dequeueReusableCell(cellPrototype : TableViewCellPrototype, forIndexPath indexPath : NSIndexPath) -> UITableViewCell { 56 | return self.dequeueReusableCellWithIdentifier(cellPrototype.reuseIdentifier, forIndexPath: indexPath) 57 | } 58 | } 59 | 60 | extension UICollectionView { 61 | class CollectionViewCellPrototype : NSObject 62 | { 63 | let reuseIdentifier : String 64 | 65 | init(reuseIdentifier : String) { 66 | self.reuseIdentifier = reuseIdentifier 67 | } 68 | } 69 | 70 | func dequeueReusableCell(cellPrototype : CollectionViewCellPrototype, forIndexPath indexPath : NSIndexPath) -> UICollectionViewCell { 71 | return self.dequeueReusableCellWithReuseIdentifier(cellPrototype.reuseIdentifier, forIndexPath: indexPath) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSNotification+Utility.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotification+Utility.m 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "NSNotification+Utility.h" 10 | 11 | @implementation NSNotification (Utility) 12 | 13 | - (BOOL)isXcodeEvent 14 | { 15 | return !( [ [self name] length] >= 2 && [ [ [self name] substringWithRange:NSMakeRange(0, 2) ] isEqualTo:@"NS"] ); 16 | } 17 | 18 | + (NSString *)transitionFromOneFileToAnotherName 19 | { 20 | return @"transition from one file to another"; 21 | } 22 | 23 | - (BOOL)isTransitionFromOneFileToAnother 24 | { 25 | return [ [self name] isEqualToString:[NSNotification transitionFromOneFileToAnotherName] ]; 26 | } 27 | 28 | - (NSDictionary *)transitionFromOneFileToAnotherInfo 29 | { 30 | NSDictionary *result; 31 | if ( [self isTransitionFromOneFileToAnother] && [ [self object] isKindOfClass:[NSDictionary class] ] ) 32 | { 33 | result = [self object]; 34 | } 35 | return result; 36 | } 37 | 38 | - (id)transitionFromOneFileToAnotherNext 39 | { 40 | id result; 41 | if ( [self isTransitionFromOneFileToAnother] ) 42 | { 43 | NSDictionary *info = [self transitionFromOneFileToAnotherInfo]; 44 | result = [info objectForKey:@"next"]; 45 | } 46 | 47 | return result; 48 | } 49 | 50 | - (NSURL *)transitionFromOneFileToAnotherNextDocumentURL 51 | { 52 | NSURL *result; 53 | 54 | if ( [self isTransitionFromOneFileToAnother] ) 55 | { 56 | id nextObject = [self transitionFromOneFileToAnotherNext]; 57 | Class DVTDocumentLocation = NSClassFromString(@"DVTDocumentLocation"); 58 | if ( [nextObject isKindOfClass:DVTDocumentLocation] ) 59 | { 60 | id documentURLObject = [nextObject performSelector:@selector(documentURL) ]; 61 | if ( [documentURLObject isKindOfClass:[NSURL class] ] ) 62 | { 63 | result = documentURLObject; 64 | } 65 | } 66 | } 67 | 68 | return result; 69 | } 70 | 71 | + (NSString *)ideEditorDocumentDidSaveName 72 | { 73 | return @"IDEEditorDocumentDidSaveNotification"; 74 | } 75 | 76 | - (BOOL)isIDEEditorDocumentDidSave 77 | { 78 | return [ [self name] isEqualToString:[NSNotification ideEditorDocumentDidSaveName] ]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /seguecode.xcworkspace/xcshareddata/seguecode.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | BB21261B-E6DA-404F-88F3-FDD70CC8EAB9 9 | IDESourceControlProjectName 10 | seguecode 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 135769308420168AF7DDF8DC60BCB834AAD3928B 14 | github.com:yoiang/seguecode.git 15 | B0E6B06954F391D32E10FEBDE27034186A3BEF62 16 | https://github.com/ddribin/ddcli.git 17 | CBF5F70D4EDC8047BC75C25236002B0EA7F6B15B 18 | https://github.com/jatoben/CommandLine.git 19 | 20 | IDESourceControlProjectPath 21 | seguecode.xcworkspace 22 | IDESourceControlProjectRelativeInstallPathDictionary 23 | 24 | 135769308420168AF7DDF8DC60BCB834AAD3928B 25 | .. 26 | B0E6B06954F391D32E10FEBDE27034186A3BEF62 27 | ../Library/ddcli 28 | CBF5F70D4EDC8047BC75C25236002B0EA7F6B15B 29 | ../Library/CommandLine 30 | 31 | IDESourceControlProjectURL 32 | github.com:yoiang/seguecode.git 33 | IDESourceControlProjectVersion 34 | 111 35 | IDESourceControlProjectWCCIdentifier 36 | 135769308420168AF7DDF8DC60BCB834AAD3928B 37 | IDESourceControlProjectWCConfigurations 38 | 39 | 40 | IDESourceControlRepositoryExtensionIdentifierKey 41 | public.vcs.git 42 | IDESourceControlWCCIdentifierKey 43 | CBF5F70D4EDC8047BC75C25236002B0EA7F6B15B 44 | IDESourceControlWCCName 45 | CommandLine 46 | 47 | 48 | IDESourceControlRepositoryExtensionIdentifierKey 49 | public.vcs.git 50 | IDESourceControlWCCIdentifierKey 51 | B0E6B06954F391D32E10FEBDE27034186A3BEF62 52 | IDESourceControlWCCName 53 | ddcli 54 | 55 | 56 | IDESourceControlRepositoryExtensionIdentifierKey 57 | public.vcs.git 58 | IDESourceControlWCCIdentifierKey 59 | 135769308420168AF7DDF8DC60BCB834AAD3928B 60 | IDESourceControlWCCName 61 | seguecode 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /seguecode.xcodeproj/xcshareddata/xcschemes/seguecodeKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Example/iOS/Generated/Main_iPhone.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Main_iPhone.swift 3 | // Example 4 | // 5 | // Generated by seguecode [http://bit.ly/seguecode] 6 | // 7 | 8 | import UIKit 9 | 10 | extension FirstViewController { 11 | 12 | struct StoryboardInstances { 13 | static let First = StoryboardInstance(identifier: "First") 14 | } 15 | 16 | struct Segues { 17 | static let FirstForwardToUIVC = Segue(identifier: "ForwardToUIVC") 18 | static let FirstGoToSecondSecond = Segue(identifier: "GoTo") 19 | static let FirstForwardToFirstSecond = Segue(identifier: "ForwardTo") 20 | } 21 | 22 | @IBAction func performFirstForwardToUIVC(sender : AnyObject? = nil) { 23 | self.performSegue(FirstViewController.Segues.FirstForwardToUIVC, sender: sender) 24 | } 25 | 26 | @IBAction func performFirstGoToSecondSecond(sender : AnyObject? = nil) { 27 | self.performSegue(FirstViewController.Segues.FirstGoToSecondSecond, sender: sender) 28 | } 29 | 30 | @IBAction func performFirstForwardToFirstSecond(sender : AnyObject? = nil) { 31 | self.performSegue(FirstViewController.Segues.FirstForwardToFirstSecond, sender: sender) 32 | } 33 | } 34 | 35 | extension UIViewController { 36 | 37 | struct Segues { 38 | static let BackToFirst = Segue(identifier: "BackTo") 39 | } 40 | 41 | @IBAction func performBackToFirst(sender : AnyObject? = nil) { 42 | self.performSegue(UIViewController.Segues.BackToFirst, sender: sender) 43 | } 44 | } 45 | 46 | extension SecondViewController { 47 | 48 | struct StoryboardInstances { 49 | static let FirstSecond = StoryboardInstance(identifier: "FirstSecond") 50 | static let SecondSecond = StoryboardInstance(identifier: "SecondSecond") 51 | } 52 | 53 | struct Segues { 54 | static let FirstSecondBackToFirst = Segue(identifier: "BackTo") 55 | static let SecondSecondBackToFirst = Segue(identifier: "BackTo") 56 | } 57 | 58 | @IBAction func performFirstSecondBackToFirst(sender : AnyObject? = nil) { 59 | self.performSegue(SecondViewController.Segues.FirstSecondBackToFirst, sender: sender) 60 | } 61 | 62 | @IBAction func performSecondSecondBackToFirst(sender : AnyObject? = nil) { 63 | self.performSegue(SecondViewController.Segues.SecondSecondBackToFirst, sender: sender) 64 | } 65 | 66 | struct TableViewCellPrototypes { 67 | static let SecondTableCell = UITableView.TableViewCellPrototype(reuseIdentifier: "SecondTableCell") 68 | } 69 | 70 | func dequeueReusableSecondTableCell(tableView : UITableView) -> UITableViewCell? { 71 | return tableView.dequeueReusableCell(SecondViewController.TableViewCellPrototypes.SecondTableCell) 72 | } 73 | 74 | func dequeueReusableSecondTableCell(tableView : UITableView, forIndexPath indexPath : NSIndexPath) -> UITableViewCell { 75 | return tableView.dequeueReusableCell(SecondViewController.TableViewCellPrototypes.SecondTableCell, forIndexPath : indexPath) 76 | } 77 | 78 | struct CollectionViewCellPrototypes { 79 | static let SecondCollectionCell = UICollectionView.CollectionViewCellPrototype(reuseIdentifier: "SecondCollectionCell") 80 | } 81 | 82 | func dequeueReusableSecondCollectionCell(collectionView : UICollectionView, forIndexPath indexPath : NSIndexPath) -> UICollectionViewCell { 83 | return collectionView.dequeueReusableCell(SecondViewController.CollectionViewCellPrototypes.SecondCollectionCell, forIndexPath : indexPath) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /seguecodePlugin.xcodeproj/xcshareddata/xcschemes/seguecodePluginLocal.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 46 | 50 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /seguecode.xcodeproj/xcshareddata/xcschemes/seguecodeiOSExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /seguecodePlugin.xcodeproj/xcshareddata/xcschemes/seguecodePlugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 61 | 65 | 66 | 67 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /seguecodeKit/StoryboardKit/SegueInstanceInfo+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SegueInstanceInfo+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/22/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | import Stencil 14 | 15 | extension SegueInstanceInfo 16 | { 17 | var segueCaseName : String? { 18 | var result : String? 19 | 20 | if let identifier = self.identifier, 21 | let source = self.source.value, 22 | let sourceIdentifier = source.storyboardIdentifier, 23 | let destination = self.destination.value, 24 | let destinationIdentifier = destination.storyboardIdentifier 25 | { 26 | result = sourceIdentifier + identifier + destinationIdentifier 27 | } 28 | 29 | return result 30 | } 31 | 32 | var segueCaseValue : String? { 33 | return self.identifier 34 | } 35 | 36 | func segueCaseStencilContext() -> [String : String]? { 37 | var result : [String : String]? 38 | 39 | if let segueCaseValue = self.segueCaseValue 40 | { 41 | var context = [ 42 | DefaultTemplate.Keys.ViewController.SegueCase.Value : segueCaseValue 43 | ] 44 | 45 | var minimumRequirement = false 46 | 47 | if let identifier = self.identifier 48 | { 49 | context[DefaultTemplate.Keys.ViewController.SegueCase.Identifier] = identifier 50 | minimumRequirement = true 51 | } 52 | 53 | if let source = self.source.value, 54 | let sourceIdentifier = source.storyboardIdentifier 55 | { 56 | context[DefaultTemplate.Keys.ViewController.SegueCase.SourceIdentifier] = sourceIdentifier 57 | minimumRequirement = true 58 | } 59 | 60 | if let destination = self.destination.value, 61 | let destinationIdentifier = destination.storyboardIdentifier 62 | { 63 | context[DefaultTemplate.Keys.ViewController.SegueCase.DestinationIdentifier] = destinationIdentifier 64 | minimumRequirement = true 65 | } 66 | 67 | if minimumRequirement == true 68 | { 69 | result = context 70 | } 71 | } 72 | 73 | return result 74 | } 75 | 76 | func peformFunctionStencilContext() -> [String : String]? { 77 | var result : [String : String]? 78 | 79 | var context = [String : String]() 80 | 81 | var minimumRequirement = false 82 | 83 | if let identifier = self.identifier 84 | { 85 | context[DefaultTemplate.Keys.ViewController.SegueCase.Identifier] = identifier 86 | minimumRequirement = true 87 | } 88 | 89 | if let source = self.source.value, 90 | let sourceIdentifier = source.storyboardIdentifier 91 | { 92 | context[DefaultTemplate.Keys.ViewController.SegueCase.SourceIdentifier] = sourceIdentifier 93 | minimumRequirement = true 94 | } 95 | 96 | if let destination = self.destination.value, 97 | let destinationIdentifier = destination.storyboardIdentifier 98 | { 99 | context[DefaultTemplate.Keys.ViewController.SegueCase.DestinationIdentifier] = destinationIdentifier 100 | minimumRequirement = true 101 | } 102 | 103 | if minimumRequirement == true 104 | { 105 | result = context 106 | } 107 | 108 | return result 109 | } 110 | } -------------------------------------------------------------------------------- /seguecode.xcodeproj/xcshareddata/xcschemes/seguecode.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 68 | 69 | 72 | 73 | 76 | 77 | 78 | 79 | 80 | 81 | 87 | 89 | 95 | 96 | 97 | 98 | 100 | 101 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSMutableDictionary+RunConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+RunConfig.m 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+RunConfig.h" 10 | 11 | #import "NSURL+Utility.h" 12 | 13 | NSString *const RunConfigSuffix = @".seguecode.json"; 14 | 15 | @implementation NSMutableDictionary (RunConfig) 16 | 17 | + (NSURL *)runConfigPathForStoryboardAtURL:(NSURL *)storyboardURL 18 | { 19 | return [NSURL URLWithFormat:@"%@%@", [storyboardURL URLByDeletingPathExtension], RunConfigSuffix]; 20 | } 21 | 22 | + (NSMutableDictionary *)dictionaryWithContentsOfJSONURL:(NSURL *)url 23 | { 24 | NSMutableDictionary *result; 25 | 26 | NSData *data = [NSData dataWithContentsOfURL:url]; 27 | 28 | NSError *error; 29 | if (data) 30 | { 31 | result = [NSJSONSerialization JSONObjectWithData:data 32 | options:0 33 | error:&error]; 34 | 35 | if (error) 36 | { 37 | NSLog(@"Error when reading JSON config from %@", url); 38 | } 39 | } 40 | 41 | return result; 42 | } 43 | 44 | + (NSMutableDictionary *)runConfigForStoryboardAtURL:(NSURL *)storyboardURL 45 | { 46 | return [NSMutableDictionary dictionaryWithContentsOfJSONURL:[self runConfigPathForStoryboardAtURL:storyboardURL] ]; 47 | } 48 | 49 | - (BOOL)writeContentsToJSONURL:(NSURL *)url 50 | { 51 | BOOL result = NO; 52 | 53 | NSError *error; 54 | NSData *data = [NSJSONSerialization dataWithJSONObject:self 55 | options:0 56 | error:&error]; 57 | if (error) 58 | { 59 | NSLog(@"Error when serializing JSON config: %@", error); 60 | } 61 | 62 | if (data) 63 | { 64 | result = [data writeToURL:url 65 | options:NSDataWritingAtomic 66 | error:&error]; 67 | 68 | if (error) 69 | { 70 | NSLog(@"Error when writing JSON config to %@: %@", url, error); 71 | } 72 | } 73 | 74 | return result; 75 | } 76 | 77 | - (BOOL)writeRunConfigForStoryboardAtURL:(NSURL *)storyboardURL 78 | { 79 | return [self writeContentsToJSONURL:[NSMutableDictionary runConfigPathForStoryboardAtURL:storyboardURL] ]; 80 | } 81 | 82 | + (NSString *)outputPathKey 83 | { 84 | return @"outputPath"; 85 | } 86 | 87 | - (void)setOutputPath:(NSString *)outputPath 88 | { 89 | if (outputPath) 90 | { 91 | [self setObject:outputPath 92 | forKey:[NSMutableDictionary outputPathKey] 93 | ]; 94 | } else 95 | { 96 | [self removeObjectForKey:[NSMutableDictionary outputPathKey] ]; 97 | } 98 | } 99 | 100 | - (NSString *)outputPath 101 | { 102 | return [self objectForKey:[NSMutableDictionary outputPathKey] ]; 103 | } 104 | 105 | + (NSString *)combineKey 106 | { 107 | return @"combine"; 108 | } 109 | 110 | - (void)setCombine:(BOOL)combine 111 | { 112 | [self setObject:[NSNumber numberWithBool:combine] 113 | forKey:[NSMutableDictionary combineKey] 114 | ]; 115 | } 116 | 117 | - (BOOL)combine 118 | { 119 | BOOL result; 120 | 121 | NSNumber *number = [self objectForKey:[NSMutableDictionary combineKey] ]; 122 | if (number != nil) 123 | { 124 | result = [number boolValue]; 125 | } else 126 | { 127 | result = NO; 128 | } 129 | 130 | return result; 131 | } 132 | 133 | + (NSString *)projectNameKey 134 | { 135 | return @"projectName"; 136 | } 137 | 138 | - (void)setProjectName:(NSString *)projectName 139 | { 140 | if (projectName) 141 | { 142 | [self setObject:projectName 143 | forKey:[NSMutableDictionary projectNameKey] 144 | ]; 145 | } else 146 | { 147 | [self removeObjectForKey:[NSMutableDictionary projectNameKey] ]; 148 | } 149 | } 150 | 151 | - (NSString *)projectName 152 | { 153 | return [self objectForKey:[NSMutableDictionary projectNameKey] ]; 154 | } 155 | 156 | + (BOOL)removeRunConfigForStoryboardAtURL:(NSURL *)storyboardURL 157 | { 158 | return [ [NSFileManager defaultManager] removeItemAtURL:[self runConfigPathForStoryboardAtURL:storyboardURL] error:nil]; 159 | } 160 | 161 | @end 162 | -------------------------------------------------------------------------------- /seguecode.xcodeproj/xcshareddata/xcschemes/seguecodeBundle.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 68 | 69 | 72 | 73 | 76 | 77 | 80 | 81 | 84 | 85 | 86 | 87 | 88 | 89 | 95 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /seguecode/SeguecodeCLIApp.m: -------------------------------------------------------------------------------- 1 | // 2 | // SeguecodeCLIApp.m 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/24/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "SeguecodeCLIApp.h" 10 | 11 | #import 12 | #import 13 | 14 | @import seguecodeKit; 15 | 16 | #define SegueCodeAppVersion @"2.3.1" 17 | 18 | @interface SeguecodeCLIApp () 19 | { 20 | BOOL _combine; 21 | 22 | BOOL _verbose; 23 | 24 | BOOL _help; 25 | BOOL _version; 26 | } 27 | 28 | @end 29 | 30 | @implementation NSString (SeguecodeCLIApp) 31 | 32 | - (NSString *)stringByRemovingEnclosingQuotes 33 | { 34 | NSString *result = nil; 35 | 36 | if (self.length >= 2 && 37 | ([self characterAtIndex:0] == '\"' || [self characterAtIndex:0] == '\'') && 38 | [self characterAtIndex:self.length - 1] == [self characterAtIndex:0]) 39 | { 40 | result = [ [self substringToIndex:self.length - 1] substringToIndex:0]; 41 | } else 42 | { 43 | result = self; 44 | } 45 | return result; 46 | } 47 | 48 | @end 49 | 50 | @implementation SeguecodeCLIApp 51 | 52 | - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser *)optionsParser 53 | { 54 | DDGetoptOption optionTable[] = 55 | { 56 | {"outputPath", 'o', DDGetoptRequiredArgument}, 57 | 58 | {"combine", 'c', DDGetoptNoArgument}, 59 | 60 | {"projectName", 'p', DDGetoptRequiredArgument}, 61 | 62 | {"verbose", 'l', DDGetoptNoArgument}, 63 | 64 | {"help", 'h', DDGetoptNoArgument}, 65 | {"version", 'v', DDGetoptNoArgument}, 66 | {nil, 0, 0}, 67 | }; 68 | [optionsParser addOptionsFromTable: optionTable]; 69 | } 70 | 71 | - (void)printUsage 72 | { 73 | ddprintf(@"%@: Usage [OPTIONS] first.storyboard [second.storyboard...]\n", DDCliApp); 74 | ddprintf(@" -o, --outputPath DIR (Required) Path to output generated files.\n" 75 | @" -c, --combine Export the View Controllers combined in one file\n" 76 | @" -p, --projectName NAME Name to use as project in source file header comment\n" 77 | @"\n" 78 | @" -l, --verbose Output verbose logging\n" 79 | @"\n" 80 | @" -v, --version Display seguecode's version\n" 81 | @" -h, --help Display help\n"); 82 | } 83 | 84 | - (BOOL)exportStoryboardFile:(NSString *)fileName 85 | { 86 | BOOL result = NO; 87 | 88 | NSString *pathFileName; 89 | fileName = [fileName stringByRemovingEnclosingQuotes]; 90 | if ( [fileName length] > 0 && [fileName characterAtIndex:0] == '/' ) 91 | { 92 | pathFileName = fileName; 93 | } else 94 | { 95 | NSString *path = [ [NSFileManager defaultManager] currentDirectoryPath]; 96 | pathFileName = [NSString stringWithFormat:@"%@/%@", path, fileName]; 97 | } 98 | NSURL *storyboardPathFileNameUrl = [NSURL fileURLWithPath:pathFileName]; 99 | 100 | NSString *outputPath; 101 | self.outputPath = [self.outputPath stringByRemovingEnclosingQuotes]; 102 | if ( [self.outputPath length] > 0 && [self.outputPath characterAtIndex:0] == '/' ) 103 | { 104 | outputPath = self.outputPath; 105 | } else 106 | { 107 | NSString *path = [ [NSFileManager defaultManager] currentDirectoryPath]; 108 | outputPath = [NSString stringWithFormat:@"%@/%@", path, self.outputPath]; 109 | } 110 | NSURL *outputPathUrl = [NSURL fileURLWithPath:outputPath]; 111 | 112 | BOOL combine = _combine; 113 | BOOL verboseLogging = _verbose; 114 | 115 | if (outputPathUrl != nil) 116 | { 117 | result = YES; 118 | [seguecode parse:storyboardPathFileNameUrl outputPath:outputPathUrl projectName:self.projectName exportTogether:combine verboseLogging:verboseLogging]; 119 | } 120 | 121 | return result; 122 | } 123 | 124 | - (int)application:(DDCliApplication *)app runWithArguments:(NSArray *)arguments 125 | { 126 | if (_help) 127 | { 128 | [self printUsage]; 129 | return EXIT_SUCCESS; 130 | } 131 | 132 | if (_version) 133 | { 134 | ddprintf(@"%@ %@\n", DDCliApp, SegueCodeAppVersion); 135 | return EXIT_SUCCESS; 136 | } 137 | 138 | __block BOOL error = NO; 139 | [arguments enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 140 | { 141 | if ( [obj isKindOfClass:[NSString class] ] ) 142 | { 143 | if ( ![self exportStoryboardFile:(NSString *)obj] ) 144 | { 145 | error = YES; 146 | } 147 | } 148 | }]; 149 | 150 | return error; 151 | } 152 | 153 | @end 154 | 155 | 156 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # seguecode 2 | 3 | [![Travis Build Status](http://img.shields.io/travis/Adorkable/seguecode.svg?style=flat)](https://travis-ci.org/Adorkable/seguecode) 4 | 5 | **seguecode** is a support tool to use alongside `UIStoryboard` development. It provides compile-time safeties around building with `UIStoryboard`s in an effort to create an error free workflow so you can focus on the important things. 6 | 7 | This include exposing: 8 | 9 | * Storyboard Scene Identifiers 10 | * Segue Identifiers 11 | * Table View Cell Prototype Identifiers 12 | * Collection View Cell Prototype Identifiers 13 | 14 | ## Xcode Plugin 15 | 16 | ### Installation 17 | 18 | #### Alcatraz 19 | **AT THE MOMENT ALCATRAZ INSTALLATION IS BROKEN DUE TO ALCATRAZ'S METHOD OF BUILDING AND INSTALLING. 20 | UNTIL A COMPATIBLE WRAPPER PROJECT CAN BE REWRITTEN PLEASE USE THE [MANUAL INSTALLATION STEPS BELOW](https://github.com/Adorkable/seguecode/blob/master/README.md#manually).** 21 | 22 | The easiest way to get and use **seguecode** is through the wonderful Xcode plugin manager [Alcatraz](http://alcatraz.io/). The **seguecode** plugin, when enabled for a storyboard, will detect when you save your storyboard and automatically regenerate your **seguecode** source code. 23 | 24 | #### Manually 25 | 1. Clone the repo 26 | 2. Run `git submodule init ; git submodule update` 27 | 3. Run `pod install` 28 | 4. Open `seguecode.xcworkspace` and build the `seguecodePlugin` scheme 29 | 5. Close and reopen Xcode 30 | 31 | ### Usage 32 | To enable the **seguecode** plugin for a storyboard: 33 | 34 | 1. Open the storyboard in Xcode 35 | 2. Pull down Xcode's *Edit menu* and select the **seguecode** option 36 | 37 | ![Plugin Screenshot](https://raw.githubusercontent.com/Adorkable/seguecode/master/README/Edit_and_Menubar.png) 38 | 39 | This will generate a file alongside your storyboard called *<Storyboard Name>.seguecode.json* which contains configuration information you can change to define how the automatic regeneration works. 40 | 41 | The **seguecode** plugin looks for this json file to see if it should be enabled for a particular storyboard file, deleting it, or unchecking the **seguecode** option in the *Edit menu*, will disable the automatic regeneration. 42 | 43 | ## Command Line 44 | You can download the [latest release](https://github.com/Adorkable/seguecode/releases/latest) 45 | 46 | or 47 | 48 | You can make your own build: 49 | 50 | 1. Clone the repo 51 | 2. Install the appropriate **[cocoapods](http://cocoapods.org)** with `pod install` 52 | 3. Build the binary 53 | 4. Place it in your favorite location for easy access. 54 | 55 | It is recommended that you include a run of **seguecode** in your project as a *Run Script Build Phase* or as an *External Build Target*. 56 | 57 | ### Exporting 58 | For an accurate list of parameters run `seguecode --help` or `seguecode -h` 59 | 60 | The most common usage is 61 | 62 | ``` Shell 63 | seguecode -o OutputFolder/ ExportMe.storyboard 64 | ``` 65 | 66 | The resulting header and source files will be exported with the same name as your storyboard file. To use them they should be included in your project and your target. 67 | 68 | **Note**: at minimum **seguecode** expects an output location and at least one storyboard file 69 | 70 | ### Exporting Customization 71 | To further customize your export use the following parameters: 72 | 73 | * `-c` or `--combine` - Export the View Controllers combined in one file 74 | * `-p` or `--projectName NAME` - Name to use as project in source file header comment 75 | * `-l` or `--verbose` - Output verbose logging 76 | * `-v` or `--version` - Display **seguecode**'s version 77 | * `-h` or `--help` - Display help 78 | 79 | ## Preparing your Storyboard 80 | To ensure a proper export please make sure: 81 | 82 | * the segue you wish to use has an *Identifier* 83 | 84 | For extra clarity and reduced conflicts please make sure: 85 | 86 | * the source and destination view controllers have *Storyboard ID*s 87 | 88 | ### Results 89 | 90 | #### Storyboard Identifier 91 | ##### TODO 92 | 93 | #### Segue Identifier 94 | 95 | Your exported header and source files will contain categories with selectors that describe your segue as well as optionally constants that can be used in your view controller ala `self.performSegueWithIdentifier(..., sender: ...)` call. 96 | 97 | The resulting selectors and constants will depend on the segue *Identifier* and *Storyboard ID*s you used in your `UIStoryboard`. 98 | 99 | For example, if you give your segue the *Identifier* `MyHead`, the source view controller's *Storyboard ID* `Down` and the destination view controller's `MyToes` the results will be: 100 | 101 | Easy method calls: 102 | 103 | ``` Swift 104 | extension MyViewController { 105 | @IBAction func performDownFromMyHead(sender : AnyObject? = nil) 106 | } 107 | ``` 108 | 109 | Easy constants: 110 | 111 | ``` Swift 112 | extension MyViewController { 113 | struct Segues { 114 | static let DownFromMyHead 115 | } 116 | } 117 | ``` 118 | 119 | To use the constant directly from your view controller call: 120 | 121 | ``` Swift 122 | self.performSegue(MyViewController.Segues.DownFromMyHead, sender: sender) 123 | ``` 124 | 125 | #### Table View Cell Prototype Identifiers 126 | ##### TODO 127 | 128 | #### Collection View Cell Prototype Identifiers 129 | ##### TODO 130 | 131 | ## Contributing 132 | **seguecode** is a new project that will hopefully continue to grow in usefulness. If you have any ideas or suggestions on how it can better serve you please [create an issue](https://github.com/Adorkable/seguecode/issues/new) labeled *feature* (check to see if the issue exists first please!). Or suggest a pull request! 133 | 134 | 135 | ## Thanks 136 | 137 | Props to **[mogenerator](https://github.com/rentzsch/mogenerator)** for pointing out **[ddcli](https://github.com/ddribin/ddcli)**. And being a CoreData savior. And the kick in the butt to start **seguecode**. 138 | -------------------------------------------------------------------------------- /seguecodePlugin/Utility/NSObject+Utility.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Utility.m 3 | // seguecode 4 | // 5 | // Created by Ian on 11/5/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Utility.h" 10 | 11 | NSString *const NSObjectUtilityClassInfoPropertyNamesKey = @"properties"; 12 | NSString *const NSObjectUtilityClassInfoMethodNamesKey = @"methods"; 13 | NSString *const NSObjectUtilityClassInfoIVarNamesKey = @"ivars"; 14 | 15 | @implementation NSObject (Utility) 16 | 17 | + (NSString *)propertyName:(objc_property_t)property 18 | { 19 | const char *propertyName = property_getName(property); 20 | return [NSString stringWithCString:propertyName encoding:NSASCIIStringEncoding]; 21 | } 22 | 23 | + (NSString *)methodName:(Method)method 24 | { 25 | NSString *result; 26 | 27 | SEL selector = method_getName(method); 28 | NSString *methodName = NSStringFromSelector(selector); 29 | if (methodName) 30 | { 31 | result = methodName; 32 | } else 33 | { 34 | result = [NSString stringWithFormat:@"Cannot find method %@", method]; 35 | } 36 | 37 | return result; 38 | } 39 | 40 | + (NSString *)ivarName:(Ivar)ivar 41 | { 42 | const char* ivarName = ivar_getName(ivar); 43 | return [NSString stringWithCString:ivarName encoding:NSASCIIStringEncoding]; 44 | } 45 | 46 | + (NSDictionary *)classInfoForClass:(Class)class 47 | { 48 | // based on: https://stackoverflow.com/questions/2299841/objective-c-introspection-reflection/2302808#2302808 49 | u_int count; 50 | 51 | objc_property_t* properties = class_copyPropertyList(class, &count); 52 | NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count]; 53 | for (int i = 0; i < count ; i++) 54 | { 55 | [propertyArray addObject:[self propertyName:properties[i] ] ]; 56 | } 57 | free(properties); 58 | 59 | Method* methods = class_copyMethodList(class, &count); 60 | NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count]; 61 | for (int i = 0; i < count ; i++) 62 | { 63 | [methodArray addObject:[self methodName:methods[i] ] ]; 64 | } 65 | free(methods); 66 | 67 | Ivar* ivars = class_copyIvarList(class, &count); 68 | NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count]; 69 | for (int i = 0; i < count ; i++) 70 | { 71 | [ivarArray addObject:[self ivarName:ivars[i] ] ]; 72 | } 73 | free(ivars); 74 | 75 | return @{ 76 | NSObjectUtilityClassInfoPropertyNamesKey : propertyArray, 77 | NSObjectUtilityClassInfoMethodNamesKey : methodArray, 78 | NSObjectUtilityClassInfoIVarNamesKey : ivarArray 79 | }; 80 | } 81 | 82 | + (NSDictionary *)classInfoForClassName:(NSString *)name 83 | { 84 | NSDictionary *result; 85 | 86 | Class class = NSClassFromString(name); 87 | if (class) 88 | { 89 | result = [self classInfoForClass:class]; 90 | } else 91 | { 92 | result = @{@"error" : [NSString stringWithFormat:@"Cannot find class named %@", name]}; 93 | } 94 | return result; 95 | } 96 | 97 | - (NSDictionary *)classInfo 98 | { 99 | return [NSObject classInfoForClass:[self class] ]; 100 | } 101 | 102 | - (id)valueForPropertyWithName:(NSString *)propertyName 103 | { 104 | id result; 105 | 106 | @try 107 | { 108 | result = [self valueForKey:propertyName]; 109 | } @catch (NSException *exception) 110 | { 111 | result = exception; 112 | } 113 | 114 | return result; 115 | } 116 | 117 | - (id)valueForMethodWithName:(NSString *)methodName 118 | { 119 | id result; 120 | 121 | if ( [methodName rangeOfString:@":"].location == NSNotFound) 122 | { 123 | SEL selector = NSSelectorFromString(methodName); 124 | if (selector && [self respondsToSelector:selector] ) 125 | { 126 | result = [self performSelector:selector]; 127 | } else 128 | { 129 | result = [NSString stringWithFormat:@"Selector %@ not found in instance", NSStringFromSelector(selector) ]; 130 | } 131 | } else 132 | { 133 | result = [NSString stringWithFormat:@"?"]; 134 | } 135 | 136 | return result; 137 | } 138 | 139 | - (NSDictionary *)instanceInfo 140 | { 141 | NSDictionary *classInfo = [self classInfo]; 142 | 143 | NSArray *propertyNames = [classInfo objectForKey:NSObjectUtilityClassInfoPropertyNamesKey]; 144 | NSMutableArray *propertiesWithValues = [NSMutableArray arrayWithCapacity:propertyNames.count]; 145 | for (NSString *propertyName in propertyNames) 146 | { 147 | NSString *propertyWithValue = [NSString stringWithFormat:@"%@ = %@", propertyName, [self valueForPropertyWithName:propertyName] ]; 148 | [propertiesWithValues addObject:propertyWithValue]; 149 | } 150 | 151 | NSArray *methodNames = [classInfo objectForKey:NSObjectUtilityClassInfoMethodNamesKey]; 152 | NSMutableArray *methodsWithValues = [NSMutableArray arrayWithCapacity:methodNames.count]; 153 | for (NSString *methodName in methodNames) 154 | { 155 | NSString *methodWithValue = [NSString stringWithFormat:@"%@ = %@", methodName, [self valueForMethodWithName:methodName] ]; 156 | [methodsWithValues addObject:methodWithValue]; 157 | } 158 | 159 | NSArray *ivarNames = [classInfo objectForKey:NSObjectUtilityClassInfoIVarNamesKey]; 160 | NSMutableArray *ivarsWithValues = [NSMutableArray arrayWithCapacity:ivarNames.count]; 161 | for (NSString *ivarName in ivarNames) 162 | { 163 | NSString *ivarWithValue = [NSString stringWithFormat:@"%@ = %@", ivarName, [self valueForPropertyWithName:ivarName] ]; 164 | [ivarsWithValues addObject:ivarWithValue]; 165 | } 166 | 167 | return @{ 168 | NSObjectUtilityClassInfoPropertyNamesKey : propertiesWithValues, 169 | NSObjectUtilityClassInfoMethodNamesKey : methodsWithValues, 170 | NSObjectUtilityClassInfoIVarNamesKey : ivarsWithValues 171 | }; 172 | } 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /seguecodeKit/seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/22/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | import Stencil 14 | 15 | public class seguecode : NSObject 16 | { 17 | public class func parse(storyboardFilePath : NSURL, outputPath : NSURL, projectName : String?, exportTogether : Bool, verboseLogging : Bool) { 18 | let application = ApplicationInfo() 19 | 20 | if let path = storyboardFilePath.path 21 | { 22 | NSLog("Reading \(path)") 23 | } else 24 | { 25 | NSLog("Reading \(storyboardFilePath)") 26 | } 27 | 28 | if let path = outputPath.path 29 | { 30 | NSLog("Writing to output path \(path)") 31 | } else 32 | { 33 | NSLog("Writing to output path \(outputPath)") 34 | } 35 | if let projectName = projectName 36 | { 37 | NSLog("Using project name \"\(projectName)\"") 38 | } 39 | 40 | NSLog("\n") 41 | 42 | if let storyboardFilePathString = storyboardFilePath.path 43 | { 44 | 45 | do { 46 | let result = try StoryboardFileParser.parse(application, pathFileName: storyboardFilePathString) 47 | 48 | if verboseLogging == true 49 | { 50 | if let logs = result.1 51 | { 52 | if logs.count > 0 53 | { 54 | NSLog("Verbose Logs:") 55 | for message in logs 56 | { 57 | NSLog("\(message)") 58 | } 59 | NSLog("\n") 60 | } 61 | } 62 | } 63 | 64 | 65 | if let storyboard = result.0, 66 | let storyboardFileNameWithExtension = storyboardFilePath.lastPathComponent 67 | { 68 | let storyboardFileName = (storyboardFileNameWithExtension as NSString).stringByDeletingPathExtension 69 | 70 | if exportTogether == true 71 | { 72 | self.exportTogether(outputPath: outputPath, application: application, storyboard: storyboard, storyboardFileName: storyboardFileName, projectName: projectName) 73 | } else 74 | { 75 | self.exportSeperately(outputPath: outputPath, application: application, storyboard: storyboard, storyboardFileName: storyboardFileName, projectName : projectName) 76 | } 77 | self.exportSharedDefinitions(outputPath: outputPath, projectName: projectName) 78 | 79 | }else 80 | { 81 | NSLog("Unknown Error while parsing storyboard \(storyboardFilePathString)") 82 | } 83 | 84 | } catch let error as NSError 85 | { 86 | NSLog("Error while parsing storyboard \(storyboardFilePathString): \(error)") 87 | } 88 | } else 89 | { 90 | NSLog("Need to specify --storyboardFilePath with a valid Storyboard file, received \(storyboardFilePath)") 91 | } 92 | } 93 | 94 | internal class func fileStencilContext(outputPath outputPath : NSURL, fileName : String, projectName : String?) -> [String : AnyObject]? 95 | { 96 | let generatedOn = NSDate() 97 | let dateFormatter = NSDateFormatter() 98 | dateFormatter.dateFormat = "M/d/YY" 99 | _ = dateFormatter.stringFromDate(generatedOn) 100 | 101 | var result : [String : AnyObject] = [ 102 | DefaultTemplate.Keys.FileName : fileName 103 | // TODO: until we have MD5 checking on the remainder of the file contents we don't to cause unimportant file diffs 104 | /*, DefaultTemplate.Keys.GeneratedOn : generatedOnString*/ 105 | ] 106 | 107 | if let projectName = projectName 108 | { 109 | result[DefaultTemplate.Keys.ProjectName] = projectName 110 | } 111 | 112 | return result 113 | } 114 | 115 | internal class func exportSeperately(outputPath outputPath : NSURL, application : ApplicationInfo, storyboard : StoryboardInstanceInfo, storyboardFileName : String, projectName : String?) { 116 | 117 | for viewControllerClass in application.viewControllerClasses 118 | { 119 | var contextDictionary : [String : AnyObject] 120 | 121 | let fileName = viewControllerClass.separateFileName(storyboardFileName) + ".swift" 122 | 123 | if let fileStencilContext = self.fileStencilContext(outputPath: outputPath, fileName: fileName, projectName: projectName) 124 | { 125 | contextDictionary = fileStencilContext 126 | 127 | var viewControllers = [ [String : AnyObject] ]() 128 | if let viewControllerContext = viewControllerClass.stencilContext() 129 | { 130 | viewControllers.append(viewControllerContext) 131 | } 132 | 133 | if viewControllers.count > 0 134 | { 135 | contextDictionary[DefaultTemplate.Keys.ViewControllers] = viewControllers 136 | 137 | let stencilContext = Context(dictionary: contextDictionary) 138 | Template.write(templateString: DefaultTemplate.sourceFile, outputPath: outputPath, fileName: fileName, context: stencilContext) 139 | } else 140 | { 141 | // TODO: delete output file? output empty file? 142 | NSLog("No information to export for view controller class \(viewControllerClass.infoClassName)") 143 | } 144 | } 145 | } 146 | } 147 | 148 | internal class func exportTogether(outputPath outputPath : NSURL, application : ApplicationInfo, storyboard : StoryboardInstanceInfo, storyboardFileName : String, projectName : String?) { 149 | 150 | let fileName = storyboardFileName + ".swift" 151 | 152 | if let fileStencilContext = self.fileStencilContext(outputPath: outputPath, fileName: fileName, projectName: projectName) 153 | { 154 | var contextDictionary = fileStencilContext 155 | 156 | var viewControllers = [ [String : AnyObject] ]() 157 | for viewControllerClass in application.viewControllerClasses 158 | { 159 | if let viewControllerContext = viewControllerClass.stencilContext() 160 | { 161 | viewControllers.append(viewControllerContext) 162 | } 163 | } 164 | 165 | if viewControllers.count > 0 166 | { 167 | contextDictionary[DefaultTemplate.Keys.ViewControllers] = viewControllers 168 | 169 | let stencilContext = Context(dictionary: contextDictionary) 170 | Template.write(templateString: DefaultTemplate.sourceFile, outputPath: outputPath, fileName: fileName, context: stencilContext) 171 | } else 172 | { 173 | // TODO: delete output file? output empty file? 174 | NSLog("No information to export") 175 | } 176 | } 177 | } 178 | 179 | internal class func exportSharedDefinitions(outputPath outputPath : NSURL, projectName : String?) { 180 | var _ : [String : AnyObject] 181 | 182 | let fileName = "UIViewController+seguecode.swift" 183 | 184 | if let fileStencilContext = self.fileStencilContext(outputPath: outputPath, fileName: fileName, projectName: projectName) 185 | { 186 | let contextDictionary = fileStencilContext 187 | 188 | let stencilContext = Context(dictionary: contextDictionary) 189 | Template.write(templateString: DefaultTemplate.sharedFile, outputPath: outputPath, fileName: fileName, context: stencilContext) 190 | } 191 | } 192 | 193 | 194 | } -------------------------------------------------------------------------------- /seguecodePlugin/seguecodePlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // seguecodePlugin.m 3 | // seguecodePlugin 4 | // 5 | // Created by Ian on 11/4/14. 6 | // Copyright (c) 2014 Adorkable. All rights reserved. 7 | // 8 | 9 | #import "seguecodePlugin.h" 10 | 11 | #import "NSObject+Utility.h" 12 | #import "NSNotification+Utility.h" 13 | #import "NSURL+Utility.h" 14 | 15 | #import "NSMutableDictionary+RunConfig.h" 16 | 17 | static seguecodePlugin *sharedPlugin; 18 | 19 | @interface seguecodePlugin() 20 | 21 | @property (nonatomic, strong, readwrite) NSBundle *bundle; 22 | 23 | @property (copy) NSURL *currentlyEditingStoryboardFileName; 24 | 25 | @property (weak, readwrite) NSMenuItem *storyboardEnabled; 26 | 27 | @end 28 | 29 | @implementation seguecodePlugin 30 | 31 | + (void)pluginDidLoad:(NSBundle *)plugin 32 | { 33 | static dispatch_once_t onceToken; 34 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"]; 35 | if ([currentApplicationName isEqual:@"Xcode"]) { 36 | dispatch_once(&onceToken, ^{ 37 | sharedPlugin = [[self alloc] initWithBundle:plugin]; 38 | }); 39 | } 40 | } 41 | 42 | + (instancetype)sharedPlugin 43 | { 44 | return sharedPlugin; 45 | } 46 | 47 | - (id)initWithBundle:(NSBundle *)plugin 48 | { 49 | if (self = [super init] ) 50 | { 51 | self.bundle = plugin; 52 | 53 | if ( [self pathToSegueCode] ) 54 | { 55 | NSLog(@"seguecode found at %@", [self pathToSegueCode] ); 56 | 57 | [self setupNotifications]; 58 | 59 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 60 | [self setupMenu]; 61 | }]; 62 | } else 63 | { 64 | NSLog(@"seguecode not found!"); 65 | } 66 | } 67 | return self; 68 | } 69 | 70 | - (void)setupNotifications 71 | { 72 | [ [NSNotificationCenter defaultCenter] addObserver:self 73 | selector:@selector(transitionFromOneFileToAnother:) 74 | name:[NSNotification transitionFromOneFileToAnotherName] 75 | object:nil]; 76 | [ [NSNotificationCenter defaultCenter] addObserver:self 77 | selector:@selector(ideEditorDocumentDidSave:) 78 | name:[NSNotification ideEditorDocumentDidSaveName] 79 | object:nil]; 80 | /* 81 | [ [NSNotificationCenter defaultCenter] addObserver:self 82 | selector:@selector(logNotification:) 83 | name:nil 84 | object:nil]; 85 | */ 86 | } 87 | 88 | - (void)transitionFromOneFileToAnother:(NSNotification *)notification 89 | { 90 | if ( [notification isTransitionFromOneFileToAnother] ) 91 | { 92 | NSURL *nextURL = [notification transitionFromOneFileToAnotherNextDocumentURL]; 93 | NSRange begin = [nextURL rangeOfString:@"file://"]; 94 | 95 | if (begin.location != NSNotFound && begin.length > 0) 96 | { 97 | if ( [ [nextURL pathExtension] isEqualToString:@"storyboard"] ) 98 | { 99 | self.currentlyEditingStoryboardFileName = nextURL; 100 | } else 101 | { 102 | self.currentlyEditingStoryboardFileName = nil; 103 | NSLog(@"Ignoring %@", [nextURL pathExtension] ); 104 | } 105 | } else 106 | { 107 | NSLog(@"Unable to find file:// in %@", nextURL); 108 | self.currentlyEditingStoryboardFileName = nil; 109 | } 110 | 111 | [self updateStoryboardEnabled]; 112 | } else 113 | { 114 | NSLog(@"Unexpected notification %@ sent to %@", 115 | notification, 116 | NSStringFromSelector(@selector(transitionFromOneFileToAnother:) ) 117 | ); 118 | } 119 | } 120 | 121 | - (void)ideEditorDocumentDidSave:(NSNotification *)notification 122 | { 123 | if ( [notification isIDEEditorDocumentDidSave] ) 124 | { 125 | id notificationObject = [notification object]; 126 | 127 | Class IBStoryboardDocument = NSClassFromString(@"IBStoryboardDocument"); 128 | if ( [notificationObject isKindOfClass:IBStoryboardDocument] && self.currentlyEditingStoryboardFileName ) 129 | { 130 | NSMutableDictionary *runConfig = [NSMutableDictionary runConfigForStoryboardAtURL:self.currentlyEditingStoryboardFileName]; 131 | 132 | if (runConfig) 133 | { 134 | NSLog(@"Applying to %@", self.currentlyEditingStoryboardFileName); 135 | [self applyToStoryboardAtURL:self.currentlyEditingStoryboardFileName 136 | withRunConfig:runConfig]; 137 | } else 138 | { 139 | NSLog(@"Skipping %@, not configured for usage", self.currentlyEditingStoryboardFileName); 140 | } 141 | } 142 | } 143 | } 144 | 145 | -(void)logNotification:(NSNotification *)notification 146 | { 147 | if ( [notification isXcodeEvent] ) 148 | { 149 | NSLog(@"Notification: %@ %@", [notification name], [notification object]); 150 | } 151 | } 152 | 153 | - (BOOL)createDefaultRunConfigForStoryboardAtPath:(NSURL *)storyboardURL 154 | { 155 | NSMutableDictionary *result = [NSMutableDictionary dictionary]; 156 | result.combine = NO; 157 | result.outputPath = [NSString stringWithFormat:@"./Generated"]; 158 | return [result writeRunConfigForStoryboardAtURL:storyboardURL]; 159 | } 160 | 161 | - (BOOL)applyToStoryboardAtURL:(NSURL *)storyboardURL withRunConfig:(NSMutableDictionary *)runConfig 162 | { 163 | NSPipe *pipe = [NSPipe pipe]; 164 | 165 | NSTask *task = [[NSTask alloc] init]; 166 | task.launchPath = [ [self pathToSegueCode] path]; 167 | 168 | NSString *outputFolder = [NSString stringWithFormat:@"\"%@/%@\"", [ [storyboardURL URLByDeletingLastPathComponent] path], runConfig.outputPath]; 169 | 170 | NSMutableArray *arguments = [NSMutableArray array]; 171 | [arguments addObjectsFromArray:@[@"--outputPath", outputFolder] ]; 172 | if (runConfig.combine) 173 | { 174 | [arguments addObject:@"--combine"]; 175 | } 176 | if (runConfig.projectName) 177 | { 178 | [arguments addObjectsFromArray:@[@"--projectName", runConfig.projectName] ]; 179 | } 180 | [arguments addObject:[NSString stringWithFormat:@"\"%@\"", [storyboardURL path] ] ]; 181 | task.arguments = arguments; 182 | 183 | task.currentDirectoryPath = [ [storyboardURL URLByDeletingLastPathComponent] path]; 184 | task.standardOutput = pipe; 185 | [task launch]; 186 | [task waitUntilExit]; 187 | 188 | NSData *outputData = [ [pipe fileHandleForReading] availableData]; 189 | NSString *outputResult = [ [NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding]; 190 | if (outputResult.length > 0) 191 | { 192 | NSLog(@"seguecode result:\n%@", outputResult); 193 | } 194 | 195 | return task.terminationStatus != 0; 196 | } 197 | 198 | - (NSURL *)pathToSegueCode 199 | { 200 | return [self.bundle URLForResource:@"seguecode.bundle/Contents/MacOS/seguecode" 201 | withExtension:nil]; 202 | } 203 | 204 | - (NSMenuItem *)xcodeEditMenu 205 | { 206 | NSMenuItem *result = [ [NSApp mainMenu] itemWithTitle:@"Edit"]; 207 | if (result == nil) 208 | { 209 | NSLog(@"Unable to find Edit menu"); 210 | } 211 | return result; 212 | } 213 | 214 | - (void)setupMenu 215 | { 216 | NSMenuItem *editMenuItem = [self xcodeEditMenu]; 217 | if (editMenuItem) 218 | { 219 | [ [editMenuItem submenu] addItem:[NSMenuItem separatorItem] ]; 220 | 221 | NSMenuItem *storyboardEnabled = [ [NSMenuItem alloc] initWithTitle:@"Enable seguecode" 222 | action:@selector(toggleEnabled:) 223 | keyEquivalent:@""]; 224 | [storyboardEnabled setTarget:self]; 225 | [ [editMenuItem submenu] addItem:storyboardEnabled]; 226 | self.storyboardEnabled = storyboardEnabled; 227 | } else 228 | { 229 | NSLog(@"Cannot add seguecode menu items"); 230 | } 231 | } 232 | 233 | - (void)toggleEnabled:(id)sender 234 | { 235 | if (self.currentlyEditingStoryboardFileName) 236 | { 237 | if (![self enabledForStoryboardAtPath:self.currentlyEditingStoryboardFileName] ) 238 | { 239 | [self createDefaultRunConfigForStoryboardAtPath:self.currentlyEditingStoryboardFileName]; 240 | } else 241 | { 242 | [NSMutableDictionary removeRunConfigForStoryboardAtURL:self.currentlyEditingStoryboardFileName]; 243 | } 244 | [self updateStoryboardEnabled]; 245 | } 246 | } 247 | 248 | - (BOOL)enabledForStoryboardAtPath:(NSURL *)storyboardURL 249 | { 250 | // TODO: why aren't we using the passed in value? 251 | return self.currentlyEditingStoryboardFileName && [NSMutableDictionary runConfigForStoryboardAtURL:self.currentlyEditingStoryboardFileName]; 252 | } 253 | 254 | - (BOOL)validateMenuItem:(NSMenuItem *)menuItem 255 | { 256 | BOOL result = YES; 257 | if (menuItem == self.storyboardEnabled) 258 | { 259 | result = self.currentlyEditingStoryboardFileName != nil; 260 | } 261 | return result; 262 | } 263 | 264 | - (void)updateStoryboardEnabled 265 | { 266 | if (self.currentlyEditingStoryboardFileName) 267 | { 268 | [self.storyboardEnabled setEnabled:YES]; 269 | if ( [self enabledForStoryboardAtPath:self.currentlyEditingStoryboardFileName] ) 270 | { 271 | [self.storyboardEnabled setState:NSOnState]; 272 | } else 273 | { 274 | [self.storyboardEnabled setState:NSOffState]; 275 | } 276 | } else 277 | { 278 | [self.storyboardEnabled setEnabled:NO]; 279 | [self.storyboardEnabled setState:NSOffState]; 280 | } 281 | } 282 | 283 | 284 | 285 | - (void)dealloc 286 | { 287 | [ [NSNotificationCenter defaultCenter] removeObserver:self]; 288 | } 289 | 290 | @end 291 | -------------------------------------------------------------------------------- /seguecodeKit/StoryboardKit/ViewControllerClassInfo+seguecode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerClassInfo+seguecode.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/21/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import StoryboardKit 12 | 13 | import Stencil 14 | 15 | extension ViewControllerClassInfo 16 | { 17 | func separateFileName(category : String) -> String { 18 | return "\(self.infoClassName)+\(category)" 19 | } 20 | 21 | func stencilContext() -> [String : AnyObject]? { 22 | var result : [String : AnyObject]? 23 | 24 | var contextDictionary : [String : AnyObject] = [ 25 | DefaultTemplate.Keys.ViewController.Name : self.infoClassName 26 | ] 27 | 28 | let instances = self.instanceInfos 29 | if instances.count > 0 30 | { 31 | let storyboardInstances = NSMutableOrderedSet() 32 | let segueInstances = NSMutableOrderedSet() 33 | var tableViewCellPrototypes = Array() 34 | var collectionViewCellPrototypes = Array() 35 | for instance in instances 36 | { 37 | if let instance = instance.value 38 | { 39 | if let storyboardIdentifier = instance.storyboardIdentifier 40 | { 41 | if storyboardIdentifier.characters.count > 0 42 | { 43 | storyboardInstances.addObject(instance) 44 | } 45 | } 46 | 47 | for segue in instance.segues 48 | { 49 | segueInstances.addObject(segue) 50 | } 51 | 52 | if let view = instance.view 53 | { 54 | let newTableViewCellPrototypes = ViewControllerClassInfo.tableViewCellPrototypes(view) 55 | if newTableViewCellPrototypes.count > 0 56 | { 57 | tableViewCellPrototypes = tableViewCellPrototypes + newTableViewCellPrototypes 58 | } 59 | let newCollectionViewCellPrototypes = ViewControllerClassInfo.collectionViewCellPrototypes(view) 60 | if newCollectionViewCellPrototypes.count > 0 61 | { 62 | collectionViewCellPrototypes = collectionViewCellPrototypes + newCollectionViewCellPrototypes 63 | } 64 | } 65 | } 66 | } 67 | 68 | if storyboardInstances.count > 0 || segueInstances.count > 0 || tableViewCellPrototypes.count > 0 || collectionViewCellPrototypes.count > 0 69 | { 70 | ViewControllerClassInfo.addStoryboardInstanceInfoStencilContexts(&contextDictionary, storyboardInstances: storyboardInstances) 71 | 72 | ViewControllerClassInfo.addSegueInfoStencilContexts(&contextDictionary, segueInstances: segueInstances) 73 | ViewControllerClassInfo.addTableViewCellPrototypeStencilContexts(&contextDictionary, cellPrototypes: tableViewCellPrototypes) 74 | ViewControllerClassInfo.addCollectionViewCellPrototypeStencilContexts(&contextDictionary, cellPrototypes: collectionViewCellPrototypes) 75 | 76 | result = contextDictionary 77 | } 78 | } 79 | 80 | return result 81 | } 82 | 83 | class func addStoryboardInstanceInfoStencilContexts(inout contextDictionary : [String : AnyObject], storyboardInstances : NSOrderedSet) { 84 | let storyboardInstanceResults = self.storyboardInstanceInfoStencilContexts(storyboardInstances) 85 | if storyboardInstanceResults.count > 0 86 | { 87 | contextDictionary[DefaultTemplate.Keys.ViewController.StoryboardInstances] = storyboardInstanceResults 88 | } 89 | } 90 | 91 | class func storyboardInstanceInfoStencilContexts(storyboardInstances : NSOrderedSet) -> [ [String : String] ] { 92 | var result = [ [String : String] ]() 93 | 94 | for storyboardInstance in storyboardInstances 95 | { 96 | if let storyboardInstance = storyboardInstance as? ViewControllerInstanceInfo 97 | { 98 | if let storyboardInstanceStencilContext = storyboardInstance.storyboardInstanceStencilContext() 99 | { 100 | result.append(storyboardInstanceStencilContext) 101 | } 102 | } 103 | } 104 | 105 | return result 106 | } 107 | 108 | class func addSegueInfoStencilContexts(inout contextDictionary : [String : AnyObject], segueInstances : NSOrderedSet) { 109 | let segueResults = self.segueInfoStencilContexts(segueInstances) 110 | if segueResults.0.count > 0 111 | { 112 | contextDictionary[DefaultTemplate.Keys.ViewController.SegueCases] = segueResults.0 113 | } 114 | 115 | if segueResults.1.count > 0 116 | { 117 | contextDictionary[DefaultTemplate.Keys.ViewController.PerformFunctions] = segueResults.1 118 | } 119 | } 120 | 121 | // TODO: clarify segueCases and performFunctions in return results, right now interchangable 122 | class func segueInfoStencilContexts(segueInstances : NSOrderedSet) -> ([ [String : String] ], [ [String: String] ]) { 123 | var resultSegueCases = [ [String : String] ]() 124 | var resultPerformFunctions = [ [String : String] ]() 125 | 126 | for segueInstance in segueInstances 127 | { 128 | if let segueInstance = segueInstance as? SegueInstanceInfo 129 | { 130 | if let segueCaseStencilContext = segueInstance.segueCaseStencilContext() 131 | { 132 | resultSegueCases.append(segueCaseStencilContext) 133 | } 134 | 135 | if let peformFunctionStencilContext = segueInstance.peformFunctionStencilContext() 136 | { 137 | resultPerformFunctions.append(peformFunctionStencilContext) 138 | } 139 | } 140 | } 141 | 142 | return (resultSegueCases, resultPerformFunctions) 143 | } 144 | 145 | class func tableViewCellPrototypes(view : ViewInstanceInfo) -> [TableViewInstanceInfo.TableViewCellPrototypeInfo] { 146 | var result = Array() 147 | 148 | if let tableView = view as? TableViewInstanceInfo, 149 | let cellPrototypes = tableView.cellPrototypes 150 | { 151 | for cellPrototype in cellPrototypes 152 | { 153 | result.append(cellPrototype) 154 | } 155 | } 156 | 157 | if let subviews = view.subviews 158 | { 159 | for subview in subviews 160 | { 161 | let subviewResult = self.tableViewCellPrototypes(subview) 162 | if subviewResult.count > 0 163 | { 164 | result = result + subviewResult 165 | } 166 | } 167 | } 168 | 169 | return result 170 | } 171 | 172 | class func addTableViewCellPrototypeStencilContexts(inout contextDictionary : [String : AnyObject], cellPrototypes: [TableViewInstanceInfo.TableViewCellPrototypeInfo]) { 173 | let cellPrototypeResults = self.cellPrototypeStencilContexts(cellPrototypes) 174 | if cellPrototypeResults.0.count > 0 175 | { 176 | contextDictionary[DefaultTemplate.Keys.ViewController.TableViewCellPrototypes] = cellPrototypeResults.0 177 | } 178 | 179 | if cellPrototypeResults.1.count > 0 180 | { 181 | contextDictionary[DefaultTemplate.Keys.ViewController.DequeueTableViewCellFunctions] = cellPrototypeResults.1 182 | } 183 | } 184 | 185 | class func collectionViewCellPrototypes(view : ViewInstanceInfo) -> [CollectionViewInstanceInfo.CollectionViewCellPrototypeInfo] { 186 | var result = Array() 187 | 188 | if let collectionView = view as? CollectionViewInstanceInfo, 189 | let cellPrototypes = collectionView.cellPrototypes 190 | { 191 | for cellPrototype in cellPrototypes 192 | { 193 | result.append(cellPrototype) 194 | } 195 | } 196 | 197 | if let subviews = view.subviews 198 | { 199 | for subview in subviews 200 | { 201 | let subviewResult = self.collectionViewCellPrototypes(subview) 202 | if subviewResult.count > 0 203 | { 204 | result = result + subviewResult 205 | } 206 | } 207 | } 208 | 209 | return result 210 | } 211 | 212 | class func addCollectionViewCellPrototypeStencilContexts(inout contextDictionary : [String : AnyObject], cellPrototypes: [CollectionViewInstanceInfo.CollectionViewCellPrototypeInfo]) { 213 | let cellPrototypeResults = self.cellPrototypeStencilContexts(cellPrototypes) 214 | if cellPrototypeResults.0.count > 0 215 | { 216 | contextDictionary[DefaultTemplate.Keys.ViewController.CollectionViewCellPrototypes] = cellPrototypeResults.0 217 | } 218 | 219 | if cellPrototypeResults.1.count > 0 220 | { 221 | contextDictionary[DefaultTemplate.Keys.ViewController.DequeueCollectionViewCellFunctions] = cellPrototypeResults.1 222 | } 223 | } 224 | 225 | // TODO: clarify cellPrototypes and dequeueFunctions in return results, right now interchangable 226 | class func cellPrototypeStencilContexts(cellPrototypes : [TableViewInstanceInfo.TableViewCellPrototypeInfo]) -> ([ [String : String] ], [ [String: String] ]) { 227 | var resultCellPrototypes = [ [String : String] ]() 228 | var resultDequeueFunctions = [ [String : String] ]() 229 | 230 | for cellPrototype in cellPrototypes 231 | { 232 | if let cellPrototypeStencilContext = cellPrototype.cellPrototypeStencilContext() 233 | { 234 | resultCellPrototypes.append(cellPrototypeStencilContext) 235 | } 236 | 237 | if let dequeueFunctionStencilContext = cellPrototype.dequeueFunctionStencilContext() 238 | { 239 | resultDequeueFunctions.append(dequeueFunctionStencilContext) 240 | } 241 | } 242 | 243 | return (resultCellPrototypes, resultDequeueFunctions) 244 | } 245 | 246 | // TODO: clarify cellPrototypes and dequeueFunctions in return results, right now interchangable 247 | class func cellPrototypeStencilContexts(cellPrototypes : [CollectionViewInstanceInfo.CollectionViewCellPrototypeInfo]) -> ([ [String : String] ], [ [String: String] ]) { 248 | var resultCellPrototypes = [ [String : String] ]() 249 | var resultDequeueFunctions = [ [String : String] ]() 250 | 251 | for cellPrototype in cellPrototypes 252 | { 253 | if let cellPrototypeStencilContext = cellPrototype.cellPrototypeStencilContext() 254 | { 255 | resultCellPrototypes.append(cellPrototypeStencilContext) 256 | } 257 | 258 | if let dequeueFunctionStencilContext = cellPrototype.dequeueFunctionStencilContext() 259 | { 260 | resultDequeueFunctions.append(dequeueFunctionStencilContext) 261 | } 262 | } 263 | 264 | return (resultCellPrototypes, resultDequeueFunctions) 265 | } 266 | } -------------------------------------------------------------------------------- /seguecodeKit/DefaultTemplate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultTemplate.swift 3 | // seguecode 4 | // 5 | // Created by Ian Grossberg on 8/21/15. 6 | // Copyright (c) 2015 Adorkable. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import Stencil 12 | 13 | class DefaultTemplate: Template { 14 | struct Keys 15 | { 16 | static let FileName = "FileName" 17 | static let ProjectName = "ProjectName" 18 | 19 | static let GeneratedOn = "GeneratedOn" 20 | 21 | static let SharedDefinitions = "SharedDefinitions" 22 | 23 | static let ViewControllers = "ViewControllers" 24 | struct ViewController { 25 | static let Name = "ViewControllerName" 26 | 27 | static let StoryboardInstances = "StoryboardInstances" 28 | struct StoryboardInstance 29 | { 30 | static let Identifier = "Identifier" 31 | static let Value = "Value" 32 | } 33 | 34 | static let SegueCases = "SegueCases" 35 | struct SegueCase 36 | { 37 | static let Identifier = "Identifier" 38 | static let SourceIdentifier = "SourceIdentifier" 39 | static let DestinationIdentifier = "DestinationIdentifier" 40 | static let Value = "Value" 41 | } 42 | 43 | static let PerformFunctions = "PerformFunctions" 44 | struct PerformFunction 45 | { 46 | static let Identifier = "Identifier" 47 | static let SourceIdentifier = "SourceIdentifier" 48 | static let DestinationIdentifier = "DestinationIdentifier" 49 | } 50 | 51 | static let TableViewCellPrototypes = "TableViewCellPrototypes" 52 | struct TableViewCellPrototype 53 | { 54 | static let ReuseIdentifier = "ReuseIdentifier" 55 | } 56 | 57 | static let DequeueTableViewCellFunctions = "DequeueTableViewCellFunctions" 58 | struct DequeueTableViewCellFunction 59 | { 60 | static let ReuseIdentifier = "ReuseIdentifier" 61 | } 62 | 63 | static let CollectionViewCellPrototypes = "CollectionViewCellPrototypes" 64 | struct CollectionViewCellPrototype 65 | { 66 | static let ReuseIdentifier = "ReuseIdentifier" 67 | } 68 | 69 | static let DequeueCollectionViewCellFunctions = "DequeueCollectionViewCellFunctions" 70 | struct DequeueCollectionViewCellFunction 71 | { 72 | static let ReuseIdentifier = "ReuseIdentifier" 73 | } 74 | } 75 | } 76 | 77 | static var topFileComments : String { 78 | return "//\n" + 79 | "{% if \(Keys.FileName) %}" + 80 | "// {{ \(Keys.FileName) }}\n" + 81 | "{% endif %}" + 82 | 83 | "{% if \(Keys.ProjectName) %}" + 84 | "// {{ \(Keys.ProjectName) }}\n" + 85 | "{% endif %}" + 86 | 87 | "//\n" + 88 | "// Generated by seguecode [http://bit.ly/seguecode]" + 89 | "{% if \(Keys.GeneratedOn) %}" + 90 | " on {{ \(Keys.GeneratedOn) }}" + 91 | "{% endif %}" + 92 | "\n" + 93 | // TODO: copywrite and company info 94 | "//" 95 | } 96 | 97 | static var storyboardInstances : String { 98 | return "{% if viewController.\(Keys.ViewController.StoryboardInstances) %}" + 99 | 100 | "\n" + 101 | " struct StoryboardInstances {\n" + 102 | "{% for storyboardInstance in viewController.\(Keys.ViewController.StoryboardInstances) %}" + 103 | 104 | " static let {{ storyboardInstance.\(Keys.ViewController.StoryboardInstance.Identifier) }} = StoryboardInstance(identifier: \"{{ storyboardInstance.\(Keys.ViewController.StoryboardInstance.Value) }}\")\n" + 105 | 106 | "{% endfor %}" + 107 | " }\n" + 108 | 109 | "{% endif %}" 110 | } 111 | 112 | // TODO: no longer cases, rename 113 | static var segueCases : String { 114 | return "{% if viewController.\(Keys.ViewController.SegueCases) %}" + 115 | 116 | "\n" + 117 | " struct Segues {\n" + 118 | "{% for segueCase in viewController.\(Keys.ViewController.SegueCases) %}" + 119 | 120 | " static let {{ segueCase.\(Keys.ViewController.SegueCase.SourceIdentifier) }}{{ segueCase.\(Keys.ViewController.SegueCase.Identifier) }}{{ segueCase.\(Keys.ViewController.SegueCase.DestinationIdentifier) }} = Segue(identifier: \"{{ segueCase.\(Keys.ViewController.SegueCase.Value) }}\")\n" + 121 | 122 | "{% endfor %}" + 123 | " }\n" + 124 | 125 | "{% endif %}" 126 | } 127 | 128 | static var performFunctions : String { 129 | return "{% if viewController.\(Keys.ViewController.PerformFunctions) %}" + 130 | "{% for performFunction in viewController.\(Keys.ViewController.PerformFunctions) %}" + 131 | 132 | "\n" + 133 | " @IBAction func perform{{ performFunction.\(Keys.ViewController.PerformFunction.SourceIdentifier) }}{{ performFunction.\(Keys.ViewController.PerformFunction.Identifier) }}{{ performFunction.\(Keys.ViewController.PerformFunction.DestinationIdentifier) }}(sender : AnyObject? = nil) {\n" + 134 | " self.performSegue({{ viewController.\(Keys.ViewController.Name) }}.Segues.{{ performFunction.\(Keys.ViewController.PerformFunction.SourceIdentifier) }}{{ performFunction.\(Keys.ViewController.PerformFunction.Identifier) }}{{ performFunction.\(Keys.ViewController.PerformFunction.DestinationIdentifier) }}, sender: sender)\n" + 135 | " }\n" + 136 | 137 | "{% endfor %}" + 138 | "{% endif %}" 139 | } 140 | 141 | static var tableViewCellPrototypes : String { 142 | return "{% if viewController.\(Keys.ViewController.TableViewCellPrototypes) %}" + 143 | 144 | "\n" + 145 | " struct TableViewCellPrototypes {\n" + 146 | "{% for cellPrototype in viewController.\(Keys.ViewController.TableViewCellPrototypes) %}" + 147 | 148 | " static let {{ cellPrototype.\(Keys.ViewController.TableViewCellPrototype.ReuseIdentifier) }} = UITableView.TableViewCellPrototype(reuseIdentifier: \"{{ cellPrototype.\(Keys.ViewController.TableViewCellPrototype.ReuseIdentifier) }}\")\n" + 149 | 150 | "{% endfor %}" + 151 | " }\n" + 152 | 153 | "{% endif %}" 154 | } 155 | 156 | static var dequeueTableViewCellFunctions : String { 157 | return "{% if viewController.\(Keys.ViewController.DequeueTableViewCellFunctions) %}" + 158 | "{% for dequeueFunction in viewController.\(Keys.ViewController.DequeueTableViewCellFunctions) %}" + 159 | 160 | "\n" + 161 | " func dequeueReusable{{ dequeueFunction.\(Keys.ViewController.DequeueTableViewCellFunction.ReuseIdentifier) }}(tableView : UITableView) -> UITableViewCell? {\n" + 162 | 163 | " return tableView.dequeueReusableCell({{ viewController.\(Keys.ViewController.Name) }}.TableViewCellPrototypes.{{ dequeueFunction.\(Keys.ViewController.DequeueTableViewCellFunction.ReuseIdentifier) }})\n" + 164 | 165 | " }\n" + 166 | "\n" + 167 | 168 | " func dequeueReusable{{ dequeueFunction.\(Keys.ViewController.DequeueTableViewCellFunction.ReuseIdentifier) }}(tableView : UITableView, forIndexPath indexPath : NSIndexPath) -> UITableViewCell {\n" + 169 | 170 | " return tableView.dequeueReusableCell({{ viewController.\(Keys.ViewController.Name) }}.TableViewCellPrototypes.{{ dequeueFunction.\(Keys.ViewController.DequeueTableViewCellFunction.ReuseIdentifier) }}, forIndexPath : indexPath)\n" + 171 | 172 | " }\n" + 173 | 174 | "{% endfor %}" + 175 | "{% endif %}" 176 | } 177 | 178 | static var collectionViewCellPrototypes : String { 179 | return "{% if viewController.\(Keys.ViewController.CollectionViewCellPrototypes) %}" + 180 | 181 | "\n" + 182 | " struct CollectionViewCellPrototypes {\n" + 183 | "{% for cellPrototype in viewController.\(Keys.ViewController.CollectionViewCellPrototypes) %}" + 184 | 185 | " static let {{ cellPrototype.\(Keys.ViewController.CollectionViewCellPrototype.ReuseIdentifier) }} = UICollectionView.CollectionViewCellPrototype(reuseIdentifier: \"{{ cellPrototype.\(Keys.ViewController.CollectionViewCellPrototype.ReuseIdentifier) }}\")\n" + 186 | 187 | "{% endfor %}" + 188 | " }\n" + 189 | 190 | "{% endif %}" 191 | } 192 | 193 | static var dequeueCollectionViewCellFunctions : String { 194 | return "{% if viewController.\(Keys.ViewController.DequeueCollectionViewCellFunctions) %}" + 195 | "{% for dequeueFunction in viewController.\(Keys.ViewController.DequeueCollectionViewCellFunctions) %}" + 196 | 197 | "\n" + 198 | 199 | " func dequeueReusable{{ dequeueFunction.\(Keys.ViewController.DequeueCollectionViewCellFunction.ReuseIdentifier) }}(collectionView : UICollectionView, forIndexPath indexPath : NSIndexPath) -> UICollectionViewCell {\n" + 200 | 201 | " return collectionView.dequeueReusableCell({{ viewController.\(Keys.ViewController.Name) }}.CollectionViewCellPrototypes.{{ dequeueFunction.\(Keys.ViewController.DequeueCollectionViewCellFunction.ReuseIdentifier) }}, forIndexPath : indexPath)\n" + 202 | 203 | " }\n" + 204 | 205 | "{% endfor %}" + 206 | "{% endif %}" 207 | } 208 | 209 | static var sourceFile : String { 210 | return self.topFileComments + "\n" + 211 | "\n" + 212 | "import UIKit\n" + 213 | 214 | // As soon as you parse multiple Storyboards this will break your project, for now we're always going to export it separately 215 | // "{% if \(Keys.TogetherSharedDefinitions) %}" + 216 | // "\n" + 217 | // "{{ \(Keys.TogetherSharedDefinitions) }}" + 218 | // "{% endif %}" + 219 | 220 | "{% if \(Keys.ViewControllers) %}" + 221 | "{% for viewController in \(Keys.ViewControllers) %}" + 222 | 223 | "\n" + 224 | "extension {{ viewController.\(Keys.ViewController.Name) }} {\n" + 225 | self.storyboardInstances + 226 | self.segueCases + 227 | self.performFunctions + 228 | self.tableViewCellPrototypes + 229 | self.dequeueTableViewCellFunctions + 230 | self.collectionViewCellPrototypes + 231 | self.dequeueCollectionViewCellFunctions + 232 | "}\n" + 233 | 234 | "{% endfor %}" + 235 | "{% endif %}" 236 | } 237 | 238 | 239 | static var sharedDefinitions : String { 240 | return self.sharedUIViewControllerDefinitions + 241 | "\n" + 242 | self.sharedUIStoryboardDefinitions + 243 | "\n" + 244 | self.sharedUITableViewDefinitions + 245 | "\n" + 246 | self.sharedUICollectionViewDefinitions 247 | } 248 | 249 | static var sharedUIViewControllerDefinitions : String { 250 | return "extension UIViewController {\n" + 251 | 252 | " class Segue : NSObject\n" + 253 | " {\n" + 254 | " let identifier : String\n" + 255 | "\n" + 256 | " init(identifier : String) {\n" + 257 | " self.identifier = identifier\n" + 258 | " }\n" + 259 | " }\n" + 260 | "\n" + 261 | 262 | " func performSegue(segue : Segue, sender : AnyObject?) {\n" + // TODO: validate that we're calling from the correct instance of the VC class for classes in multiple instances in storyboards 263 | " self.performSegueWithIdentifier(segue.identifier, sender: sender)\n" + 264 | " }\n" + 265 | "\n" + 266 | 267 | " class StoryboardInstance : NSObject\n" + 268 | " {\n" + 269 | " let identifier : String\n" + 270 | "\n" + 271 | " init(identifier : String) {\n" + 272 | " self.identifier = identifier\n" + 273 | " }\n" + 274 | " }\n" + 275 | "}\n" 276 | } 277 | 278 | static var sharedUIStoryboardDefinitions : String { 279 | return "extension UIStoryboard {\n" + 280 | 281 | " func instantiateViewController(instance : UIViewController.StoryboardInstance) -> UIViewController {\n" + 282 | "\n" + 283 | " return self.instantiateViewControllerWithIdentifier(instance.identifier)\n" + 284 | " }\n" + 285 | "}\n" 286 | } 287 | 288 | static var sharedUITableViewDefinitions : String { 289 | return "extension UITableView {\n" + 290 | 291 | " class TableViewCellPrototype : NSObject\n" + 292 | " {\n" + 293 | " let reuseIdentifier : String\n" + 294 | "\n" + 295 | " init(reuseIdentifier : String) {\n" + 296 | " self.reuseIdentifier = reuseIdentifier\n" + 297 | " }\n" + 298 | " }\n" + 299 | "\n" + 300 | 301 | " func dequeueReusableCell(cellPrototype : TableViewCellPrototype) -> UITableViewCell? {\n" + 302 | " return self.dequeueReusableCellWithIdentifier(cellPrototype.reuseIdentifier)\n" + 303 | " }\n" + 304 | "\n" + 305 | 306 | " func dequeueReusableCell(cellPrototype : TableViewCellPrototype, forIndexPath indexPath : NSIndexPath) -> UITableViewCell {\n" + 307 | " return self.dequeueReusableCellWithIdentifier(cellPrototype.reuseIdentifier, forIndexPath: indexPath)\n" + 308 | " }\n" + 309 | 310 | "}\n" 311 | } 312 | 313 | static var sharedUICollectionViewDefinitions : String { 314 | return "extension UICollectionView {\n" + 315 | 316 | " class CollectionViewCellPrototype : NSObject\n" + 317 | " {\n" + 318 | " let reuseIdentifier : String\n" + 319 | "\n" + 320 | " init(reuseIdentifier : String) {\n" + 321 | " self.reuseIdentifier = reuseIdentifier\n" + 322 | " }\n" + 323 | " }\n" + 324 | "\n" + 325 | 326 | " func dequeueReusableCell(cellPrototype : CollectionViewCellPrototype, forIndexPath indexPath : NSIndexPath) -> UICollectionViewCell {\n" + 327 | " return self.dequeueReusableCellWithReuseIdentifier(cellPrototype.reuseIdentifier, forIndexPath: indexPath)\n" + 328 | " }\n" + 329 | 330 | "}\n" 331 | } 332 | 333 | static var sharedFile : String { 334 | return self.topFileComments + "\n" + 335 | "\n" + 336 | "import UIKit\n" + 337 | "\n" + 338 | self.sharedDefinitions 339 | } 340 | 341 | required init() { 342 | super.init(templateString: DefaultTemplate.sourceFile) 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /seguecodePlugin.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3C4B54131A0EE7FE0041E9D0 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B54121A0EE7FE0041E9D0 /* AppKit.framework */; }; 11 | 3C4B54151A0EE7FE0041E9D0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B54141A0EE7FE0041E9D0 /* Foundation.framework */; }; 12 | 3C4B541D1A0EE7FE0041E9D0 /* seguecodePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B541C1A0EE7FE0041E9D0 /* seguecodePlugin.m */; }; 13 | 3C4B54261A0EE8270041E9D0 /* NSNotification+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B54231A0EE8270041E9D0 /* NSNotification+Utility.m */; }; 14 | 3C4B54271A0EE8270041E9D0 /* NSObject+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B54251A0EE8270041E9D0 /* NSObject+Utility.m */; }; 15 | 3C4B54411A0EE8740041E9D0 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B54121A0EE7FE0041E9D0 /* AppKit.framework */; }; 16 | 3C4B54421A0EE8740041E9D0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B54141A0EE7FE0041E9D0 /* Foundation.framework */; }; 17 | 3C4B54611A0EEAC10041E9D0 /* NSNotification+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B54231A0EE8270041E9D0 /* NSNotification+Utility.m */; }; 18 | 3C4B54631A0EEAC10041E9D0 /* NSObject+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B54251A0EE8270041E9D0 /* NSObject+Utility.m */; }; 19 | 3C4B54651A0EEAC10041E9D0 /* seguecodePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4B541C1A0EE7FE0041E9D0 /* seguecodePlugin.m */; }; 20 | 3C6608661B8B6FB000F86FFD /* seguecode.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3CAA72131B8A064F0028683D /* seguecode.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 21 | 3CAA721A1B8A07490028683D /* NSMutableDictionary+RunConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA72191B8A07490028683D /* NSMutableDictionary+RunConfig.m */; }; 22 | 3CAA721F1B8A0B600028683D /* seguecode.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3CAA72131B8A064F0028683D /* seguecode.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 23 | 3CF4E5761BFB828600D00C91 /* NSURL+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CF4E5751BFB828600D00C91 /* NSURL+Utility.m */; }; 24 | 3CF4E5771BFB828600D00C91 /* NSURL+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CF4E5751BFB828600D00C91 /* NSURL+Utility.m */; }; 25 | 3CFE5E331B8B68A800A4146D /* NSMutableDictionary+RunConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CAA72191B8A07490028683D /* NSMutableDictionary+RunConfig.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 3C4B54571A0EEA910041E9D0 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 32 | proxyType = 2; 33 | remoteGlobalIDString = 3CE464411856B24A002F423D; 34 | remoteInfo = seguecode; 35 | }; 36 | 3CAA720D1B8A064F0028683D /* PBXContainerItemProxy */ = { 37 | isa = PBXContainerItemProxy; 38 | containerPortal = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 39 | proxyType = 1; 40 | remoteGlobalIDString = 3C1CE0871B8857B800DA379A; 41 | remoteInfo = seguecodeBundle; 42 | }; 43 | 3CAA72121B8A064F0028683D /* PBXContainerItemProxy */ = { 44 | isa = PBXContainerItemProxy; 45 | containerPortal = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 46 | proxyType = 2; 47 | remoteGlobalIDString = 3C1CE0881B8857B800DA379A; 48 | remoteInfo = seguecodeBundle; 49 | }; 50 | 3CAA72141B8A064F0028683D /* PBXContainerItemProxy */ = { 51 | isa = PBXContainerItemProxy; 52 | containerPortal = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 53 | proxyType = 2; 54 | remoteGlobalIDString = 3C1CE0A51B88598600DA379A; 55 | remoteInfo = seguecodeKit; 56 | }; 57 | 3CAA72161B8A064F0028683D /* PBXContainerItemProxy */ = { 58 | isa = PBXContainerItemProxy; 59 | containerPortal = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 60 | proxyType = 2; 61 | remoteGlobalIDString = 3C1380021AF73FA800E417B2; 62 | remoteInfo = iOSExample; 63 | }; 64 | /* End PBXContainerItemProxy section */ 65 | 66 | /* Begin PBXCopyFilesBuildPhase section */ 67 | 3C6608651B8B6F9F00F86FFD /* CopyFiles */ = { 68 | isa = PBXCopyFilesBuildPhase; 69 | buildActionMask = 2147483647; 70 | dstPath = ""; 71 | dstSubfolderSpec = 7; 72 | files = ( 73 | 3C6608661B8B6FB000F86FFD /* seguecode.bundle in CopyFiles */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 3CAA721E1B8A0B470028683D /* CopyFiles */ = { 78 | isa = PBXCopyFilesBuildPhase; 79 | buildActionMask = 2147483647; 80 | dstPath = ""; 81 | dstSubfolderSpec = 7; 82 | files = ( 83 | 3CAA721F1B8A0B600028683D /* seguecode.bundle in CopyFiles */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXCopyFilesBuildPhase section */ 88 | 89 | /* Begin PBXFileReference section */ 90 | 3C4B54101A0EE7FE0041E9D0 /* seguecodePlugin.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = seguecodePlugin.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | 3C4B54121A0EE7FE0041E9D0 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 92 | 3C4B54141A0EE7FE0041E9D0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 93 | 3C4B54181A0EE7FE0041E9D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94 | 3C4B54191A0EE7FE0041E9D0 /* seguecodePlugin.xcscheme */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = seguecodePlugin.xcscheme; path = seguecodePlugin.xcodeproj/xcshareddata/xcschemes/seguecodePlugin.xcscheme; sourceTree = SOURCE_ROOT; }; 95 | 3C4B541B1A0EE7FE0041E9D0 /* seguecodePlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = seguecodePlugin.h; sourceTree = ""; }; 96 | 3C4B541C1A0EE7FE0041E9D0 /* seguecodePlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = seguecodePlugin.m; sourceTree = ""; }; 97 | 3C4B54221A0EE8270041E9D0 /* NSNotification+Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotification+Utility.h"; sourceTree = ""; }; 98 | 3C4B54231A0EE8270041E9D0 /* NSNotification+Utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotification+Utility.m"; sourceTree = ""; }; 99 | 3C4B54241A0EE8270041E9D0 /* NSObject+Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Utility.h"; sourceTree = ""; }; 100 | 3C4B54251A0EE8270041E9D0 /* NSObject+Utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Utility.m"; sourceTree = ""; }; 101 | 3C4B544E1A0EE8A90041E9D0 /* seguecodePlugin.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = seguecodePlugin.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 102 | 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = seguecode.xcodeproj; sourceTree = ""; }; 103 | 3CAA72181B8A07490028683D /* NSMutableDictionary+RunConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+RunConfig.h"; sourceTree = ""; }; 104 | 3CAA72191B8A07490028683D /* NSMutableDictionary+RunConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+RunConfig.m"; sourceTree = ""; }; 105 | 3CF4E5711BFB826F00D00C91 /* NSURL+Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+Utility.h"; sourceTree = ""; }; 106 | 3CF4E5751BFB828600D00C91 /* NSURL+Utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+Utility.m"; sourceTree = ""; }; 107 | /* End PBXFileReference section */ 108 | 109 | /* Begin PBXFrameworksBuildPhase section */ 110 | 3C4B540E1A0EE7FE0041E9D0 /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | 3C4B54131A0EE7FE0041E9D0 /* AppKit.framework in Frameworks */, 115 | 3C4B54151A0EE7FE0041E9D0 /* Foundation.framework in Frameworks */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | 3C4B543E1A0EE8740041E9D0 /* Frameworks */ = { 120 | isa = PBXFrameworksBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | 3C4B54411A0EE8740041E9D0 /* AppKit.framework in Frameworks */, 124 | 3C4B54421A0EE8740041E9D0 /* Foundation.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | /* End PBXFrameworksBuildPhase section */ 129 | 130 | /* Begin PBXGroup section */ 131 | 3C4B54111A0EE7FE0041E9D0 /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 3C4B54121A0EE7FE0041E9D0 /* AppKit.framework */, 135 | 3C4B54141A0EE7FE0041E9D0 /* Foundation.framework */, 136 | ); 137 | name = Frameworks; 138 | sourceTree = ""; 139 | }; 140 | 3C4B54161A0EE7FE0041E9D0 /* seguecodePlugin */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 3C4B54211A0EE8270041E9D0 /* Utility */, 144 | 3C4B541B1A0EE7FE0041E9D0 /* seguecodePlugin.h */, 145 | 3C4B541C1A0EE7FE0041E9D0 /* seguecodePlugin.m */, 146 | 3C4B54171A0EE7FE0041E9D0 /* Supporting Files */, 147 | ); 148 | path = seguecodePlugin; 149 | sourceTree = ""; 150 | }; 151 | 3C4B54171A0EE7FE0041E9D0 /* Supporting Files */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 3C4B54181A0EE7FE0041E9D0 /* Info.plist */, 155 | 3C4B54191A0EE7FE0041E9D0 /* seguecodePlugin.xcscheme */, 156 | ); 157 | name = "Supporting Files"; 158 | sourceTree = ""; 159 | }; 160 | 3C4B54211A0EE8270041E9D0 /* Utility */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 3CAA72181B8A07490028683D /* NSMutableDictionary+RunConfig.h */, 164 | 3CAA72191B8A07490028683D /* NSMutableDictionary+RunConfig.m */, 165 | 3C4B54221A0EE8270041E9D0 /* NSNotification+Utility.h */, 166 | 3C4B54231A0EE8270041E9D0 /* NSNotification+Utility.m */, 167 | 3C4B54241A0EE8270041E9D0 /* NSObject+Utility.h */, 168 | 3C4B54251A0EE8270041E9D0 /* NSObject+Utility.m */, 169 | 3CF4E5711BFB826F00D00C91 /* NSURL+Utility.h */, 170 | 3CF4E5751BFB828600D00C91 /* NSURL+Utility.m */, 171 | ); 172 | path = Utility; 173 | sourceTree = ""; 174 | }; 175 | 3C4B54521A0EEA910041E9D0 /* Products */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | 3C4B54581A0EEA910041E9D0 /* seguecode */, 179 | 3CAA72131B8A064F0028683D /* seguecode.bundle */, 180 | 3CAA72151B8A064F0028683D /* seguecodeKit.framework */, 181 | 3CAA72171B8A064F0028683D /* iOSExample.app */, 182 | ); 183 | name = Products; 184 | sourceTree = ""; 185 | }; 186 | 3CB24CCC1A0AD53200006169 = { 187 | isa = PBXGroup; 188 | children = ( 189 | 3C4B54101A0EE7FE0041E9D0 /* seguecodePlugin.xcplugin */, 190 | 3C4B54161A0EE7FE0041E9D0 /* seguecodePlugin */, 191 | 3C4B54111A0EE7FE0041E9D0 /* Frameworks */, 192 | 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */, 193 | 3C4B544E1A0EE8A90041E9D0 /* seguecodePlugin.xcplugin */, 194 | ); 195 | sourceTree = ""; 196 | }; 197 | /* End PBXGroup section */ 198 | 199 | /* Begin PBXNativeTarget section */ 200 | 3C4B540F1A0EE7FE0041E9D0 /* seguecodePlugin */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = 3C4B541E1A0EE7FE0041E9D0 /* Build configuration list for PBXNativeTarget "seguecodePlugin" */; 203 | buildPhases = ( 204 | 3C4B544F1A0EE8CD0041E9D0 /* Get Latest seguecodeBundle */, 205 | 3C4B540C1A0EE7FE0041E9D0 /* Sources */, 206 | 3C6608651B8B6F9F00F86FFD /* CopyFiles */, 207 | 3C4B540E1A0EE7FE0041E9D0 /* Frameworks */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | ); 213 | name = seguecodePlugin; 214 | productName = seguecodePlugin; 215 | productReference = 3C4B54101A0EE7FE0041E9D0 /* seguecodePlugin.xcplugin */; 216 | productType = "com.apple.product-type.bundle"; 217 | }; 218 | 3C4B543F1A0EE8740041E9D0 /* seguecodePluginLocal */ = { 219 | isa = PBXNativeTarget; 220 | buildConfigurationList = 3C4B544B1A0EE8740041E9D0 /* Build configuration list for PBXNativeTarget "seguecodePluginLocal" */; 221 | buildPhases = ( 222 | 3C4B543C1A0EE8740041E9D0 /* Sources */, 223 | 3CAA721E1B8A0B470028683D /* CopyFiles */, 224 | 3C4B543E1A0EE8740041E9D0 /* Frameworks */, 225 | ); 226 | buildRules = ( 227 | ); 228 | dependencies = ( 229 | 3CAA720E1B8A064F0028683D /* PBXTargetDependency */, 230 | ); 231 | name = seguecodePluginLocal; 232 | productName = seguecodePluginLocal; 233 | productReference = 3C4B544E1A0EE8A90041E9D0 /* seguecodePlugin.xcplugin */; 234 | productType = "com.apple.product-type.bundle"; 235 | }; 236 | /* End PBXNativeTarget section */ 237 | 238 | /* Begin PBXProject section */ 239 | 3CB24CCD1A0AD53200006169 /* Project object */ = { 240 | isa = PBXProject; 241 | attributes = { 242 | LastSwiftMigration = 0700; 243 | LastUpgradeCheck = 0700; 244 | ORGANIZATIONNAME = Adorkable; 245 | TargetAttributes = { 246 | 3C4B540F1A0EE7FE0041E9D0 = { 247 | CreatedOnToolsVersion = 6.1; 248 | }; 249 | 3C4B543F1A0EE8740041E9D0 = { 250 | CreatedOnToolsVersion = 6.1; 251 | }; 252 | }; 253 | }; 254 | buildConfigurationList = 3CB24CD01A0AD53200006169 /* Build configuration list for PBXProject "seguecodePlugin" */; 255 | compatibilityVersion = "Xcode 3.2"; 256 | developmentRegion = English; 257 | hasScannedForEncodings = 0; 258 | knownRegions = ( 259 | en, 260 | ); 261 | mainGroup = 3CB24CCC1A0AD53200006169; 262 | productRefGroup = 3CB24CCC1A0AD53200006169; 263 | projectDirPath = ""; 264 | projectReferences = ( 265 | { 266 | ProductGroup = 3C4B54521A0EEA910041E9D0 /* Products */; 267 | ProjectRef = 3C4B54511A0EEA910041E9D0 /* seguecode.xcodeproj */; 268 | }, 269 | ); 270 | projectRoot = ""; 271 | targets = ( 272 | 3C4B540F1A0EE7FE0041E9D0 /* seguecodePlugin */, 273 | 3C4B543F1A0EE8740041E9D0 /* seguecodePluginLocal */, 274 | ); 275 | }; 276 | /* End PBXProject section */ 277 | 278 | /* Begin PBXReferenceProxy section */ 279 | 3C4B54581A0EEA910041E9D0 /* seguecode */ = { 280 | isa = PBXReferenceProxy; 281 | fileType = "compiled.mach-o.executable"; 282 | path = seguecode; 283 | remoteRef = 3C4B54571A0EEA910041E9D0 /* PBXContainerItemProxy */; 284 | sourceTree = BUILT_PRODUCTS_DIR; 285 | }; 286 | 3CAA72131B8A064F0028683D /* seguecode.bundle */ = { 287 | isa = PBXReferenceProxy; 288 | fileType = wrapper.cfbundle; 289 | path = seguecode.bundle; 290 | remoteRef = 3CAA72121B8A064F0028683D /* PBXContainerItemProxy */; 291 | sourceTree = BUILT_PRODUCTS_DIR; 292 | }; 293 | 3CAA72151B8A064F0028683D /* seguecodeKit.framework */ = { 294 | isa = PBXReferenceProxy; 295 | fileType = wrapper.framework; 296 | path = seguecodeKit.framework; 297 | remoteRef = 3CAA72141B8A064F0028683D /* PBXContainerItemProxy */; 298 | sourceTree = BUILT_PRODUCTS_DIR; 299 | }; 300 | 3CAA72171B8A064F0028683D /* iOSExample.app */ = { 301 | isa = PBXReferenceProxy; 302 | fileType = wrapper.application; 303 | path = iOSExample.app; 304 | remoteRef = 3CAA72161B8A064F0028683D /* PBXContainerItemProxy */; 305 | sourceTree = BUILT_PRODUCTS_DIR; 306 | }; 307 | /* End PBXReferenceProxy section */ 308 | 309 | /* Begin PBXShellScriptBuildPhase section */ 310 | 3C4B544F1A0EE8CD0041E9D0 /* Get Latest seguecodeBundle */ = { 311 | isa = PBXShellScriptBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | ); 315 | inputPaths = ( 316 | ); 317 | name = "Get Latest seguecodeBundle"; 318 | outputPaths = ( 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | shellPath = /bin/sh; 322 | shellScript = "VERSION_NUMBER=$(/usr/libexec/PlistBuddy -c \"Print CFBundleShortVersionString\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\")\n\necho \"Retrieving seguecodeBundle for version ${VERSION_NUMBER}\"\n\ncd \"${BUILT_PRODUCTS_DIR}\"\nrm -f -r -d seguecode.bundle.zip\ncurl -O -L https://github.com/Adorkable/seguecode/releases/download/$VERSION_NUMBER/seguecode.bundle.zip\nrm -f -r -d seguecode.bundle\nunzip seguecode.bundle"; 323 | }; 324 | /* End PBXShellScriptBuildPhase section */ 325 | 326 | /* Begin PBXSourcesBuildPhase section */ 327 | 3C4B540C1A0EE7FE0041E9D0 /* Sources */ = { 328 | isa = PBXSourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | 3C4B54261A0EE8270041E9D0 /* NSNotification+Utility.m in Sources */, 332 | 3CF4E5761BFB828600D00C91 /* NSURL+Utility.m in Sources */, 333 | 3CAA721A1B8A07490028683D /* NSMutableDictionary+RunConfig.m in Sources */, 334 | 3C4B54271A0EE8270041E9D0 /* NSObject+Utility.m in Sources */, 335 | 3C4B541D1A0EE7FE0041E9D0 /* seguecodePlugin.m in Sources */, 336 | ); 337 | runOnlyForDeploymentPostprocessing = 0; 338 | }; 339 | 3C4B543C1A0EE8740041E9D0 /* Sources */ = { 340 | isa = PBXSourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | 3C4B54611A0EEAC10041E9D0 /* NSNotification+Utility.m in Sources */, 344 | 3CF4E5771BFB828600D00C91 /* NSURL+Utility.m in Sources */, 345 | 3CFE5E331B8B68A800A4146D /* NSMutableDictionary+RunConfig.m in Sources */, 346 | 3C4B54631A0EEAC10041E9D0 /* NSObject+Utility.m in Sources */, 347 | 3C4B54651A0EEAC10041E9D0 /* seguecodePlugin.m in Sources */, 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | }; 351 | /* End PBXSourcesBuildPhase section */ 352 | 353 | /* Begin PBXTargetDependency section */ 354 | 3CAA720E1B8A064F0028683D /* PBXTargetDependency */ = { 355 | isa = PBXTargetDependency; 356 | name = seguecodeBundle; 357 | targetProxy = 3CAA720D1B8A064F0028683D /* PBXContainerItemProxy */; 358 | }; 359 | /* End PBXTargetDependency section */ 360 | 361 | /* Begin XCBuildConfiguration section */ 362 | 3C4B541F1A0EE7FE0041E9D0 /* Debug */ = { 363 | isa = XCBuildConfiguration; 364 | buildSettings = { 365 | COMBINE_HIDPI_IMAGES = YES; 366 | DEPLOYMENT_LOCATION = YES; 367 | DSTROOT = "$(HOME)"; 368 | GCC_PREPROCESSOR_DEFINITIONS = ( 369 | "DEBUG=1", 370 | "$(inherited)", 371 | ); 372 | INFOPLIST_FILE = seguecodePlugin/Info.plist; 373 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 374 | MACOSX_DEPLOYMENT_TARGET = 10.10; 375 | PRODUCT_BUNDLE_IDENTIFIER = "cc.adorkable.$(PRODUCT_NAME:rfc1034identifier)"; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | WRAPPER_EXTENSION = xcplugin; 378 | }; 379 | name = Debug; 380 | }; 381 | 3C4B54201A0EE7FE0041E9D0 /* Release */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | COMBINE_HIDPI_IMAGES = YES; 385 | DEPLOYMENT_LOCATION = YES; 386 | DSTROOT = "$(HOME)"; 387 | INFOPLIST_FILE = seguecodePlugin/Info.plist; 388 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 389 | MACOSX_DEPLOYMENT_TARGET = 10.10; 390 | PRODUCT_BUNDLE_IDENTIFIER = "cc.adorkable.$(PRODUCT_NAME:rfc1034identifier)"; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | WRAPPER_EXTENSION = xcplugin; 393 | }; 394 | name = Release; 395 | }; 396 | 3C4B544C1A0EE8740041E9D0 /* Debug */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | COMBINE_HIDPI_IMAGES = YES; 400 | DEPLOYMENT_LOCATION = YES; 401 | DSTROOT = "$(HOME)"; 402 | GCC_PREPROCESSOR_DEFINITIONS = ( 403 | "DEBUG=1", 404 | "$(inherited)", 405 | ); 406 | INFOPLIST_FILE = seguecodePlugin/Info.plist; 407 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 408 | MACOSX_DEPLOYMENT_TARGET = 10.10; 409 | PRODUCT_BUNDLE_IDENTIFIER = "cc.adorkable.$(PRODUCT_NAME:rfc1034identifier)"; 410 | PRODUCT_NAME = seguecodePlugin; 411 | WRAPPER_EXTENSION = xcplugin; 412 | }; 413 | name = Debug; 414 | }; 415 | 3C4B544D1A0EE8740041E9D0 /* Release */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | COMBINE_HIDPI_IMAGES = YES; 419 | DEPLOYMENT_LOCATION = YES; 420 | DSTROOT = "$(HOME)"; 421 | INFOPLIST_FILE = seguecodePlugin/Info.plist; 422 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 423 | MACOSX_DEPLOYMENT_TARGET = 10.10; 424 | PRODUCT_BUNDLE_IDENTIFIER = "cc.adorkable.$(PRODUCT_NAME:rfc1034identifier)"; 425 | PRODUCT_NAME = seguecodePlugin; 426 | WRAPPER_EXTENSION = xcplugin; 427 | }; 428 | name = Release; 429 | }; 430 | 3CB24CE41A0AD53200006169 /* Debug */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ALWAYS_SEARCH_USER_PATHS = NO; 434 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 435 | CLANG_CXX_LIBRARY = "libc++"; 436 | CLANG_ENABLE_MODULES = YES; 437 | CLANG_ENABLE_OBJC_ARC = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_CONSTANT_CONVERSION = YES; 440 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 441 | CLANG_WARN_EMPTY_BODY = YES; 442 | CLANG_WARN_ENUM_CONVERSION = YES; 443 | CLANG_WARN_INT_CONVERSION = YES; 444 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 445 | CLANG_WARN_UNREACHABLE_CODE = YES; 446 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 447 | COPY_PHASE_STRIP = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | ENABLE_TESTABILITY = YES; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_DYNAMIC_NO_PIC = NO; 452 | GCC_OPTIMIZATION_LEVEL = 0; 453 | GCC_PREPROCESSOR_DEFINITIONS = ( 454 | "DEBUG=1", 455 | "$(inherited)", 456 | ); 457 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 458 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 459 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 460 | GCC_WARN_UNDECLARED_SELECTOR = YES; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 462 | GCC_WARN_UNUSED_FUNCTION = YES; 463 | GCC_WARN_UNUSED_VARIABLE = YES; 464 | MTL_ENABLE_DEBUG_INFO = YES; 465 | ONLY_ACTIVE_ARCH = YES; 466 | }; 467 | name = Debug; 468 | }; 469 | 3CB24CE51A0AD53200006169 /* Release */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_SEARCH_USER_PATHS = NO; 473 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 474 | CLANG_CXX_LIBRARY = "libc++"; 475 | CLANG_ENABLE_MODULES = YES; 476 | CLANG_ENABLE_OBJC_ARC = YES; 477 | CLANG_WARN_BOOL_CONVERSION = YES; 478 | CLANG_WARN_CONSTANT_CONVERSION = YES; 479 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 480 | CLANG_WARN_EMPTY_BODY = YES; 481 | CLANG_WARN_ENUM_CONVERSION = YES; 482 | CLANG_WARN_INT_CONVERSION = YES; 483 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 484 | CLANG_WARN_UNREACHABLE_CODE = YES; 485 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 486 | COPY_PHASE_STRIP = YES; 487 | ENABLE_NS_ASSERTIONS = NO; 488 | ENABLE_STRICT_OBJC_MSGSEND = YES; 489 | GCC_C_LANGUAGE_STANDARD = gnu99; 490 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 491 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 492 | GCC_WARN_UNDECLARED_SELECTOR = YES; 493 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 494 | GCC_WARN_UNUSED_FUNCTION = YES; 495 | GCC_WARN_UNUSED_VARIABLE = YES; 496 | MTL_ENABLE_DEBUG_INFO = NO; 497 | }; 498 | name = Release; 499 | }; 500 | /* End XCBuildConfiguration section */ 501 | 502 | /* Begin XCConfigurationList section */ 503 | 3C4B541E1A0EE7FE0041E9D0 /* Build configuration list for PBXNativeTarget "seguecodePlugin" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | 3C4B541F1A0EE7FE0041E9D0 /* Debug */, 507 | 3C4B54201A0EE7FE0041E9D0 /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | 3C4B544B1A0EE8740041E9D0 /* Build configuration list for PBXNativeTarget "seguecodePluginLocal" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | 3C4B544C1A0EE8740041E9D0 /* Debug */, 516 | 3C4B544D1A0EE8740041E9D0 /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | defaultConfigurationName = Release; 520 | }; 521 | 3CB24CD01A0AD53200006169 /* Build configuration list for PBXProject "seguecodePlugin" */ = { 522 | isa = XCConfigurationList; 523 | buildConfigurations = ( 524 | 3CB24CE41A0AD53200006169 /* Debug */, 525 | 3CB24CE51A0AD53200006169 /* Release */, 526 | ); 527 | defaultConfigurationIsVisible = 0; 528 | defaultConfigurationName = Release; 529 | }; 530 | /* End XCConfigurationList section */ 531 | }; 532 | rootObject = 3CB24CCD1A0AD53200006169 /* Project object */; 533 | } 534 | -------------------------------------------------------------------------------- /Example/iOS/Base.lproj/Main_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 34 | 48 | 62 | 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 | 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 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 170 | 184 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 261 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | --------------------------------------------------------------------------------