Skip to content

Commit e4c7234

Browse files
committed
Merge branch 'develop'
2 parents 7c3868f + ea48b1a commit e4c7234

File tree

4 files changed

+100
-61
lines changed

4 files changed

+100
-61
lines changed

R.swift/func.swift

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func failOnError(error: NSError?) {
2828
}
2929

3030
func inputDirectories(processInfo: NSProcessInfo) -> [NSURL] {
31-
return processInfo.arguments.skip(1).map { NSURL(fileURLWithPath: $0 as String)! }
31+
return processInfo.arguments.skip(1).map { NSURL(fileURLWithPath: $0 as! String)! }
3232
}
3333

3434
func filterDirectoryContentsRecursively(fileManager: NSFileManager, filter: (NSURL) -> Bool)(url: NSURL) -> [NSURL] {
@@ -110,18 +110,31 @@ func storyboardStructFromStoryboards(storyboards: [Storyboard]) -> Struct {
110110
func storyboardStructForStoryboard(storyboard: Storyboard) -> Struct {
111111
let instanceVars = [Var(name: "instance", type: Type._UIStoryboard, getter: "return UIStoryboard(name: \"\(storyboard.name)\", bundle: nil)")]
112112

113-
let viewControllerVars = storyboard.viewControllers
114-
.map { Var(name: $0.storyboardIdentifier, type: $0.type.asOptional(), getter: "return instance.instantiateViewControllerWithIdentifier(\"\($0.storyboardIdentifier)\") as? \($0.type.asNonOptional())") }
113+
114+
let initialViewControllerVar = catOptionals([storyboard.initialViewController.map {
115+
Var(name: "initialViewController", type: $0.type.asOptional(), getter: "return instance.instantiateInitialViewController() as? \($0.type.asNonOptional())")
116+
}])
117+
118+
let viewControllerVars = catOptionals(storyboard.viewControllers
119+
.map { vc in
120+
vc.storyboardIdentifier.map {
121+
return Var(name: $0, type: vc.type.asOptional(), getter: "return instance.instantiateViewControllerWithIdentifier(\"\($0)\") as? \(vc.type.asNonOptional())")
122+
}
123+
})
115124

116125
let validateImagesLines = distinct(storyboard.usedImageIdentifiers)
117126
.map { "assert(UIImage(named: \"\($0)\") != nil, \"[R.swift] Image named '\($0)' is used in storyboard '\(storyboard.name)', but couldn't be loaded.\")" }
118127
let validateImagesFunc = Function(name: "validateImages", parameters: [], returnType: Type._Void, body: join("\n", validateImagesLines))
119128

120-
let validateViewControllersLines = storyboard.viewControllers
121-
.map { "assert(\(sanitizedSwiftName($0.storyboardIdentifier)) != nil, \"[R.swift] ViewController with identifier '\(sanitizedSwiftName($0.storyboardIdentifier))' could not be loaded from storyboard '\(storyboard.name)' as '\($0.type)'.\")" }
129+
let validateViewControllersLines = catOptionals(storyboard.viewControllers
130+
.map { vc in
131+
vc.storyboardIdentifier.map {
132+
"assert(\(sanitizedSwiftName($0)) != nil, \"[R.swift] ViewController with identifier '\(sanitizedSwiftName($0))' could not be loaded from storyboard '\(storyboard.name)' as '\(vc.type)'.\")"
133+
}
134+
})
122135
let validateViewControllersFunc = Function(name: "validateViewControllers", parameters: [], returnType: Type._Void, body: join("\n", validateViewControllersLines))
123136

124-
return Struct(name: storyboard.name, vars: instanceVars + viewControllerVars, functions: [validateImagesFunc, validateViewControllersFunc], structs: [])
137+
return Struct(name: storyboard.name, vars: instanceVars + initialViewControllerVar + viewControllerVars, functions: [validateImagesFunc, validateViewControllersFunc], structs: [])
125138
}
126139

127140
// Nib
@@ -132,10 +145,10 @@ func nibStructFromNibs(nibs: [Nib]) -> Struct {
132145

133146
func nibStructForNib(nib: Nib) -> Struct {
134147
let ownerOrNilParameter = Function.Parameter(name: "ownerOrNil", type: Type._AnyObject.asOptional())
135-
let optionsOrNilParameter = Function.Parameter(name: "options", localName: "optionsOrNil", type: Type(className: "[NSObject : AnyObject]", optional: true))
148+
let optionsOrNilParameter = Function.Parameter(name: "options", localName: "optionsOrNil", type: Type(name: "[NSObject : AnyObject]", optional: true))
136149

137150
let instanceVars = [Var(name: "instance", type: Type._UINib, getter: "return UINib.init(nibName: \"\(nib.name)\", bundle: nil)")]
138-
let instantiateFunc = Function(name: "instantiateWithOwner", parameters: [ownerOrNilParameter, optionsOrNilParameter], returnType: Type(className: "[AnyObject]"), body: "return instance.instantiateWithOwner(ownerOrNil, options: optionsOrNil)")
151+
let instantiateFunc = Function(name: "instantiateWithOwner", parameters: [ownerOrNilParameter, optionsOrNilParameter], returnType: Type(name: "[AnyObject]"), body: "return instance.instantiateWithOwner(ownerOrNil, options: optionsOrNil)")
139152

140153
let viewFuncs = zip(nib.rootViews, Ordinals)
141154
.map { (view: $0.0, ordinal: $0.1) }
@@ -157,7 +170,7 @@ func reuseIdentifierStructFromReuseIdentifierContainers(containers: [ReuseIdenti
157170
// Validation
158171

159172
func validateAllFunctionWithStoryboards(storyboards: [Storyboard]) -> Function {
160-
return Function(name: "validate", parameters: [], returnType: Type._Void, body: storyboards.map(swiftCallStoryboardValidators).reduce("", combine: +))
173+
return Function(name: "validate", parameters: [], returnType: Type._Void, body: join("\n", storyboards.map(swiftCallStoryboardValidators)))
161174
}
162175

163176
func swiftCallStoryboardValidators(storyboard: Storyboard) -> String {

R.swift/types.swift

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,56 @@ import Foundation
1111

1212
/// MARK: Swift types
1313

14-
struct Type: Printable {
15-
static let _Void = Type(className: "Void")
16-
static let _AnyObject = Type(className: "AnyObject")
17-
static let _String = Type(className: "String")
18-
static let _UINib = Type(className: "UINib")
19-
static let _UIImage = Type(className: "UIImage")
20-
static let _UIStoryboard = Type(className: "UIStoryboard")
21-
static let _UIViewController = Type(className: "UIViewController")
22-
23-
let moduleName: String?
24-
let className: String
14+
struct Type: Printable, Equatable {
15+
static let _Void = Type(name: "Void")
16+
static let _AnyObject = Type(name: "AnyObject")
17+
static let _String = Type(name: "String")
18+
static let _UINib = Type(name: "UINib")
19+
static let _UIImage = Type(name: "UIImage")
20+
static let _UIStoryboard = Type(name: "UIStoryboard")
21+
static let _UIViewController = Type(name: "UIViewController")
22+
23+
let module: String?
24+
let name: String
2525
let optional: Bool
2626

2727
var fullyQualifiedName: String {
2828
let optionalString = optional ? "?" : ""
2929

30-
if let moduleName = moduleName {
31-
return "\(moduleName).\(className)\(optionalString)"
30+
if let module = module {
31+
return "\(module).\((name))\(optionalString)"
3232
}
3333

34-
return "\(className)\(optionalString)"
34+
return "\(name)\(optionalString)"
3535
}
3636

3737
var description: String {
3838
return fullyQualifiedName
3939
}
4040

41-
init(className: String, optional: Bool = false) {
42-
self.moduleName = nil
43-
self.className = className
41+
init(name: String, optional: Bool = false) {
42+
self.module = nil
43+
self.name = name
4444
self.optional = optional
4545
}
4646

47-
init(moduleName: String?, className: String, optional: Bool = false) {
48-
self.moduleName = moduleName
49-
self.className = className
47+
init(module: String?, name: String, optional: Bool = false) {
48+
self.module = module
49+
self.name = name
5050
self.optional = optional
5151
}
5252

5353
func asOptional() -> Type {
54-
return Type(moduleName: self.moduleName, className: className, optional: true)
54+
return Type(module: module, name: name, optional: true)
5555
}
5656

5757
func asNonOptional() -> Type {
58-
return Type(moduleName: moduleName, className: className, optional: false)
58+
return Type(module: module, name: name, optional: false)
5959
}
60+
}
6061

61-
func isVoid() -> Bool {
62-
return (moduleName == Type._Void.moduleName && className == Type._Void.className && optional == Type._Void.optional)
63-
}
62+
func ==(lhs: Type, rhs: Type) -> Bool {
63+
return (lhs.module == rhs.module && lhs.name == rhs.name && lhs.optional == rhs.optional)
6464
}
6565

6666
struct Var: Printable {
@@ -83,7 +83,7 @@ struct Function: Printable {
8383
var description: String {
8484
let swiftName = sanitizedSwiftName(name, lowercaseFirstCharacter: true)
8585
let parameterString = join(", ", parameters)
86-
let returnString = returnType.isVoid() ? "" : " -> \(returnType)"
86+
let returnString = Type._Void == returnType ? "" : " -> \(returnType)"
8787
return "static func \(swiftName)(\(parameterString))\(returnString) {\n\(indent(body))\n}"
8888
}
8989

@@ -104,6 +104,7 @@ struct Function: Printable {
104104

105105
init(name: String, type: Type) {
106106
self.name = name
107+
self.localName = nil
107108
self.type = type
108109
}
109110

@@ -155,18 +156,23 @@ struct AssetFolder {
155156
init(url: NSURL, fileManager: NSFileManager) {
156157
name = url.filename!
157158

158-
let contents = fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles, error: nil) as [NSURL]
159+
let contents = fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles, error: nil) as! [NSURL]
159160
imageAssets = contents.map { $0.filename! }
160161
}
161162
}
162163

163164
struct Storyboard: ReuseIdentifierContainer {
164165
let name: String
165166
let segues: [String]
167+
private let initialViewControllerIdentifier: String?
166168
let viewControllers: [ViewController]
167169
let usedImageIdentifiers: [String]
168170
let reuseIdentifiers: [String]
169171

172+
var initialViewController: ViewController? {
173+
return viewControllers.filter { $0.id == self.initialViewControllerIdentifier }.first
174+
}
175+
170176
init(url: NSURL) {
171177
name = url.filename!
172178

@@ -177,13 +183,15 @@ struct Storyboard: ReuseIdentifierContainer {
177183
parser.parse()
178184

179185
segues = parserDelegate.segues
186+
initialViewControllerIdentifier = parserDelegate.initialViewControllerIdentifier
180187
viewControllers = parserDelegate.viewControllers
181188
usedImageIdentifiers = parserDelegate.usedImageIdentifiers
182189
reuseIdentifiers = parserDelegate.reuseIdentifiers
183190
}
184191

185192
struct ViewController {
186-
let storyboardIdentifier: String
193+
let id: String
194+
let storyboardIdentifier: String?
187195
let type: Type
188196
}
189197
}
@@ -210,13 +218,19 @@ struct Nib: ReuseIdentifierContainer {
210218
/// MARK: Parsers
211219

212220
class StoryboardParserDelegate: NSObject, NSXMLParserDelegate {
221+
var initialViewControllerIdentifier: String?
213222
var segues: [String] = []
214223
var viewControllers: [Storyboard.ViewController] = []
215224
var usedImageIdentifiers: [String] = []
216225
var reuseIdentifiers: [String] = []
217226

218-
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {
227+
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {
219228
switch elementName {
229+
case "document":
230+
if let initialViewController = attributeDict["initialViewController"] as? String {
231+
initialViewControllerIdentifier = initialViewController
232+
}
233+
220234
case "segue":
221235
if let segueIdentifier = attributeDict["identifier"] as? String {
222236
segues.append(segueIdentifier)
@@ -240,16 +254,19 @@ class StoryboardParserDelegate: NSObject, NSXMLParserDelegate {
240254

241255
func viewControllerFromAttributes(attributeDict: [NSObject : AnyObject], elementName: String) -> Storyboard.ViewController? {
242256
if attributeDict["sceneMemberID"] as? String == "viewController" {
243-
if let storyboardIdentifier = attributeDict["storyboardIdentifier"] as? String {
244-
let customModule = attributeDict["customModule"] as? String
245-
let customClass = attributeDict["customClass"] as? String
246-
let customType = customClass.map { Type(moduleName: customModule, className: $0, optional: false) }
257+
if let id = attributeDict["id"] as? String {
258+
let storyboardIdentifier = attributeDict["storyboardIdentifier"] as? String
247259

248-
let type = customType ?? ElementNameToTypeMapping[elementName] ?? Type._UIViewController
249-
return Storyboard.ViewController(storyboardIdentifier: storyboardIdentifier, type: type)
250-
}
260+
let customModule = attributeDict["customModule"] as? String
261+
let customClass = attributeDict["customClass"] as? String
262+
let customType = customClass.map { Type(module: customModule, name: $0, optional: false) }
263+
264+
let type = customType ?? ElementNameToTypeMapping[elementName] ?? Type._UIViewController
265+
266+
return Storyboard.ViewController(id: id, storyboardIdentifier: storyboardIdentifier, type: type)
267+
}
251268
}
252-
269+
253270
return nil
254271
}
255272
}
@@ -263,7 +280,7 @@ class NibParserDelegate: NSObject, NSXMLParserDelegate {
263280
var isObjectsTagOpened = false;
264281
var levelSinceObjectsTagOpened = 0;
265282

266-
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {
283+
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {
267284
switch elementName {
268285
case "objects":
269286
isObjectsTagOpened = true;
@@ -285,7 +302,7 @@ class NibParserDelegate: NSObject, NSXMLParserDelegate {
285302
}
286303
}
287304

288-
func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) {
305+
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
289306
switch elementName {
290307
case "objects":
291308
isObjectsTagOpened = false;
@@ -299,8 +316,8 @@ class NibParserDelegate: NSObject, NSXMLParserDelegate {
299316

300317
func viewWithAttributes(attributeDict: [NSObject : AnyObject]) -> Type? {
301318
let customModule = attributeDict["customModule"] as? String
302-
let customClass = attributeDict["customClass"] as? String ?? "UIView"
319+
let customClass = (attributeDict["customClass"] as? String) ?? "UIView"
303320

304-
return Type(moduleName: customModule, className: customClass)
321+
return Type(module: customModule, name: customClass)
305322
}
306323
}

R.swift/util.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import Foundation
1111

12+
1213
// MARK: Array operations
1314

1415
extension Array {
@@ -25,7 +26,15 @@ extension Array {
2526
}
2627
}
2728

28-
func flatten<T>(coll : [[T]]) -> [T] {
29+
func catOptionals<T>(c: [T?]) -> [T] {
30+
return c.flatMap(list)
31+
}
32+
33+
func list<T>(x: T?) -> [T] {
34+
return x.map { [$0] } ?? []
35+
}
36+
37+
func flatten<T>(coll: [[T]]) -> [T] {
2938
return coll.reduce([], combine: +)
3039
}
3140

@@ -51,7 +60,7 @@ func join<S where S: Printable>(separator: String, components: [S]) -> String {
5160

5261
extension String {
5362
var lowercaseFirstCharacter: String {
54-
if countElements(self) <= 1 { return self.lowercaseString }
63+
if count(self) <= 1 { return self.lowercaseString }
5564
let index = advance(startIndex, 1)
5665
return substringToIndex(index).lowercaseString + substringFromIndex(index)
5766
}
@@ -71,7 +80,7 @@ extension NSURL {
7180
var urlIsDirectoryValue: AnyObject?
7281
self.getResourceValue(&urlIsDirectoryValue, forKey: NSURLIsDirectoryKey, error: nil)
7382

74-
return urlIsDirectoryValue as? Bool ?? false
83+
return (urlIsDirectoryValue as? Bool) ?? false
7584
}
7685

7786
var filename: String? {

R.swift/values.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ let Ordinals = [
4545

4646
let ElementNameToTypeMapping = [
4747
"viewController": Type._UIViewController,
48-
"glkViewController": Type(className: "GLKViewController"),
49-
"tabBarController": Type(className: "UITabBarController"),
50-
"pageViewController": Type(className: "UIPageViewController"),
51-
"tableViewController": Type(className: "UITableViewController"),
52-
"splitViewController": Type(className: "UISplitViewController"),
53-
"navigationController": Type(className: "UINavigationController"),
54-
"avPlayerViewController": Type(className: "AVPlayerViewController"),
55-
"collectionViewController": Type(className: "UICollectionViewController"),
48+
"glkViewController": Type(name: "GLKViewController"),
49+
"tabBarController": Type(name: "UITabBarController"),
50+
"pageViewController": Type(name: "UIPageViewController"),
51+
"tableViewController": Type(name: "UITableViewController"),
52+
"splitViewController": Type(name: "UISplitViewController"),
53+
"navigationController": Type(name: "UINavigationController"),
54+
"avPlayerViewController": Type(name: "AVPlayerViewController"),
55+
"collectionViewController": Type(name: "UICollectionViewController"),
5656
]

0 commit comments

Comments
 (0)