├── .gitignore
├── CustomViews
├── CustomViews
│ ├── SampleTable.json
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── CounterView.swift
│ ├── SquaresView.swift
│ ├── PacketLineExtensions.swift
│ ├── Info.plist
│ ├── Extensions.swift
│ ├── FeedParser.swift
│ ├── RemoteGitRepository.swift
│ ├── TwoLabels.swift
│ ├── StreamExtensions.swift
│ ├── ProgressView.swift
│ ├── PacketLineParser.swift
│ ├── AppDelegate.swift
│ ├── CounterView.xib
│ ├── Base.lproj
│ │ └── LaunchScreen.xib
│ └── SampleTable.swift
├── CustomViews.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
└── CustomViewsTests
│ ├── Info.plist
│ └── CustomViewsTests.swift
├── RepositoryBrowser
├── api
│ ├── users
│ │ ├── alblue.jpg
│ │ └── alblue.json
│ ├── README.txt
│ └── index.json
├── RepositoryBrowserWatch Extension
│ ├── Assets.xcassets
│ │ └── README__ignoredByTemplate__
│ ├── Info.plist
│ ├── RepositoryController.swift
│ ├── RepositoryListController.swift
│ ├── ExtensionDelegate.swift
│ └── InterfaceController.swift
├── RepositoryBrowser.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── RepositoryBrowserTests
│ ├── Info.plist
│ ├── ThreadsTest.swift
│ ├── URITemplateTests.swift
│ ├── GitHubAPITests.swift
│ ├── RepositoryBrowserTests.swift
│ └── NSURLExtensionsTest.swift
├── RepositoryBrowserWatch
│ ├── Info.plist
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ └── Base.lproj
│ │ └── Interface.storyboard
└── RepositoryBrowser
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Threads.swift
│ ├── Info.plist
│ ├── URITemplate.swift
│ ├── DetailViewController.swift
│ ├── NSURLExtensions.swift
│ ├── Base.lproj
│ └── LaunchScreen.xib
│ ├── GitHubAPI.swift
│ ├── AppDelegate.swift
│ └── MasterViewController.swift
├── playing
└── MyPlayground.playground
│ ├── Resources
│ └── alblue.png
│ ├── Pages
│ ├── Example Documentation.xcplaygroundpage
│ │ ├── timeline.xctimeline
│ │ └── Contents.swift
│ └── Playground Code.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ └── contents.xcplayground
├── SingleView
├── SingleView.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── SingleViewTests
│ ├── Info.plist
│ └── SingleViewTests.swift
├── GitHubDetails.swift
├── SingleView
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── ViewController.swift
│ ├── AppDelegate.swift
│ └── Base.lproj
│ │ └── LaunchScreen.xib
├── GitHubRepositoryTest.swift
├── GitHubRepository.swift
├── Cards.swift
└── CardsTest.swift
├── Storyboards
├── Storyboards.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── StoryboardsTests
│ ├── Info.plist
│ └── StoryboardsTests.swift
└── Storyboards
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── ViewController.swift
│ ├── Info.plist
│ ├── MessageViewController.swift
│ ├── AppDelegate.swift
│ └── Base.lproj
│ └── LaunchScreen.xib
├── MasterDetail
├── MasterDetail.xcodeproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── MasterDetailTests
│ ├── Info.plist
│ └── MasterDetailTests.swift
└── MasterDetail
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Info.plist
│ ├── DetailViewController.swift
│ ├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
│ ├── AppDelegate.swift
│ └── MasterViewController.swift
├── exploring
├── upper.swift
├── iteration.swift
├── functions.swift
└── literals.swift
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *~
3 | xcuserdata
4 | xcshareddata
5 | *.xcworkspace
6 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/SampleTable.json:
--------------------------------------------------------------------------------
1 | [{"title":"Sample Title","content":"Sample Content"}]
2 |
--------------------------------------------------------------------------------
/RepositoryBrowser/api/users/alblue.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alblue/com.packtpub.swift.essentials/HEAD/RepositoryBrowser/api/users/alblue.jpg
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/Assets.xcassets/README__ignoredByTemplate__:
--------------------------------------------------------------------------------
1 | Did you know that git does not support storing empty directories?
2 |
--------------------------------------------------------------------------------
/playing/MyPlayground.playground/Resources/alblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alblue/com.packtpub.swift.essentials/HEAD/playing/MyPlayground.playground/Resources/alblue.png
--------------------------------------------------------------------------------
/playing/MyPlayground.playground/Pages/Example Documentation.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SingleView/SingleView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RepositoryBrowser/api/README.txt:
--------------------------------------------------------------------------------
1 | The GitHub API is rate-limited. In order to test and develop
2 | against it the files in this directory can be published to a web server
3 | and used as a testing proxy.
4 |
5 | Run this in a web server (for example, python -m SimpleHTTPServer 1234)
6 | and the API can be used against http://localhost:1234/index.json.
7 |
--------------------------------------------------------------------------------
/playing/MyPlayground.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/exploring/upper.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env xcrun swift
2 |
3 | import func Darwin.exit
4 |
5 | let args = Process.arguments[1.. This is a block quote
23 | //: > which is merged together
24 | //: > using _italics_ or **bold**
25 | //:
26 | //: Link to [AlBlue's Blog](http://alblue.bandlem.com)
27 | //: Image of 
--------------------------------------------------------------------------------
/CustomViews/CustomViewsTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SingleView/SingleViewTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Storyboards/StoryboardsTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetailTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016, Alex Blewitt
4 | Copyright (c) 2016, Packt Publishing Ltd
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
14 | all 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
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/RepositoryBrowser/api/users/alblue.json:
--------------------------------------------------------------------------------
1 | {
2 | "login": "alblue",
3 | "id": 76791,
4 | "avatar_url": "../users/alblue.jpg",
5 | "gravatar_id": "",
6 | "url": "../users/alblue.json",
7 | "html_url": "https://github.com/alblue",
8 | "followers_url": "../users/alblue/followers.json",
9 | "following_url": "../users/alblue/following{/other_user}.json",
10 | "gists_url": "../users/alblue/gists{/gist_id}.json",
11 | "starred_url": "../users/alblue/starred{/owner}{/repo}.json",
12 | "subscriptions_url": "../users/alblue/subscriptions.json",
13 | "organizations_url": "../users/alblue/orgs.json",
14 | "repos_url": "../users/alblue/repos.json",
15 | "events_url": "../users/alblue/events{/privacy}.json",
16 | "received_events_url": "../users/alblue/received_events.json",
17 | "type": "User",
18 | "site_admin": false,
19 | "name": "Alex Blewitt",
20 | "company": "Bandlem Ltd",
21 | "blog": "http://alblue.bandlem.com",
22 | "location": "Milton Keynes, UK",
23 | "email": "Alex.Blewitt+github@gmail.com",
24 | "hireable": false,
25 | "bio": null,
26 | "public_repos": 22,
27 | "public_gists": 1,
28 | "followers": 19,
29 | "following": 1,
30 | "created_at": "2009-04-22T23:57:30Z",
31 | "updated_at": "2014-10-16T16:04:16Z"
32 | }
33 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | RepositoryBrowser
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | UISupportedInterfaceOrientations
26 |
27 | UIInterfaceOrientationPortrait
28 | UIInterfaceOrientationPortraitUpsideDown
29 |
30 | WKCompanionAppBundleIdentifier
31 | com.packtpub.swift.essentials.RepositoryBrowser
32 | WKWatchKitApp
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/SingleView/GitHubDetails.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | protocol GitHubDetails {
23 | func detailsURL() -> String
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "24x24",
5 | "idiom" : "watch",
6 | "scale" : "2x",
7 | "role" : "notificationCenter",
8 | "subtype" : "38mm"
9 | },
10 | {
11 | "size" : "27.5x27.5",
12 | "idiom" : "watch",
13 | "scale" : "2x",
14 | "role" : "notificationCenter",
15 | "subtype" : "42mm"
16 | },
17 | {
18 | "size" : "29x29",
19 | "idiom" : "watch",
20 | "role" : "companionSettings",
21 | "scale" : "2x"
22 | },
23 | {
24 | "size" : "29x29",
25 | "idiom" : "watch",
26 | "role" : "companionSettings",
27 | "scale" : "3x"
28 | },
29 | {
30 | "size" : "40x40",
31 | "idiom" : "watch",
32 | "scale" : "2x",
33 | "role" : "appLauncher",
34 | "subtype" : "38mm"
35 | },
36 | {
37 | "size" : "86x86",
38 | "idiom" : "watch",
39 | "scale" : "2x",
40 | "role" : "quickLook",
41 | "subtype" : "38mm"
42 | },
43 | {
44 | "size" : "98x98",
45 | "idiom" : "watch",
46 | "scale" : "2x",
47 | "role" : "quickLook",
48 | "subtype" : "42mm"
49 | }
50 | ],
51 | "info" : {
52 | "version" : 1,
53 | "author" : "xcode"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/SingleView/SingleView/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 | }
--------------------------------------------------------------------------------
/Storyboards/Storyboards/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 | }
--------------------------------------------------------------------------------
/playing/MyPlayground.playground/Pages/Playground Code.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | var str = "Hello, playground"
6 |
7 | for i in 1...12 {
8 | let j = (i-7) * (i-6)
9 | let k = i
10 | print("I is \(i)")
11 | }
12 |
13 | let blue = UIColor.blueColor()
14 | let size = CGRect(x:0,y:0,width:200,height:100)
15 | let label = UILabel(frame:size)
16 | label.text = str
17 | label.textColor = blue;
18 | label.font = UIFont.systemFontOfSize(24)
19 | let alblue = UIImage(named:"alblue")
20 |
21 | import XCPlayground
22 |
23 | let page = XCPlaygroundPage.currentPage
24 | page.captureValue(alblue, withIdentifier:"Al Blue")
25 |
26 | dispatch_async(dispatch_get_main_queue()) {
27 | for n in 1...6 {
28 | if n % 2 == 0 {
29 | page.captureValue(n,withIdentifier:"even")
30 | page.captureValue(0,withIdentifier:"odd")
31 | } else {
32 | page.captureValue(n,withIdentifier:"odd")
33 | page.captureValue(0,withIdentifier:"even")
34 | }
35 | }
36 | }
37 | page.needsIndefiniteExecution = true
38 |
39 | /**
40 | Returns the string in SHOUTY CAPS
41 | - parameter input: the input string
42 | - author: Alex Blewitt
43 | - returns: The input string, but in upper case
44 | - throws: No errors thrown
45 | - note: Please don't shout
46 | - seealso: String.uppercaseString
47 | - since: 2016
48 | */
49 | func shout(input:String) -> String {
50 | return input.uppercaseString
51 | }
52 | shout(str)
53 |
--------------------------------------------------------------------------------
/RepositoryBrowser/api/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "current_user_url": "user.json",
3 | "authorizations_url": "authorizations.json",
4 | "code_search_url": "search/code?q={query}{&page,per_page,sort,order}.json",
5 | "emails_url": "user/emails.json",
6 | "emojis_url": "emojis.json",
7 | "events_url": "events.json",
8 | "feeds_url": "feeds.json",
9 | "following_url": "user/following{/target}.json",
10 | "gists_url": "gists{/gist_id}.json",
11 | "hub_url": "hub.json",
12 | "issue_search_url": "search/issues?q={query}{&page,per_page,sort,order}.json",
13 | "issues_url": "issues.json",
14 | "keys_url": "user/keys.json",
15 | "notifications_url": "notifications.json",
16 | "organization_repositories_url": "orgs/{org}/repos{?type,page,per_page,sort}.json",
17 | "organization_url": "orgs/{org}.json",
18 | "public_gists_url": "gists/public.json",
19 | "rate_limit_url": "rate_limit.json",
20 | "repository_url": "repos/{owner}/{repo}.json",
21 | "repository_search_url": "search/repositories?q={query}{&page,per_page,sort,order}.json",
22 | "current_user_repositories_url": "user/repos{?type,page,per_page,sort}.json",
23 | "starred_url": "user/starred{/owner}{/repo}.json",
24 | "starred_gists_url": "gists/starred.json",
25 | "team_url": "teams.json",
26 | "user_url": "users/{user}.json",
27 | "user_organizations_url": "user/orgs.json",
28 | "user_repositories_url": "users/{user}/repos{?type,page,per_page,sort}.json",
29 | "user_search_url": "search/users?q={query}{&page,per_page,sort,order}"
30 | }
31 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | RepositoryBrowserWatch Extension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSExtension
26 |
27 | NSExtensionAttributes
28 |
29 | WKAppBundleIdentifier
30 | com.packtpub.swift.essentials.RepositoryBrowser.watchkitapp
31 |
32 | NSExtensionPointIdentifier
33 | com.apple.watchkit
34 |
35 | RemoteInterfacePrincipalClass
36 | $(PRODUCT_MODULE_NAME).InterfaceController
37 | WKExtensionDelegateClassName
38 | $(PRODUCT_MODULE_NAME).ExtensionDelegate
39 |
40 |
41 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/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 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/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 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/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 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/SingleView/GitHubRepositoryTest.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class GitHubRepositoryTest:XCTestCase {
25 | func testRepository() {
26 | let repo = GitHubRepository()
27 | repo.id = 1
28 | repo.name = "Grit"
29 | XCTAssertEqual(repo.detailsURL(),"https://api.github.com/repositories/1","repository details")
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/ThreadsTest.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class ThreadsTest: XCTestCase {
25 | func testThreads() {
26 | Threads.runOnBackgroundThread {
27 | XCTAssertFalse(NSThread.isMainThread(), "Running on background thread")
28 | Threads.runOnUIThread {
29 | XCTAssertTrue(NSThread.isMainThread(), "Running on UI thread")
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/URITemplateTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class URITemplateTests: XCTestCase {
25 |
26 | func testURITemplate() {
27 | let template = "http://example.com/{blah}/blah/{?blah}"
28 | let replacement = URITemplate.replace(template,values: ["blah":"foo"])
29 | XCTAssertEqual("http://example.com/foo/blah/",replacement,"Template replacement")
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/SingleView/SingleView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/Threads.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | class Threads {
25 | class func runOnBackgroundThread(fn:()->()) {
26 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),fn)
27 | }
28 | class func runOnUIThread(fn:()->()) {
29 | if NSThread.isMainThread() {
30 | fn()
31 | } else {
32 | dispatch_async(dispatch_get_main_queue(), fn)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards/ViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class ViewController: UIViewController {
25 |
26 | override func viewDidLoad() {
27 | super.viewDidLoad()
28 | // Do any additional setup after loading the view, typically from a nib.
29 | }
30 |
31 | override func didReceiveMemoryWarning() {
32 | super.didReceiveMemoryWarning()
33 | // Dispose of any resources that can be recreated.
34 | }
35 |
36 |
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/SingleView/GitHubRepository.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | class GitHubRepository:GitHubDetails {
23 | class var api:String {
24 | get {
25 | return "https://api.github.com"
26 | }
27 | }
28 | var id:UInt64 = 0
29 | var name:String = ""
30 | func detailsURL() -> String {
31 | return "\(GitHubRepository.api)/repositories/\(id)"
32 | }
33 | }
34 |
35 | // let repo = GitHubRepository()
36 | // repo.id = 1
37 | // repo.name = Grit
38 | // repo.detailsURL() == https://api.github.com/repositories/1
39 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards/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
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 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/CounterView.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class CounterView:UIView {
25 | @IBOutlet weak var label:UILabel!
26 | @IBAction func change(sender:AnyObject) {
27 | let count = (sender as! UIStepper).value
28 | label.text = "Count is \(count)"
29 | }
30 | override func intrinsicContentSize() -> CGSize {
31 | let height = max(50,label.intrinsicContentSize().height)
32 | let width = max(300,label.intrinsicContentSize().width)
33 | return CGSize(width: width, height: height)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/SingleView/SingleView/ViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | import UIKit
24 |
25 | class ViewController: UIViewController {
26 |
27 | override func viewDidLoad() {
28 | super.viewDidLoad()
29 | view.backgroundColor = UIColor.blackColor()
30 | let label = UILabel(frame:view.bounds)
31 | label.textColor = UIColor.whiteColor()
32 | label.textAlignment = .Center
33 | label.text = "Welcome to Swift"
34 | view.addSubview(label)
35 | }
36 |
37 | override func didReceiveMemoryWarning() {
38 | super.didReceiveMemoryWarning()
39 | // Dispose of any resources that can be recreated.
40 | }
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/SingleView/Cards.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | enum Suit {
23 | case Clubs, Diamonds, Hearts // many on one line
24 | case Spades // or on different lines
25 | }
26 |
27 | // var suit:Suit = Suit.Clubs
28 | // var suit:Suit = .Clubs
29 |
30 | enum Rank:Int {
31 | case Two = 2, Three, Four, Five
32 | case Six, Seven, Eight, Nine, Ten
33 | case Jack, Queen, King, Ace
34 | }
35 |
36 | // Rank.Two.rawValue == 2
37 | // Rank(rawValue:14)! == Rank.Ace
38 |
39 | enum Card {
40 | case Face(Rank,Suit)
41 | case Joker
42 | }
43 |
44 | // var aceOfSpades:Card = .Face(.Ace,.Spades)
45 | // var twoOfHearts:Card = .Face(.Two,.Hearts)
46 | // var theJoker:Card = .Joker
47 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/RepositoryController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import WatchKit
23 | import Foundation
24 |
25 | class RepositoryController: WKInterfaceController {
26 | @IBOutlet weak var repo: WKInterfaceLabel!
27 | @IBOutlet weak var issues: WKInterfaceLabel!
28 | @IBOutlet weak var watchers: WKInterfaceLabel!
29 | @IBOutlet weak var forks: WKInterfaceLabel!
30 | override func awakeWithContext(context: AnyObject?) {
31 | if let data = context as? [String:String] {
32 | repo.setText(data["name"])
33 | issues.setText(data["open_issues_count"])
34 | watchers.setText(data["watchers_count"])
35 | forks.setText(data["forks_count"])
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/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
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIStatusBarTintParameters
34 |
35 | UINavigationBar
36 |
37 | Style
38 | UIBarStyleDefault
39 | Translucent
40 |
41 |
42 |
43 | UISupportedInterfaceOrientations
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 | UISupportedInterfaceOrientations~ipad
50 |
51 | UIInterfaceOrientationPortrait
52 | UIInterfaceOrientationPortraitUpsideDown
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/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
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIStatusBarTintParameters
34 |
35 | UINavigationBar
36 |
37 | Style
38 | UIBarStyleDefault
39 | Translucent
40 |
41 |
42 |
43 | UISupportedInterfaceOrientations
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 | UISupportedInterfaceOrientations~ipad
50 |
51 | UIInterfaceOrientationPortrait
52 | UIInterfaceOrientationPortraitUpsideDown
53 | UIInterfaceOrientationLandscapeLeft
54 | UIInterfaceOrientationLandscapeRight
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/GitHubAPITests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class GitHubAPITests: XCTestCase{
25 | func testApi() {
26 | let bundle = NSBundle(forClass:GitHubAPITests.self)
27 | if let url = bundle.URLForResource("api/index", withExtension:"json") {
28 | if let api = GitHubAPI.connect(url) {
29 | XCTAssertTrue(true,"Created API")
30 | let userRepo = api.getURLForUserRepos("alblue")
31 | userRepo.withJSONArrayOfDictionary {
32 | array in
33 | XCTAssertEqual(22,array.count,"Number of repos")
34 | }
35 | api.withUserRepos("alblue") {
36 | array in
37 | XCTAssertEqual(22,array.count,"Number of repos")
38 | }
39 | } else {
40 | XCTAssertFalse(true,"Failed to parse \(url)")
41 | }
42 | } else {
43 | XCTAssertFalse(true,"Failed to find sample API")
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/SingleView/SingleViewTests/SingleViewTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 | import XCTest
24 |
25 | class SingleViewTests: XCTestCase {
26 |
27 | override func setUp() {
28 | super.setUp()
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 | }
31 |
32 | override func tearDown() {
33 | // Put teardown code here. This method is called after the invocation of each test method in the class.
34 | super.tearDown()
35 | }
36 |
37 | func testExample() {
38 | // This is an example of a functional test case.
39 | XCTAssert(true, "Pass")
40 | }
41 |
42 | func testPerformanceExample() {
43 | // This is an example of a performance test case.
44 | self.measureBlock() {
45 | // Put the code you want to measure the time of here.
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/CustomViews/CustomViewsTests/CustomViewsTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 | import XCTest
24 |
25 | class CustomViewsTests: XCTestCase {
26 |
27 | override func setUp() {
28 | super.setUp()
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 | }
31 |
32 | override func tearDown() {
33 | // Put teardown code here. This method is called after the invocation of each test method in the class.
34 | super.tearDown()
35 | }
36 |
37 | func testExample() {
38 | // This is an example of a functional test case.
39 | XCTAssert(true, "Pass")
40 | }
41 |
42 | func testPerformanceExample() {
43 | // This is an example of a performance test case.
44 | self.measureBlock() {
45 | // Put the code you want to measure the time of here.
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetailTests/MasterDetailTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 | import XCTest
24 |
25 | class MasterDetailTests: XCTestCase {
26 |
27 | override func setUp() {
28 | super.setUp()
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 | }
31 |
32 | override func tearDown() {
33 | // Put teardown code here. This method is called after the invocation of each test method in the class.
34 | super.tearDown()
35 | }
36 |
37 | func testExample() {
38 | // This is an example of a functional test case.
39 | XCTAssert(true, "Pass")
40 | }
41 |
42 | func testPerformanceExample() {
43 | // This is an example of a performance test case.
44 | self.measureBlock() {
45 | // Put the code you want to measure the time of here.
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Storyboards/StoryboardsTests/StoryboardsTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 | import XCTest
24 |
25 | class StoryboardsTests: XCTestCase {
26 |
27 | override func setUp() {
28 | super.setUp()
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 | }
31 |
32 | override func tearDown() {
33 | // Put teardown code here. This method is called after the invocation of each test method in the class.
34 | super.tearDown()
35 | }
36 |
37 | func testExample() {
38 | // This is an example of a functional test case.
39 | XCTAssert(true, "Pass")
40 | }
41 |
42 | func testPerformanceExample() {
43 | // This is an example of a performance test case.
44 | self.measureBlock() {
45 | // Put the code you want to measure the time of here.
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/SquaresView.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class SquaresView: UIView {
25 | required init?(coder: NSCoder) {
26 | super.init(coder:coder)
27 | setupView()
28 | }
29 | override init(frame: CGRect) {
30 | super.init(frame:frame)
31 | setupView()
32 | }
33 | func setupView() {
34 | contentMode = .Redraw
35 | }
36 | override func drawRect(rect: CGRect) {
37 | let context = UIGraphicsGetCurrentContext()
38 | let red = UIColor.redColor().CGColor
39 | CGContextSetStrokeColorWithColor(context,red)
40 | CGContextStrokeRect(context, CGRect(x:center.x - 50, y:center.y - 50, width:100, height:100))
41 | UIColor.greenColor().setFill()
42 | UIColor.blackColor().setStroke()
43 | CGContextFillRect(context, CGRect(x:center.x - 25, y:center.y - 25, width:50, height:50))
44 | CGContextStrokeRect(context, CGRect(x:center.x - 25, y:center.y - 25, width:50, height:50))
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/RepositoryBrowserTests.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 | import XCTest
24 |
25 | class RepositoryBrowserTests: XCTestCase {
26 |
27 | override func setUp() {
28 | super.setUp()
29 | // Put setup code here. This method is called before the invocation of each test method in the class.
30 | }
31 |
32 | override func tearDown() {
33 | // Put teardown code here. This method is called after the invocation of each test method in the class.
34 | super.tearDown()
35 | }
36 |
37 | func testExample() {
38 | // This is an example of a functional test case.
39 | XCTAssert(true, "Pass")
40 | }
41 |
42 | func testPerformanceExample() {
43 | // This is an example of a performance test case.
44 | self.measureBlock() {
45 | // Put the code you want to measure the time of here.
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/SingleView/CardsTest.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class CardsTest:XCTestCase {
25 | func testSuit() {
26 | let suit_clubs:Suit = Suit.Clubs
27 | let clubs:Suit = .Clubs
28 | XCTAssertEqual(suit_clubs,clubs,"Clubs are equal")
29 | }
30 | func testRank() {
31 | XCTAssertEqual(Rank.Two.rawValue,2,"Rank.Two.rawValue == 2")
32 | XCTAssertEqual(Rank(rawValue: 14)!,Rank.Ace,"Rank(rawValue:14)! == Rank.Ace")
33 | }
34 | func testCard() {
35 | let aceOfSpades:Card = .Face(.Ace,.Spades)
36 | let theJoker:Card = .Joker
37 |
38 | var jokerSeen = false;
39 | var aceOfSpadesSeen = false;
40 |
41 | for card in [aceOfSpades,theJoker] {
42 | switch(card) {
43 | case .Face(.Ace,.Spades): aceOfSpadesSeen = true
44 | case .Face(let rank, let suit): XCTFail("Saw a card \(rank) of \(suit)")
45 | case .Joker: jokerSeen = true
46 | }
47 | }
48 | XCTAssert(jokerSeen)
49 | XCTAssert(aceOfSpadesSeen)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/PacketLineExtensions.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | extension NSOutputStream {
25 | func writePacketLine(message:String = "") -> Int {
26 | let data = message.utf8data
27 | let length = data.length
28 | if length == 0 {
29 | return writeData("0000".utf8data)
30 | } else {
31 | let prefix = (length + 4).toHex(4).utf8data
32 | return self.writeData(prefix) + self.writeData(data)
33 | }
34 | }
35 | }
36 |
37 | extension NSInputStream {
38 | func readPacketLine() -> NSData? {
39 | if let data = readData(4) {
40 | let length = data.utf8string.fromHex()
41 | if length == 0 {
42 | return nil
43 | } else {
44 | return readData(length - 4)
45 | }
46 | } else {
47 | return nil
48 | }
49 | }
50 | func readPacketLineString() -> NSString? {
51 | if let data = self.readPacketLine() {
52 | return data.utf8string
53 | } else {
54 | return nil
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/URITemplate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | class URITemplate {
25 | class func replace(template:String, values:[String:String]) -> String {
26 | var replacement = template
27 | while true {
28 | if let parameterRange = replacement.rangeOfString("\\{[^}]*\\}", options: NSStringCompareOptions.RegularExpressionSearch) {
29 | var value:String
30 | let parameter = replacement.substringWithRange(parameterRange)
31 | if parameter.hasPrefix("{?") {
32 | value = ""
33 | } else {
34 | let start = parameterRange.startIndex.successor()
35 | let end = parameterRange.endIndex.predecessor()
36 | let name = replacement.substringWithRange(Range(start:start,end:end))
37 | value = values[name] ?? ""
38 | }
39 | replacement.replaceRange(parameterRange, with: value)
40 | } else {
41 | break
42 | }
43 | }
44 | return replacement
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/DetailViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class DetailViewController: UIViewController {
25 |
26 | @IBOutlet weak var detailDescriptionLabel: UILabel!
27 |
28 |
29 | var detailItem: AnyObject? {
30 | didSet {
31 | // Update the view.
32 | self.configureView()
33 | }
34 | }
35 |
36 | func configureView() {
37 | // Update the user interface for the detail item.
38 | if let detail: AnyObject = self.detailItem {
39 | if let label = self.detailDescriptionLabel {
40 | label.text = detail.description
41 | }
42 | }
43 | }
44 |
45 | override func viewDidLoad() {
46 | super.viewDidLoad()
47 | // Do any additional setup after loading the view, typically from a nib.
48 | self.configureView()
49 | }
50 |
51 | override func didReceiveMemoryWarning() {
52 | super.didReceiveMemoryWarning()
53 | // Dispose of any resources that can be recreated.
54 | }
55 |
56 |
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/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
29 | UIStatusBarHidden
30 |
31 | UIViewControllerBasedStatusBarAppearance
32 |
33 | NSAppTransportSecurity
34 |
35 | NSAllowsArbitraryLoads
36 |
37 |
38 | UIRequiredDeviceCapabilities
39 |
40 | armv7
41 |
42 | UIStatusBarTintParameters
43 |
44 | UINavigationBar
45 |
46 | Style
47 | UIBarStyleDefault
48 | Translucent
49 |
50 |
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/DetailViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class DetailViewController: UIViewController {
25 |
26 | @IBOutlet weak var userLabel: UILabel?
27 | @IBOutlet weak var repoLabel: UILabel?
28 | @IBOutlet weak var issuesLabel: UILabel?
29 | @IBOutlet weak var watchersLabel: UILabel?
30 |
31 | var user: String? {
32 | didSet {
33 | configureView()
34 | }
35 | }
36 | var repo: String? {
37 | didSet {
38 | configureView()
39 | }
40 | }
41 | var data:[String:String]? {
42 | didSet {
43 | configureView()
44 | }
45 | }
46 | override func viewDidLoad() {
47 | super.viewDidLoad()
48 | configureView()
49 | }
50 | func configureView() {
51 | if let label = userLabel { label.text = user }
52 | if let label = repoLabel { label.text = repo }
53 | if let label = issuesLabel {
54 | label.text = self.data?["open_issues_count"]
55 | }
56 | if let label = watchersLabel {
57 | label.text = self.data?["watchers_count"]
58 | }
59 | }
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards/MessageViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class MessageViewController: UIViewController {
25 |
26 | let messages = [
27 | "Ouch, that hurts",
28 | "Please don't do that again",
29 | "Why did you press that?",
30 | ]
31 | @IBAction func changeMessage() {
32 | message.text = messages[Int(arc4random_uniform(UInt32(messages.count)))]
33 | }
34 | @IBOutlet weak var message: UILabel!
35 | @IBAction func about(sender: AnyObject) {
36 | performSegueWithIdentifier("about", sender: sender)
37 | }
38 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
39 | if segue.identifier == "about" {
40 | let dest = segue.destinationViewController as UIViewController
41 | dest.view.backgroundColor = message.backgroundColor
42 | }
43 | }
44 | override func viewDidLoad() {
45 | let red = CGFloat(drand48())
46 | let green = CGFloat(drand48())
47 | let blue = CGFloat(drand48())
48 | message.backgroundColor = UIColor(
49 | red:red,
50 | green:green,
51 | blue:blue,
52 | alpha:0.5
53 | )
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserTests/NSURLExtensionsTest.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import XCTest
23 |
24 | class NSURLExtensionsTest: XCTestCase {
25 |
26 | func testNSURLJSON() {
27 | let json = "{\"test\":\"value\"}".dataUsingEncoding(NSUTF8StringEncoding)!
28 | let base64 = json.base64EncodedDataWithOptions(.EncodingEndLineWithLineFeed)
29 | let data = NSString(data: base64, encoding: NSUTF8StringEncoding)!
30 | let dataURL = NSURL(string:"data:text/plain;base64,\(data)")!
31 | dataURL.withJSONDictionary {
32 | dict in
33 | XCTAssertEqual(dict["test"] ?? "", "value", "Value is as expected")
34 | }
35 | sleep(1)
36 | }
37 | func testNSURLJSONArray() {
38 | let json = "[{\"test\":\"value\"}]".dataUsingEncoding(NSUTF8StringEncoding)!
39 | let base64 = json.base64EncodedDataWithOptions(.EncodingEndLineWithLineFeed)
40 | let data = NSString(data: base64, encoding: NSUTF8StringEncoding)!
41 | let dataURL = NSURL(string:"data:text/plain;base64,\(data)")!
42 | dataURL.withJSONArrayOfDictionary {
43 | dict in
44 | XCTAssertEqual(dict[0]["test"] ?? "", "value", "Value is as expected")
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/Extensions.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | extension NSData {
25 | var utf8string:String {
26 | return String(data:self,encoding:NSUTF8StringEncoding)!
27 | }
28 | }
29 |
30 | extension String {
31 | var utf8data:NSData {
32 | return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
33 | }
34 | func fromHex() -> Int {
35 | var result = 0
36 | for c in self.characters {
37 | result *= 16
38 | switch c {
39 | case "0": result += 0
40 | case "1": result += 1
41 | case "2": result += 2
42 | case "3": result += 3
43 | case "4": result += 4
44 | case "5": result += 5
45 | case "6": result += 6
46 | case "7": result += 7
47 | case "8": result += 8
48 | case "9": result += 9
49 | case "a", "A": result += 10
50 | case "b", "B": result += 11
51 | case "c", "C": result += 12
52 | case "d", "D": result += 13
53 | case "e", "E": result += 14
54 | case "f", "F": result += 15
55 | default: break
56 | }
57 | }
58 | return result;
59 | }
60 | }
61 |
62 | extension Int {
63 | func toHex(digits:Int) -> String {
64 | return String(format:"%0\(digits)x",self)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/RepositoryListController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import WatchKit
23 | import Foundation
24 |
25 | class RepositoryRowController: NSObject {
26 | @IBOutlet weak var name: WKInterfaceLabel!
27 | }
28 | class RepositoryListController: WKInterfaceController {
29 | let delegate = WKExtension.sharedExtension().delegate as! ExtensionDelegate
30 | @IBOutlet weak var repositoriesTable: WKInterfaceTable!
31 | var repos = []
32 | override func awakeWithContext(context: AnyObject?) {
33 | super.awakeWithContext(context)
34 | if let user = context as? String {
35 | delegate.loadReposFor(user) {
36 | result in
37 | self.repositoriesTable.setNumberOfRows(
38 | result.count, withRowType: "repository")
39 | self.repos = result
40 | for (index,repo) in result.enumerate() {
41 | let controller = self.repositoriesTable
42 | .rowControllerAtIndex(index) as! RepositoryRowController
43 | controller.name.setText(repo["name"] ?? "")
44 | }
45 | }
46 | } else {
47 | repos = []
48 | }
49 | }
50 | override func contextForSegueWithIdentifier(
51 | segueIdentifier: String,
52 | inTable table: WKInterfaceTable,
53 | rowIndex: Int) -> AnyObject? {
54 | return repos[rowIndex]
55 | }
56 | }
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/NSURLExtensions.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | func toStringString(dict:[String:AnyObject]) -> [String:String] {
25 | var result:[String:String] = [:]
26 | for (key,value) in dict {
27 | if let valueString = value as? String {
28 | result[key] = valueString
29 | } else {
30 | result[key] = "\(value)"
31 | }
32 | }
33 | return result
34 | }
35 |
36 | extension NSURL {
37 | func withJSONDictionary(fn:[String:String] -> ()) {
38 | let session = NSURLSession.sharedSession()
39 | session.dataTaskWithURL(self) {
40 | data,response,error -> () in
41 | if let json = try? NSJSONSerialization.JSONObjectWithData(
42 | data!, options: .AllowFragments) as? [String:AnyObject] {
43 | fn(toStringString(json!))
44 | } else {
45 | fn([String:String]())
46 | }
47 | }.resume()
48 | }
49 | func withJSONArrayOfDictionary(fn:[[String:String]] -> ()) {
50 | let session = NSURLSession.sharedSession()
51 | session.dataTaskWithURL(self) {
52 | data,response,error -> () in
53 | if let json = try? NSJSONSerialization.JSONObjectWithData(
54 | data!, options: .AllowFragments) as? [[String:AnyObject]] {
55 | fn(json!.map(toStringString))
56 | } else {
57 | fn([[String:String]]())
58 | }
59 | }.resume()
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/exploring/iteration.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env xcrun swift
2 |
3 | for i in 1...12 { // for-in loop over a numeric range
4 | print("i is \(i)") // print out i
5 | }
6 |
7 | for _ in 1...12 { // underscore is a hole - ignored value
8 | print("Looping...") // underscore cannot be read
9 | }
10 |
11 | // Set up data from previously
12 | var shopping = [
13 | "Milk",
14 | "Eggs",
15 | "Coffee",
16 | "Tea",
17 | ]
18 |
19 | var costs = [
20 | "Milk":1,
21 | "Eggs":2,
22 | "Coffee":3,
23 | "Tea":4,
24 | ]
25 |
26 | var cost = 0
27 | for item in shopping { // for-in loop iterates over collection
28 | if let c = costs[item] { // if block uses let in case cost is nil
29 | cost += c // note this is not idiomatic; see below
30 | } // for tuple iteration
31 | }
32 | cost == 10
33 |
34 | Array(costs.keys) // creates a new array based on keys
35 | Array(costs.values) // creates a new array based on values
36 |
37 | for item in costs.keys { // can iterate over keys in a dictionary
38 | print(item)
39 | }
40 |
41 | var (a,b) = (1,2) // tuple assignment; effectively a=1,b=2
42 |
43 | for (item,cost) in costs { // can iterate over key/values together
44 | print("The \(item) " +
45 | "costs \(cost)")
46 | }
47 |
48 | var sum = 0
49 | for var i=0;i<=10;i++ { // can use traditional for loops as well
50 | sum += i // however may be removed in Swift 3
51 | }
52 | sum == 55
53 |
54 | for var i=0,j=10; i<=10 && j >= 0; i++, j-- { // can use many loop variables
55 | print("\(i), \(j)");
56 | }
57 |
58 | // --- break, continue and labels ---
59 |
60 | var deck = [1...13,1...13,1...13,1...13]
61 | suits: for suit in deck { // suit: introduces a label at this for block
62 | for card in suit { // nested for block
63 | if card == 3 {
64 | continue // goes to 'for card in suit' with next card
65 | }
66 | if card == 5 {
67 | continue suits // goes to the 'for suit in deck' with next suit
68 | }
69 | if card == 7 {
70 | break // leaves 'for card in suit' block
71 | }
72 | if card == 13 {
73 | break suits // leaves 'for suit in deck' block
74 | }
75 | }
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/playing/MyPlayground.playground/Pages/Playground Code.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/ExtensionDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import WatchKit
23 |
24 | class ExtensionDelegate: NSObject, WKExtensionDelegate {
25 | var api:GitHubAPI!
26 | var users:[String] = []
27 | var repos:[String:[[String:String]]] = [:]
28 | func loadReposFor(user:String, fn:([[String:String]])->()) {
29 | repos[user] = []
30 | api.withUserRepos(user) {
31 | results in
32 | self.repos[user] = results
33 | fn(results)
34 | }
35 | }
36 | func addUser(user:String) {
37 | users += [user]
38 | users.sortInPlace({ $0 < $1 })
39 | }
40 | func applicationDidFinishLaunching() {
41 | // Perform any final initialization of your application.
42 | api = GitHubAPI.connect()
43 | addUser("alblue")
44 | }
45 | func applicationDidBecomeActive() {
46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
47 | }
48 | func applicationWillResignActive() {
49 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
50 | // Use this method to pause ongoing tasks, disable timers, etc.
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch Extension/InterfaceController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import WatchKit
23 | import Foundation
24 |
25 | class InterfaceController: WKInterfaceController {
26 | let delegate = WKExtension.sharedExtension().delegate as! ExtensionDelegate
27 | @IBOutlet weak var usersTable: WKInterfaceTable!
28 | override func awakeWithContext(context: AnyObject?) {
29 | super.awakeWithContext(context)
30 | // Configure interface objects here.
31 | let users = delegate.users
32 | usersTable.setNumberOfRows(users.count, withRowType: "user")
33 | for (index,user) in users.enumerate() {
34 | let controller = usersTable.rowControllerAtIndex(index) as! UserRowController
35 | controller.name.setText(user)
36 | delegate.api.withUserImage(user) {
37 | image in controller.icon.setImage(image)
38 | }
39 | }
40 | }
41 | override func contextForSegueWithIdentifier(
42 | segueIdentifier: String,
43 | inTable table: WKInterfaceTable,
44 | rowIndex: Int) -> AnyObject? {
45 | return delegate.users[rowIndex]
46 | }
47 | override func willActivate() {
48 | // This method is called when watch view controller is about to be visible to user
49 | super.willActivate()
50 | }
51 | override func didDeactivate() {
52 | // This method is called when watch view controller is no longer visible
53 | super.didDeactivate()
54 | }
55 | }
56 |
57 | class UserRowController: NSObject {
58 | @IBOutlet weak var name: WKInterfaceLabel!
59 | @IBOutlet weak var icon: WKInterfaceImage!
60 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Swift Essentials
2 | ================
3 |
4 | This repository contains source code for the Packt Publishing book
5 | "Swift Essentials" for the first and second editions. Tags and branches
6 | exist for both versions.
7 |
8 | https://www.packtpub.com/application-development/swift-essentials
9 |
10 | Second edition
11 | --------------
12 | * ISBN-10: 1785888870
13 | * ISBN-13: 978-1-78588-887-8
14 |
15 | *Chapters*
16 |
17 | * Chapter 1: [Exploring Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter1)
18 | * Chapter 2: [Playing with Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter2)
19 | * Chapter 3: [Creating an iOS Swift App](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter3)
20 | * Chapter 4: [Storyboard Applications with Swift and iOS](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter4)
21 | * Chapter 5: [Creating Custom Views in Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter5)
22 | * Chapter 6: [Parsing Networked Data](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter6)
23 | * Chapter 7: [Building a Repository Browser](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter7)
24 | * Chapter 8: [Adding Watch Support](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition2/chapter8)
25 |
26 | First edition
27 | -------------
28 | * ISBN-10: 1784396702
29 | * ISBN-13: 978-1-78439-670-1
30 |
31 | *Chapters*
32 |
33 | * Chapter 1: [Exploring Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter1)
34 | * Chapter 2: [Playing with Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter2)
35 | * Chapter 3: [Creating an iOS Swift App](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter3)
36 | * Chapter 4: [Storyboard Applications with Swift and iOS](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter4)
37 | * Chapter 5: [Creating Custom Views in Swift](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter5)
38 | * Chapter 6: [Parsing Networked Data](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter6)
39 | * Chapter 7: [Building a Repository Browser](https://github.com/alblue/com.packtpub.swift.essentials/tree/edition1/chapter7)
40 |
41 | Contact
42 | -------
43 |
44 | Follow me on Twitter or @alblue, or mail alex.blewitt@gmail.com
45 | http://alblue.bandlem.com
46 |
47 | The book website is http://swiftessentials.org and Twitter @swiftessentials
48 |
49 | LICENSE
50 | -------
51 |
52 | Code examples are licensed under the MIT license as contained in the
53 | LICENSE file
54 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/FeedParser.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | class FeedParser: NSObject, NSXMLParserDelegate {
25 | var inEntry:Bool = false
26 | var inTitle:Bool = false
27 | var title:String?
28 | var link:String?
29 | var items:[(String,String)] = []
30 | init(_ data:NSData) {
31 | let parser = NSXMLParser(data: data);
32 | parser.shouldProcessNamespaces = true
33 | super.init()
34 | parser.delegate = self
35 | // If you get an EXC_BAD_ACCESS on the parse()
36 | // line, check your delegate methods are declared
37 | // to allow implicitly unwrapped optionals since
38 | // sometimes these values may be nil
39 | parser.parse()
40 | }
41 | func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName: String?, attributes: [String:String]) {
42 | switch elementName {
43 | case "entry":
44 | inEntry = true
45 | case "title":
46 | inTitle = true
47 | case "link":
48 | link = attributes["href"]
49 | default: break
50 | }
51 | }
52 | func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName: String?) {
53 | switch elementName {
54 | case "entry":
55 | inEntry = false
56 | if title != nil && link != nil {
57 | items += [(title!,link!)]
58 | }
59 | title = nil
60 | link = nil
61 | case "title": inTitle = false
62 | default: break
63 | }
64 | }
65 | func parser(parser: NSXMLParser, foundCharacters string: String) {
66 | if inEntry && inTitle {
67 | title = string
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/RemoteGitRepository.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | class RemoteGitRepository {
25 | let host:String
26 | let repo:String
27 | let port:Int
28 | init(host:String, repo:String, _ port:Int = 9418) {
29 | self.host = host
30 | self.repo = repo
31 | self.port = port
32 | }
33 | func lsRemote() -> [String:String] {
34 | var refs = [String:String]()
35 | if let (input,output) = NSStream.open(host,port) {
36 | output.writePacketLine("git-upload-pack \(repo)\0host=\(host)\0")
37 | while true {
38 | if let response = input.readPacketLineString() {
39 | let hash = String(response.substringToIndex(41))
40 | let ref = String(response.substringFromIndex(41))
41 | if ref.hasPrefix("HEAD") {
42 | continue
43 | } else {
44 | refs[ref] = hash
45 | }
46 | } else {
47 | break
48 | }
49 | }
50 | output.writePacketLine()
51 | input.close()
52 | output.close()
53 | }
54 | return refs
55 | }
56 | func lsRemoteAsync(fn:(String,String) -> ()) {
57 | if let (input,output) = NSStream.connect(host,port) {
58 | input.delegate = PacketLineParser(output) { (response:NSString) -> () in
59 | let hash = String(response.substringToIndex(41))
60 | let ref = String(response.substringFromIndex(41))
61 | if !ref.hasPrefix("HEAD") {
62 | fn(ref,hash)
63 | }
64 | }
65 | input.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
66 | input.open()
67 | output.open()
68 | output.writePacketLine("git-upload-pack \(repo)\0host=\(host)\0")
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/TwoLabels.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class TwoLabels:UIView {
25 | var left:UILabel = UILabel()
26 | var right:UILabel = UILabel()
27 | required init?(coder:NSCoder) {
28 | super.init(coder:coder)
29 | setupView()
30 | }
31 | override init(frame: CGRect) {
32 | super.init(frame:frame)
33 | setupView()
34 | }
35 | func setupView() {
36 | addSubview(left)
37 | addSubview(right)
38 | configureView()
39 | setNeedsUpdateConstraints()
40 | }
41 | func configureView() {
42 | left.text = "Left"
43 | right.text = "Right"
44 | }
45 | override func updateConstraints() {
46 | translatesAutoresizingMaskIntoConstraints = false
47 | left.translatesAutoresizingMaskIntoConstraints = false
48 | right.translatesAutoresizingMaskIntoConstraints = false
49 | removeConstraints(constraints)
50 | // left.width = right.width * 1 + 0
51 | let equalWidths = NSLayoutConstraint(item: left, attribute: .Width, relatedBy: .Equal, toItem: right, attribute: .Width, multiplier: 1, constant: 0)
52 | addConstraint(equalWidths)
53 | let options = NSLayoutFormatOptions()
54 | let namedViews = ["left":left,"right":right]
55 | addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[left]-[right]-|", options: options, metrics:nil, views: namedViews));
56 | addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[left]-|", options: options, metrics:nil, views: namedViews));
57 | addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[right]-|", options: options, metrics:nil, views: namedViews));
58 | super.updateConstraints()
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/StreamExtensions.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | extension NSStream {
25 | class func open(host:String,_ port:Int) -> (NSInputStream, NSOutputStream)? {
26 | if let (input,output) = connect(host,port) {
27 | input.open()
28 | output.open()
29 | return (input,output)
30 | } else {
31 | return nil
32 | }
33 | }
34 | class func connect(host:String,_ port:Int) -> (NSInputStream, NSOutputStream)? {
35 | var input:NSInputStream?
36 | var output:NSOutputStream?
37 | NSStream.getStreamsToHostWithName(host, port: port, inputStream: &input, outputStream: &output)
38 | guard let i = input, o = output else {
39 | return nil
40 | }
41 | return (i,o)
42 | }
43 | }
44 |
45 | extension NSInputStream {
46 | func readBytes(size:Int) -> [UInt8]? {
47 | let buffer = Array(count:size,repeatedValue:0)
48 | var completed = 0
49 | while completed < size {
50 | let read = self.read(UnsafeMutablePointer(buffer) + completed, maxLength: size - completed)
51 | if read < 0 {
52 | return nil
53 | } else {
54 | completed += read
55 | }
56 | }
57 | return buffer
58 | }
59 | func readData(size:Int) -> NSData? {
60 | if let buffer = readBytes(size) {
61 | return NSData(bytes: UnsafeMutablePointer(buffer), length: buffer.count)
62 | } else {
63 | return nil
64 | }
65 | }
66 | }
67 |
68 | extension NSOutputStream {
69 | func writeData(data:NSData) -> Int {
70 | let size = data.length
71 | var completed = 0
72 | while completed < size {
73 | let wrote = write(UnsafePointer(data.bytes) +
74 | completed, maxLength:size - completed)
75 | if wrote < 0 {
76 | return wrote
77 | } else {
78 | completed += wrote
79 | }
80 | }
81 | return completed
82 | }
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/ProgressView.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | @IBDesignable class ProgessView: UIView {
25 | let circle = CAShapeLayer()
26 | let square = CAShapeLayer()
27 | let progress = CAShapeLayer()
28 | @IBInspectable var progressAmount: CGFloat = 0.5 {
29 | didSet {
30 | setNeedsLayout()
31 | }
32 | }
33 | let mask = CAShapeLayer()
34 | let black = UIColor.blackColor().CGColor
35 | required init?(coder: NSCoder) {
36 | super.init(coder:coder)
37 | setupView()
38 | }
39 | override init(frame: CGRect) {
40 | super.init(frame:frame)
41 | setupView()
42 | }
43 | func setupView() {
44 | for layer in [progress, square, circle] {
45 | layer.strokeColor = black
46 | layer.fillColor = nil
47 | self.layer.addSublayer(layer)
48 | }
49 | progress.lineWidth = 10
50 | progress.strokeColor = UIColor.redColor().CGColor
51 | configureView()
52 | }
53 | func configureView() {
54 | let rect = self.bounds
55 | let sq = rect.insetBy(dx: rect.width/3, dy: rect.height/3)
56 | square.fillColor = black
57 | square.path = UIBezierPath(rect: sq).CGPath
58 | circle.path = UIBezierPath(ovalInRect: rect).CGPath
59 | let radius = min(rect.width, rect.height)/2
60 | let center = CGPoint(x: rect.midX, y: rect.midY)
61 | progress.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(-M_PI_2), endAngle: CGFloat(3 * M_PI_2), clockwise: true).CGPath
62 | progress.strokeStart = 0
63 | progress.strokeEnd = progressAmount
64 | mask.path = UIBezierPath(ovalInRect: rect).CGPath
65 | progress.mask = mask
66 | }
67 | override func layoutSubviews() {
68 | setupView()
69 | }
70 | @IBAction func setProgress(sender:AnyObject) {
71 | switch sender {
72 | case let slider as UISlider: progressAmount = CGFloat(slider.value)
73 | case let stepper as UIStepper: progressAmount = CGFloat(stepper.value)
74 | default: break
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/PacketLineParser.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 |
24 | class PacketLineParser: NSObject, NSStreamDelegate {
25 | let output:NSOutputStream
26 | let callback:(NSString)->()
27 | var capture:PacketLineParser?
28 | init(_ output:NSOutputStream, _ callback:(NSString) -> ()) {
29 | self.output = output
30 | self.callback = callback
31 | super.init()
32 | // Since this is stored in an NSInputStream delegate which
33 | // only weakly owns this object, if no other approach is
34 | // taken this object will be thrown away before it receives
35 | // any messages. To avoid this, we create a cyclic reference
36 | // to itself to prevent it being closed, and then handle
37 | // the cleanup when the stream is ended.
38 | capture = self
39 | }
40 | func stream(stream: NSStream, handleEvent: NSStreamEvent) {
41 | let input = stream as! NSInputStream
42 | if handleEvent == NSStreamEvent.HasBytesAvailable {
43 | if let line = input.readPacketLineString() {
44 | callback(line)
45 | } else {
46 | closeStreams(input,output)
47 | }
48 | }
49 | if handleEvent == NSStreamEvent.EndEncountered || handleEvent == NSStreamEvent.ErrorOccurred {
50 | closeStreams(input,output)
51 | }
52 | }
53 | func closeStreams(input:NSInputStream,_ output:NSOutputStream) {
54 | // only run this once
55 | if capture != nil {
56 | // ensure that the capture is released
57 | capture = nil
58 | // remove from run loop
59 | output.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
60 | input.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
61 | // remove any delegates
62 | input.delegate = nil
63 | output.delegate = nil
64 | // close the streams, if they are not closed already
65 | if output.streamStatus != NSStreamStatus.Closed {
66 | // send the other client a close message
67 | output.writePacketLine()
68 | output.close()
69 | }
70 | if input.streamStatus != NSStreamStatus.Closed {
71 | input.close()
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | @UIApplicationMain
25 | class AppDelegate: UIResponder, UIApplicationDelegate {
26 |
27 | var window: UIWindow?
28 |
29 |
30 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
31 | // Override point for customization after application launch.
32 | return true
33 | }
34 |
35 | func applicationWillResignActive(application: UIApplication) {
36 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
37 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
38 | }
39 |
40 | func applicationDidEnterBackground(application: UIApplication) {
41 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
43 | }
44 |
45 | func applicationWillEnterForeground(application: UIApplication) {
46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
47 | }
48 |
49 | func applicationDidBecomeActive(application: UIApplication) {
50 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
51 | }
52 |
53 | func applicationWillTerminate(application: UIApplication) {
54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
55 | }
56 |
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 |
23 | import UIKit
24 |
25 | @UIApplicationMain
26 | class AppDelegate: UIResponder, UIApplicationDelegate {
27 |
28 | var window: UIWindow?
29 |
30 |
31 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
32 | // Override point for customization after application launch.
33 | return true
34 | }
35 |
36 | func applicationWillResignActive(application: UIApplication) {
37 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
38 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
39 | }
40 |
41 | func applicationDidEnterBackground(application: UIApplication) {
42 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
44 | }
45 |
46 | func applicationWillEnterForeground(application: UIApplication) {
47 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
48 | }
49 |
50 | func applicationDidBecomeActive(application: UIApplication) {
51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
52 | }
53 |
54 | func applicationWillTerminate(application: UIApplication) {
55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
56 | }
57 |
58 |
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/SingleView/SingleView/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | @UIApplicationMain
25 | class AppDelegate: UIResponder, UIApplicationDelegate {
26 |
27 | var window: UIWindow?
28 |
29 |
30 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
31 | window = UIWindow()
32 | window?.rootViewController = ViewController()
33 | window?.makeKeyAndVisible()
34 | return true
35 | }
36 |
37 | func applicationWillResignActive(application: UIApplication) {
38 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
39 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
40 | }
41 |
42 | func applicationDidEnterBackground(application: UIApplication) {
43 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
45 | }
46 |
47 | func applicationWillEnterForeground(application: UIApplication) {
48 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
49 | }
50 |
51 | func applicationDidBecomeActive(application: UIApplication) {
52 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
53 | }
54 |
55 | func applicationWillTerminate(application: UIApplication) {
56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
57 | }
58 |
59 |
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/CounterView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SingleView/SingleView/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Storyboards/Storyboards/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/GitHubAPI.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import Foundation
23 | import UIKit
24 |
25 | class GitHubAPI {
26 | let base:NSURL
27 | let services:[String:String]
28 | let cache = NSCache()
29 | class func connect() -> GitHubAPI? {
30 | return connect("https://api.github.com")
31 | }
32 | class func connect(url:String) -> GitHubAPI? {
33 | if let nsurl = NSURL(string:url) {
34 | return connect(nsurl)
35 | } else {
36 | return nil
37 | }
38 | }
39 | class func connect(url:NSURL) -> GitHubAPI? {
40 | if let data = NSData(contentsOfURL:url) {
41 | if let json = try? NSJSONSerialization.JSONObjectWithData(data,options:.AllowFragments) as? [String:String] {
42 | return GitHubAPI(url,json!)
43 | } else {
44 | return nil
45 | }
46 | } else {
47 | return nil
48 | }
49 | }
50 | init(_ base:NSURL, _ services:[String:String]) {
51 | self.base = base
52 | self.services = services
53 | }
54 | func getURLForUserRepos(user:String) -> NSURL {
55 | let key = "r:\(user)"
56 | if let url = cache.objectForKey(key) as? NSURL {
57 | return url
58 | } else {
59 | let userRepositoriesURL = services["user_repositories_url"]!
60 | let userRepositoryURL = URITemplate.replace(userRepositoriesURL, values:["user":user])
61 | let url = NSURL(string:userRepositoryURL, relativeToURL:base)!
62 | cache.setObject(url,forKey:key)
63 | return url
64 | }
65 | }
66 | func withUserRepos(user:String, fn:([[String:String]]) -> ()) {
67 | let key = "repos:\(user)"
68 | if let repos = cache.objectForKey(key) as? [[String:String]] {
69 | fn(repos)
70 | } else {
71 | let url = getURLForUserRepos(user)
72 | url.withJSONArrayOfDictionary {
73 | repos in
74 | self.cache.setObject(repos,forKey:key)
75 | fn(repos)
76 | }
77 | }
78 | }
79 | func getURLForUserInfo(user:String) -> NSURL {
80 | let key = "ui:\(user)"
81 | if let url = cache.objectForKey(key) as? NSURL {
82 | return url
83 | } else {
84 | let userURL = services["user_url"]!
85 | let userSpecificURL = URITemplate.replace(userURL, values:["user":user])
86 | let url = NSURL(string:userSpecificURL, relativeToURL:base)!
87 | cache.setObject(url,forKey:key)
88 | return url
89 | }
90 | }
91 | func withUserImage(user:String, fn:(UIImage -> ())) {
92 | let key = "image:\(user)"
93 | if let image = cache.objectForKey(key) as? UIImage {
94 | fn(image)
95 | } else {
96 | let url = getURLForUserInfo(user)
97 | url.withJSONDictionary {
98 | userInfo in
99 | if let avatar_url = userInfo["avatar_url"] {
100 | if let avatarURL = NSURL(string:avatar_url, relativeToURL:url) {
101 | if let data = NSData(contentsOfURL:avatarURL) {
102 | if let image = UIImage(data: data) {
103 | self.cache.setObject(image,forKey:key)
104 | fn(image)
105 | }
106 | }
107 | }
108 | }
109 | }
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | @UIApplicationMain
25 | class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
26 |
27 | var window: UIWindow?
28 |
29 |
30 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
31 | // Override point for customization after application launch.
32 | let splitViewController = self.window!.rootViewController as! UISplitViewController
33 | let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
34 | navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
35 | splitViewController.delegate = self
36 | return true
37 | }
38 |
39 | func applicationWillResignActive(application: UIApplication) {
40 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
41 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
42 | }
43 |
44 | func applicationDidEnterBackground(application: UIApplication) {
45 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
47 | }
48 |
49 | func applicationWillEnterForeground(application: UIApplication) {
50 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
51 | }
52 |
53 | func applicationDidBecomeActive(application: UIApplication) {
54 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
55 | }
56 |
57 | func applicationWillTerminate(application: UIApplication) {
58 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
59 | }
60 |
61 | // MARK: - Split view
62 |
63 | func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
64 | if let secondaryAsNavController = secondaryViewController as? UINavigationController {
65 | if let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController {
66 | if topAsDetailController.detailItem == nil {
67 | // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
68 | return true
69 | }
70 | }
71 | }
72 | return false
73 | }
74 |
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowser/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | @UIApplicationMain
25 | class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
26 |
27 | var window: UIWindow?
28 | var api:GitHubAPI!
29 | var users:[String] = []
30 | var repos:[String:[[String:String]]] = [:]
31 |
32 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
33 | // Override point for customization after application launch.
34 | let splitViewController = self.window!.rootViewController as! UISplitViewController
35 | let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
36 | navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
37 | splitViewController.delegate = self
38 | api = GitHubAPI.connect("https://raw.githubusercontent.com/alblue/com.packtpub.swift.essentials/master/RepositoryBrowser/api/index.json")
39 | users = [] // or load from NSUserDefaults.standardUserDefaults
40 | return true
41 | }
42 |
43 | func applicationWillResignActive(application: UIApplication) {
44 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
45 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
46 | }
47 |
48 | func applicationDidEnterBackground(application: UIApplication) {
49 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
50 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
51 | }
52 |
53 | func applicationWillEnterForeground(application: UIApplication) {
54 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
55 | }
56 |
57 | func applicationDidBecomeActive(application: UIApplication) {
58 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
59 | }
60 |
61 | func applicationWillTerminate(application: UIApplication) {
62 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
63 | }
64 |
65 | // MARK: - Split view
66 |
67 | func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
68 | return true
69 | }
70 | func loadRepoNamesFor(user:String, fn:([[String:String]])->()) {
71 | repos[user] = []
72 | api.withUserRepos(user) {
73 | results in
74 | self.repos[user] = results
75 | fn(results)
76 | }
77 | }
78 | func addUser(user:String) {
79 | users += [user]
80 | users.sortInPlace({ $0 < $1 })
81 | }
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/MasterDetail/MasterDetail/MasterViewController.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class MasterViewController: UITableViewController {
25 |
26 | var detailViewController: DetailViewController? = nil
27 | var objects = NSMutableArray()
28 |
29 |
30 | override func awakeFromNib() {
31 | super.awakeFromNib()
32 | if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
33 | self.clearsSelectionOnViewWillAppear = false
34 | self.preferredContentSize = CGSize(width: 320.0, height: 600.0)
35 | }
36 | }
37 |
38 | override func viewDidLoad() {
39 | super.viewDidLoad()
40 | // Do any additional setup after loading the view, typically from a nib.
41 | self.navigationItem.leftBarButtonItem = self.editButtonItem()
42 |
43 | let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
44 | self.navigationItem.rightBarButtonItem = addButton
45 | if let split = self.splitViewController {
46 | let controllers = split.viewControllers
47 | self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
48 | }
49 | }
50 |
51 | override func didReceiveMemoryWarning() {
52 | super.didReceiveMemoryWarning()
53 | // Dispose of any resources that can be recreated.
54 | }
55 |
56 | func insertNewObject(sender: AnyObject) {
57 | objects.insertObject(NSDate(), atIndex: 0)
58 | let indexPath = NSIndexPath(forRow: 0, inSection: 0)
59 | self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
60 | }
61 |
62 | // MARK: - Segues
63 |
64 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
65 | if segue.identifier == "showDetail" {
66 | if let indexPath = self.tableView.indexPathForSelectedRow {
67 | let object = objects[indexPath.row] as! NSDate
68 | let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
69 | controller.detailItem = object
70 | controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
71 | controller.navigationItem.leftItemsSupplementBackButton = true
72 | }
73 | }
74 | }
75 |
76 | // MARK: - Table View
77 |
78 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
79 | return 1
80 | }
81 |
82 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
83 | return objects.count
84 | }
85 |
86 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
87 | let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
88 |
89 | let object = objects[indexPath.row] as! NSDate
90 | cell.textLabel!.text = object.description
91 | return cell
92 | }
93 |
94 | override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
95 | // Return false if you do not want the specified item to be editable.
96 | return true
97 | }
98 |
99 | override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
100 | if editingStyle == .Delete {
101 | objects.removeObjectAtIndex(indexPath.row)
102 | tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
103 | } else if editingStyle == .Insert {
104 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
105 | }
106 | }
107 |
108 |
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/CustomViews/CustomViews/SampleTable.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016, Alex Blewitt, Bandlem Ltd
2 | // Copyright (c) 2016, Packt Publishing Ltd
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy
5 | // of this software and associated documentation files (the "Software"), to deal
6 | // in the Software without restriction, including without limitation the rights
7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | // copies of the Software, and to permit persons to whom the Software is
9 | // furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be included in
12 | // all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | // THE SOFTWARE.
21 |
22 | import UIKit
23 |
24 | class SampleTable: UITableViewController {
25 | var items = [
26 | ("First", "A first item"),
27 | ("Second", "A second item"),
28 | ]
29 | required init?(coder: NSCoder) {
30 | super.init(coder:coder)
31 | }
32 | override func viewDidLoad() {
33 | let xib = UINib(nibName:"CounterView",bundle:nil)
34 | let objects = xib.instantiateWithOwner(self, options:nil)
35 | let counter = objects.first as? UIView
36 | tableView.tableHeaderView = counter
37 | let footer = UITableViewHeaderFooterView()
38 | footer.contentView.addSubview(TwoLabels(frame:CGRect.zero))
39 | tableView.tableFooterView = footer
40 | let url = NSURL(string: "https://raw.githubusercontent.com/alblue/com.packtpub.swift.essentials/master/CustomViews/CustomViews/SampleTable.json")!
41 | let session = NSURLSession.sharedSession()
42 | let task = session.dataTaskWithURL(url, completionHandler: {data,response,error -> Void in
43 | guard error == nil else {
44 | self.items += [("Error",error!.localizedDescription)]
45 | return
46 | }
47 | let statusCode = (response as! NSHTTPURLResponse).statusCode
48 | guard statusCode < 500 else {
49 | self.items += [("Server error \(statusCode)",
50 | url.absoluteString)]
51 | return
52 | }
53 | guard statusCode < 400 else {
54 | self.items += [("Client error \(statusCode)",
55 | url.absoluteString)]
56 | return
57 | }
58 | if let parsed = try? NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) as! NSArray {
59 | for entry in parsed {
60 | switch (entry["title"], entry["content"]) {
61 | case (let title as String, let content as String):
62 | self.items += [(title,content)]
63 | default:
64 | self.items += [("Error", "Missing unknown entry")]
65 | }
66 | }
67 | } else {
68 | self.items += [("Error", "JSON is not an array")]
69 | }
70 | self.runOnUIThread {
71 | self.tableView.backgroundColor = UIColor.redColor()
72 | self.tableView.reloadData()
73 | self.tableView.backgroundColor = UIColor.greenColor()
74 | }
75 | })
76 | task.resume()
77 | session.dataTaskWithURL(NSURL(string:"http://alblue.bandlem.com/Tag/swift/atom.xml")!, completionHandler: {data,response,error -> Void in
78 | if let data = data {
79 | self.items += FeedParser(data).items
80 | self.runOnUIThread(self.tableView.reloadData)
81 | }
82 | }).resume()
83 | runOnBackgroundThread {
84 | let repo = RemoteGitRepository(host: "github.com", repo: "/alblue/com.packtpub.swift.essentials.git")
85 | // way of forcing true without compiler warnings of unused code
86 | let async = arc4random() >= 0
87 | if async {
88 | repo.lsRemoteAsync() { (ref:String,hash:String) in
89 | self.items += [(ref,hash)]
90 | self.runOnUIThread(self.tableView.reloadData)
91 | }
92 | } else {
93 | for (ref,hash) in repo.lsRemote() {
94 | self.items += [(ref,hash)]
95 | }
96 | self.runOnUIThread(self.tableView.reloadData)
97 | }
98 | }
99 | }
100 | func runOnBackgroundThread(fn:()->()) {
101 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),fn)
102 | }
103 | func runOnUIThread(fn:()->()) {
104 | if NSThread.isMainThread() {
105 | fn()
106 | } else {
107 | dispatch_async(dispatch_get_main_queue(), fn)
108 | }
109 | }
110 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
111 | return items.count
112 | }
113 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
114 | let (title,subtitle) = items[indexPath.row]
115 | let cell = tableView.dequeueReusableCellWithIdentifier("prototypeCell")!
116 | let titleLabel = cell.viewWithTag(1) as! UILabel
117 | let subtitleLabel = cell.viewWithTag(2) as! UILabel
118 | titleLabel.text = title
119 | subtitleLabel.text = subtitle
120 | return cell
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/RepositoryBrowser/RepositoryBrowserWatch/Base.lproj/Interface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |