├── .github
└── workflows
│ └── manual.yml
├── .gitignore
├── CODEOWNERS
├── LICENSE
├── README.md
├── SoManyBugs.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
└── SoManyBugs
├── AppDelegate.swift
├── Assets.xcassets
├── AppIcon.appiconset
│ ├── Contents.json
│ ├── Icon-40.png
│ ├── Icon-40@2x.png
│ ├── Icon-40@3x.png
│ ├── Icon-60@2x.png
│ ├── Icon-60@3x.png
│ ├── Icon-76.png
│ ├── Icon-76@2x.png
│ ├── Icon-83.5@2x.png
│ ├── Icon-Small.png
│ ├── Icon-Small@2x.png
│ └── Icon-Small@3x.png
├── Contents.json
├── LaunchLogo.imageset
│ ├── Contents.json
│ └── LaunchLogo.pdf
├── back.imageset
│ ├── Contents.json
│ └── back.pdf
├── settings.imageset
│ ├── Contents.json
│ └── settings.pdf
├── spider.imageset
│ ├── Contents.json
│ └── spider.pdf
└── web.imageset
│ ├── Contents.json
│ └── web.pdf
├── Base.lproj
├── LaunchScreen.xib
└── Main.storyboard
├── BreakpointBugViewController.swift
├── BreakpointSettingsViewController.swift
├── BugFactory.swift
├── FinalBugViewController.swift
├── FinalSettingsViewController.swift
├── Images
├── back.pdf
├── settings.pdf
├── spider.pdf
└── web.pdf
├── Info.plist
├── PrintBugViewController.swift
├── PrintSettingsViewController.swift
├── UIColor+BugTheme.swift
├── VisualBugViewController.swift
└── VisualSettingsViewController.swift
/.github/workflows/manual.yml:
--------------------------------------------------------------------------------
1 | # Workflow to ensure whenever a Github PR is submitted,
2 | # a JIRA ticket gets created automatically.
3 | name: Manual Workflow
4 |
5 | # Controls when the action will run.
6 | on:
7 | # Triggers the workflow on pull request events but only for the master branch
8 | pull_request_target:
9 | types: [opened, reopened]
10 |
11 | # Allows you to run this workflow manually from the Actions tab
12 | workflow_dispatch:
13 |
14 | jobs:
15 | test-transition-issue:
16 | name: Convert Github Issue to Jira Issue
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Checkout
20 | uses: actions/checkout@master
21 |
22 | - name: Login
23 | uses: atlassian/gajira-login@master
24 | env:
25 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
26 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
27 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
28 |
29 | - name: Create NEW JIRA ticket
30 | id: create
31 | uses: atlassian/gajira-create@master
32 | with:
33 | project: CONUPDATE
34 | issuetype: Task
35 | summary: |
36 | Github PR [Assign the ND component] | Repo: ${{ github.repository }} | PR# ${{github.event.number}}
37 | description: |
38 | Repo link: https://github.com/${{ github.repository }}
39 | PR no. ${{ github.event.pull_request.number }}
40 | PR title: ${{ github.event.pull_request.title }}
41 | PR description: ${{ github.event.pull_request.description }}
42 | In addition, please resolve other issues, if any.
43 | fields: '{"components": [{"name":"Github PR"}], "customfield_16449":"https://classroom.udacity.com/", "customfield_16450":"Resolve the PR", "labels": ["github"], "priority":{"id": "4"}}'
44 |
45 | - name: Log created issue
46 | run: echo "Issue ${{ steps.create.outputs.issue }} was created"
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
35 | # Ignore those pesky DS_Store files!
36 | .DS_Store
37 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @batmanimal
2 |
3 | * @udacity/active-public-content
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Udacity
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # iOS Debugging
4 |
5 | 
6 |
7 | This repository contains resources for Udacity's iOS Debugging course.
8 |
9 | ## Overview
10 |
11 | iOS Debugging covers the basics of print or "caveman" debugging, debugging with breakpoints, and the new visual debugging tools provided by Xcode. It uses a single, flowing example called SoManyBugs to demonstrate each debugging technique.
12 |
13 | ## Setup
14 |
15 | The SoManyBugs should build and run without any additional setup; however, it is purposefully riddled with runtime bugs that should be solved as you complete the iOS Debugging course.
16 |
17 | ## Maintainers
18 |
19 | @jarrodparkes
20 |
--------------------------------------------------------------------------------
/SoManyBugs.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A9407EB51B9F5EC20053559D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407EB41B9F5EC20053559D /* AppDelegate.swift */; };
11 | A9407EBA1B9F5EC20053559D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A9407EB81B9F5EC20053559D /* Main.storyboard */; };
12 | A9407EBC1B9F5EC20053559D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A9407EBB1B9F5EC20053559D /* Assets.xcassets */; };
13 | A9407ED21B9F61D20053559D /* FinalBugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407EC61B9F61D20053559D /* FinalBugViewController.swift */; };
14 | A9407ED31B9F61D20053559D /* BreakpointBugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407EC71B9F61D20053559D /* BreakpointBugViewController.swift */; };
15 | A9407ED41B9F61D20053559D /* VisualSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407EC81B9F61D20053559D /* VisualSettingsViewController.swift */; };
16 | A9407ED51B9F61D20053559D /* PrintBugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407EC91B9F61D20053559D /* PrintBugViewController.swift */; };
17 | A9407ED61B9F61D20053559D /* VisualBugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECA1B9F61D20053559D /* VisualBugViewController.swift */; };
18 | A9407ED71B9F61D20053559D /* PrintSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECB1B9F61D20053559D /* PrintSettingsViewController.swift */; };
19 | A9407ED81B9F61D20053559D /* BreakpointSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECC1B9F61D20053559D /* BreakpointSettingsViewController.swift */; };
20 | A9407ED91B9F61D20053559D /* FinalSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECD1B9F61D20053559D /* FinalSettingsViewController.swift */; };
21 | A9407EDA1B9F61D20053559D /* BugFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECE1B9F61D20053559D /* BugFactory.swift */; };
22 | A9407EDB1B9F61D20053559D /* UIColor+BugTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9407ECF1B9F61D20053559D /* UIColor+BugTheme.swift */; };
23 | A9407EE31B9F61E20053559D /* back.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9407EDF1B9F61E20053559D /* back.pdf */; };
24 | A9407EE41B9F61E20053559D /* settings.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9407EE01B9F61E20053559D /* settings.pdf */; };
25 | A9407EE51B9F61E20053559D /* spider.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9407EE11B9F61E20053559D /* spider.pdf */; };
26 | A9407EE61B9F61E20053559D /* web.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9407EE21B9F61E20053559D /* web.pdf */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXFileReference section */
30 | A9407EB11B9F5EC20053559D /* SoManyBugs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SoManyBugs.app; sourceTree = BUILT_PRODUCTS_DIR; };
31 | A9407EB41B9F5EC20053559D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
32 | A9407EB91B9F5EC20053559D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
33 | A9407EBB1B9F5EC20053559D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
34 | A9407EC01B9F5EC20053559D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
35 | A9407EC61B9F61D20053559D /* FinalBugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FinalBugViewController.swift; sourceTree = ""; };
36 | A9407EC71B9F61D20053559D /* BreakpointBugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreakpointBugViewController.swift; sourceTree = ""; };
37 | A9407EC81B9F61D20053559D /* VisualSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisualSettingsViewController.swift; sourceTree = ""; };
38 | A9407EC91B9F61D20053559D /* PrintBugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrintBugViewController.swift; sourceTree = ""; };
39 | A9407ECA1B9F61D20053559D /* VisualBugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisualBugViewController.swift; sourceTree = ""; };
40 | A9407ECB1B9F61D20053559D /* PrintSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrintSettingsViewController.swift; sourceTree = ""; };
41 | A9407ECC1B9F61D20053559D /* BreakpointSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreakpointSettingsViewController.swift; sourceTree = ""; };
42 | A9407ECD1B9F61D20053559D /* FinalSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FinalSettingsViewController.swift; sourceTree = ""; };
43 | A9407ECE1B9F61D20053559D /* BugFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugFactory.swift; sourceTree = ""; };
44 | A9407ECF1B9F61D20053559D /* UIColor+BugTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+BugTheme.swift"; sourceTree = ""; };
45 | A9407EDF1B9F61E20053559D /* back.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = back.pdf; path = Images/back.pdf; sourceTree = ""; };
46 | A9407EE01B9F61E20053559D /* settings.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = settings.pdf; path = Images/settings.pdf; sourceTree = ""; };
47 | A9407EE11B9F61E20053559D /* spider.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = spider.pdf; path = Images/spider.pdf; sourceTree = ""; };
48 | A9407EE21B9F61E20053559D /* web.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = web.pdf; path = Images/web.pdf; sourceTree = ""; };
49 | A9E4C7EB1D1AB2AC0070ADD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | A9407EAE1B9F5EC20053559D /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | );
58 | runOnlyForDeploymentPostprocessing = 0;
59 | };
60 | /* End PBXFrameworksBuildPhase section */
61 |
62 | /* Begin PBXGroup section */
63 | A9407EA81B9F5EC20053559D = {
64 | isa = PBXGroup;
65 | children = (
66 | A9407EB31B9F5EC20053559D /* SoManyBugs */,
67 | A9407EB21B9F5EC20053559D /* Products */,
68 | );
69 | sourceTree = "";
70 | };
71 | A9407EB21B9F5EC20053559D /* Products */ = {
72 | isa = PBXGroup;
73 | children = (
74 | A9407EB11B9F5EC20053559D /* SoManyBugs.app */,
75 | );
76 | name = Products;
77 | sourceTree = "";
78 | };
79 | A9407EB31B9F5EC20053559D /* SoManyBugs */ = {
80 | isa = PBXGroup;
81 | children = (
82 | A9407EB41B9F5EC20053559D /* AppDelegate.swift */,
83 | A9407ECE1B9F61D20053559D /* BugFactory.swift */,
84 | A9407ECF1B9F61D20053559D /* UIColor+BugTheme.swift */,
85 | A9407EE71B9F622C0053559D /* Controllers */,
86 | A9407EEC1B9F62B30053559D /* Supporting Files */,
87 | );
88 | path = SoManyBugs;
89 | sourceTree = "";
90 | };
91 | A9407EDE1B9F61D80053559D /* Images */ = {
92 | isa = PBXGroup;
93 | children = (
94 | A9407EDF1B9F61E20053559D /* back.pdf */,
95 | A9407EE01B9F61E20053559D /* settings.pdf */,
96 | A9407EE11B9F61E20053559D /* spider.pdf */,
97 | A9407EE21B9F61E20053559D /* web.pdf */,
98 | );
99 | name = Images;
100 | sourceTree = "";
101 | };
102 | A9407EE71B9F622C0053559D /* Controllers */ = {
103 | isa = PBXGroup;
104 | children = (
105 | A9407EE81B9F62350053559D /* Print */,
106 | A9407EE91B9F623A0053559D /* Breakpoint */,
107 | A9407EEA1B9F62400053559D /* Visual */,
108 | A9407EEB1B9F62440053559D /* Final */,
109 | );
110 | name = Controllers;
111 | sourceTree = "";
112 | };
113 | A9407EE81B9F62350053559D /* Print */ = {
114 | isa = PBXGroup;
115 | children = (
116 | A9407EC91B9F61D20053559D /* PrintBugViewController.swift */,
117 | A9407ECB1B9F61D20053559D /* PrintSettingsViewController.swift */,
118 | );
119 | name = Print;
120 | sourceTree = "";
121 | };
122 | A9407EE91B9F623A0053559D /* Breakpoint */ = {
123 | isa = PBXGroup;
124 | children = (
125 | A9407EC71B9F61D20053559D /* BreakpointBugViewController.swift */,
126 | A9407ECC1B9F61D20053559D /* BreakpointSettingsViewController.swift */,
127 | );
128 | name = Breakpoint;
129 | sourceTree = "";
130 | };
131 | A9407EEA1B9F62400053559D /* Visual */ = {
132 | isa = PBXGroup;
133 | children = (
134 | A9407ECA1B9F61D20053559D /* VisualBugViewController.swift */,
135 | A9407EC81B9F61D20053559D /* VisualSettingsViewController.swift */,
136 | );
137 | name = Visual;
138 | sourceTree = "";
139 | };
140 | A9407EEB1B9F62440053559D /* Final */ = {
141 | isa = PBXGroup;
142 | children = (
143 | A9407EC61B9F61D20053559D /* FinalBugViewController.swift */,
144 | A9407ECD1B9F61D20053559D /* FinalSettingsViewController.swift */,
145 | );
146 | name = Final;
147 | sourceTree = "";
148 | };
149 | A9407EEC1B9F62B30053559D /* Supporting Files */ = {
150 | isa = PBXGroup;
151 | children = (
152 | A9407EDE1B9F61D80053559D /* Images */,
153 | A9407EB81B9F5EC20053559D /* Main.storyboard */,
154 | A9E4C7EA1D1AB2AC0070ADD7 /* LaunchScreen.xib */,
155 | A9407EBB1B9F5EC20053559D /* Assets.xcassets */,
156 | A9407EC01B9F5EC20053559D /* Info.plist */,
157 | );
158 | name = "Supporting Files";
159 | sourceTree = "";
160 | };
161 | /* End PBXGroup section */
162 |
163 | /* Begin PBXNativeTarget section */
164 | A9407EB01B9F5EC20053559D /* SoManyBugs */ = {
165 | isa = PBXNativeTarget;
166 | buildConfigurationList = A9407EC31B9F5EC20053559D /* Build configuration list for PBXNativeTarget "SoManyBugs" */;
167 | buildPhases = (
168 | A9407EAD1B9F5EC20053559D /* Sources */,
169 | A9407EAE1B9F5EC20053559D /* Frameworks */,
170 | A9407EAF1B9F5EC20053559D /* Resources */,
171 | );
172 | buildRules = (
173 | );
174 | dependencies = (
175 | );
176 | name = SoManyBugs;
177 | productName = SoManyBugs;
178 | productReference = A9407EB11B9F5EC20053559D /* SoManyBugs.app */;
179 | productType = "com.apple.product-type.application";
180 | };
181 | /* End PBXNativeTarget section */
182 |
183 | /* Begin PBXProject section */
184 | A9407EA91B9F5EC20053559D /* Project object */ = {
185 | isa = PBXProject;
186 | attributes = {
187 | LastUpgradeCheck = 1020;
188 | ORGANIZATIONNAME = Udacity;
189 | TargetAttributes = {
190 | A9407EB01B9F5EC20053559D = {
191 | CreatedOnToolsVersion = 7.0;
192 | LastSwiftMigration = 1020;
193 | };
194 | };
195 | };
196 | buildConfigurationList = A9407EAC1B9F5EC20053559D /* Build configuration list for PBXProject "SoManyBugs" */;
197 | compatibilityVersion = "Xcode 3.2";
198 | developmentRegion = en;
199 | hasScannedForEncodings = 0;
200 | knownRegions = (
201 | en,
202 | Base,
203 | );
204 | mainGroup = A9407EA81B9F5EC20053559D;
205 | productRefGroup = A9407EB21B9F5EC20053559D /* Products */;
206 | projectDirPath = "";
207 | projectRoot = "";
208 | targets = (
209 | A9407EB01B9F5EC20053559D /* SoManyBugs */,
210 | );
211 | };
212 | /* End PBXProject section */
213 |
214 | /* Begin PBXResourcesBuildPhase section */
215 | A9407EAF1B9F5EC20053559D /* Resources */ = {
216 | isa = PBXResourcesBuildPhase;
217 | buildActionMask = 2147483647;
218 | files = (
219 | A9407EE61B9F61E20053559D /* web.pdf in Resources */,
220 | A9407EE51B9F61E20053559D /* spider.pdf in Resources */,
221 | A9407EE31B9F61E20053559D /* back.pdf in Resources */,
222 | A9407EBC1B9F5EC20053559D /* Assets.xcassets in Resources */,
223 | A9407EBA1B9F5EC20053559D /* Main.storyboard in Resources */,
224 | A9407EE41B9F61E20053559D /* settings.pdf in Resources */,
225 | );
226 | runOnlyForDeploymentPostprocessing = 0;
227 | };
228 | /* End PBXResourcesBuildPhase section */
229 |
230 | /* Begin PBXSourcesBuildPhase section */
231 | A9407EAD1B9F5EC20053559D /* Sources */ = {
232 | isa = PBXSourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | A9407ED41B9F61D20053559D /* VisualSettingsViewController.swift in Sources */,
236 | A9407ED31B9F61D20053559D /* BreakpointBugViewController.swift in Sources */,
237 | A9407ED71B9F61D20053559D /* PrintSettingsViewController.swift in Sources */,
238 | A9407ED81B9F61D20053559D /* BreakpointSettingsViewController.swift in Sources */,
239 | A9407EB51B9F5EC20053559D /* AppDelegate.swift in Sources */,
240 | A9407EDB1B9F61D20053559D /* UIColor+BugTheme.swift in Sources */,
241 | A9407ED21B9F61D20053559D /* FinalBugViewController.swift in Sources */,
242 | A9407ED51B9F61D20053559D /* PrintBugViewController.swift in Sources */,
243 | A9407EDA1B9F61D20053559D /* BugFactory.swift in Sources */,
244 | A9407ED91B9F61D20053559D /* FinalSettingsViewController.swift in Sources */,
245 | A9407ED61B9F61D20053559D /* VisualBugViewController.swift in Sources */,
246 | );
247 | runOnlyForDeploymentPostprocessing = 0;
248 | };
249 | /* End PBXSourcesBuildPhase section */
250 |
251 | /* Begin PBXVariantGroup section */
252 | A9407EB81B9F5EC20053559D /* Main.storyboard */ = {
253 | isa = PBXVariantGroup;
254 | children = (
255 | A9407EB91B9F5EC20053559D /* Base */,
256 | );
257 | name = Main.storyboard;
258 | sourceTree = "";
259 | };
260 | A9E4C7EA1D1AB2AC0070ADD7 /* LaunchScreen.xib */ = {
261 | isa = PBXVariantGroup;
262 | children = (
263 | A9E4C7EB1D1AB2AC0070ADD7 /* Base */,
264 | );
265 | name = LaunchScreen.xib;
266 | sourceTree = "";
267 | };
268 | /* End PBXVariantGroup section */
269 |
270 | /* Begin XCBuildConfiguration section */
271 | A9407EC11B9F5EC20053559D /* Debug */ = {
272 | isa = XCBuildConfiguration;
273 | buildSettings = {
274 | ALWAYS_SEARCH_USER_PATHS = NO;
275 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
276 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
277 | CLANG_CXX_LIBRARY = "libc++";
278 | CLANG_ENABLE_MODULES = YES;
279 | CLANG_ENABLE_OBJC_ARC = YES;
280 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
281 | CLANG_WARN_BOOL_CONVERSION = YES;
282 | CLANG_WARN_COMMA = YES;
283 | CLANG_WARN_CONSTANT_CONVERSION = YES;
284 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
286 | CLANG_WARN_EMPTY_BODY = YES;
287 | CLANG_WARN_ENUM_CONVERSION = YES;
288 | CLANG_WARN_INFINITE_RECURSION = YES;
289 | CLANG_WARN_INT_CONVERSION = YES;
290 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
291 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
292 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
293 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
294 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
295 | CLANG_WARN_STRICT_PROTOTYPES = YES;
296 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
297 | CLANG_WARN_UNREACHABLE_CODE = YES;
298 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
299 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
300 | COPY_PHASE_STRIP = NO;
301 | DEBUG_INFORMATION_FORMAT = dwarf;
302 | ENABLE_STRICT_OBJC_MSGSEND = YES;
303 | ENABLE_TESTABILITY = YES;
304 | GCC_C_LANGUAGE_STANDARD = gnu99;
305 | GCC_DYNAMIC_NO_PIC = NO;
306 | GCC_NO_COMMON_BLOCKS = YES;
307 | GCC_OPTIMIZATION_LEVEL = 0;
308 | GCC_PREPROCESSOR_DEFINITIONS = (
309 | "DEBUG=1",
310 | "$(inherited)",
311 | );
312 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
313 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
314 | GCC_WARN_UNDECLARED_SELECTOR = YES;
315 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
316 | GCC_WARN_UNUSED_FUNCTION = YES;
317 | GCC_WARN_UNUSED_VARIABLE = YES;
318 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
319 | MTL_ENABLE_DEBUG_INFO = YES;
320 | ONLY_ACTIVE_ARCH = YES;
321 | SDKROOT = iphoneos;
322 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
323 | TARGETED_DEVICE_FAMILY = "1,2";
324 | };
325 | name = Debug;
326 | };
327 | A9407EC21B9F5EC20053559D /* Release */ = {
328 | isa = XCBuildConfiguration;
329 | buildSettings = {
330 | ALWAYS_SEARCH_USER_PATHS = NO;
331 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
332 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
333 | CLANG_CXX_LIBRARY = "libc++";
334 | CLANG_ENABLE_MODULES = YES;
335 | CLANG_ENABLE_OBJC_ARC = YES;
336 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
337 | CLANG_WARN_BOOL_CONVERSION = YES;
338 | CLANG_WARN_COMMA = YES;
339 | CLANG_WARN_CONSTANT_CONVERSION = YES;
340 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
341 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
342 | CLANG_WARN_EMPTY_BODY = YES;
343 | CLANG_WARN_ENUM_CONVERSION = YES;
344 | CLANG_WARN_INFINITE_RECURSION = YES;
345 | CLANG_WARN_INT_CONVERSION = YES;
346 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
347 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
348 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
351 | CLANG_WARN_STRICT_PROTOTYPES = YES;
352 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
353 | CLANG_WARN_UNREACHABLE_CODE = YES;
354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
355 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
356 | COPY_PHASE_STRIP = NO;
357 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
358 | ENABLE_NS_ASSERTIONS = NO;
359 | ENABLE_STRICT_OBJC_MSGSEND = YES;
360 | GCC_C_LANGUAGE_STANDARD = gnu99;
361 | GCC_NO_COMMON_BLOCKS = YES;
362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
364 | GCC_WARN_UNDECLARED_SELECTOR = YES;
365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
366 | GCC_WARN_UNUSED_FUNCTION = YES;
367 | GCC_WARN_UNUSED_VARIABLE = YES;
368 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
369 | MTL_ENABLE_DEBUG_INFO = NO;
370 | SDKROOT = iphoneos;
371 | TARGETED_DEVICE_FAMILY = "1,2";
372 | VALIDATE_PRODUCT = YES;
373 | };
374 | name = Release;
375 | };
376 | A9407EC41B9F5EC20053559D /* Debug */ = {
377 | isa = XCBuildConfiguration;
378 | buildSettings = {
379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
380 | INFOPLIST_FILE = SoManyBugs/Info.plist;
381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
382 | PRODUCT_BUNDLE_IDENTIFIER = com.udacity.SoManyBugs;
383 | PRODUCT_NAME = "$(TARGET_NAME)";
384 | SWIFT_VERSION = 5.0;
385 | };
386 | name = Debug;
387 | };
388 | A9407EC51B9F5EC20053559D /* Release */ = {
389 | isa = XCBuildConfiguration;
390 | buildSettings = {
391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
392 | INFOPLIST_FILE = SoManyBugs/Info.plist;
393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
394 | PRODUCT_BUNDLE_IDENTIFIER = com.udacity.SoManyBugs;
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
397 | SWIFT_VERSION = 5.0;
398 | };
399 | name = Release;
400 | };
401 | /* End XCBuildConfiguration section */
402 |
403 | /* Begin XCConfigurationList section */
404 | A9407EAC1B9F5EC20053559D /* Build configuration list for PBXProject "SoManyBugs" */ = {
405 | isa = XCConfigurationList;
406 | buildConfigurations = (
407 | A9407EC11B9F5EC20053559D /* Debug */,
408 | A9407EC21B9F5EC20053559D /* Release */,
409 | );
410 | defaultConfigurationIsVisible = 0;
411 | defaultConfigurationName = Release;
412 | };
413 | A9407EC31B9F5EC20053559D /* Build configuration list for PBXNativeTarget "SoManyBugs" */ = {
414 | isa = XCConfigurationList;
415 | buildConfigurations = (
416 | A9407EC41B9F5EC20053559D /* Debug */,
417 | A9407EC51B9F5EC20053559D /* Release */,
418 | );
419 | defaultConfigurationIsVisible = 0;
420 | defaultConfigurationName = Release;
421 | };
422 | /* End XCConfigurationList section */
423 | };
424 | rootObject = A9407EA91B9F5EC20053559D /* Project object */;
425 | }
426 |
--------------------------------------------------------------------------------
/SoManyBugs.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SoManyBugs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SoManyBugs/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/16/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - AppDelegate: UIResponder, UIApplicationDelegate
12 |
13 | @UIApplicationMain
14 | class AppDelegate: UIResponder, UIApplicationDelegate {
15 |
16 | // MARK: Properties
17 |
18 | var window: UIWindow?
19 |
20 | // MARK: UIApplicationDelegate Methods
21 |
22 | func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
23 | return true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x",
7 | "filename" : "Icon-Small@2x.png"
8 | },
9 | {
10 | "idiom" : "iphone",
11 | "size" : "29x29",
12 | "scale" : "3x",
13 | "filename" : "Icon-Small@3x.png"
14 | },
15 | {
16 | "idiom" : "iphone",
17 | "size" : "40x40",
18 | "scale" : "2x",
19 | "filename" : "Icon-40@2x.png"
20 | },
21 | {
22 | "idiom" : "iphone",
23 | "size" : "40x40",
24 | "scale" : "3x",
25 | "filename" : "Icon-40@3x.png"
26 | },
27 | {
28 | "idiom" : "iphone",
29 | "size" : "60x60",
30 | "scale" : "2x",
31 | "filename" : "Icon-60@2x.png"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "3x",
37 | "filename" : "Icon-60@3x.png"
38 | },
39 | {
40 | "idiom" : "ipad",
41 | "size" : "29x29",
42 | "scale" : "1x",
43 | "filename" : "Icon-Small.png"
44 | },
45 | {
46 | "idiom" : "ipad",
47 | "size" : "29x29",
48 | "scale" : "2x",
49 | "filename" : "Icon-Small@2x.png"
50 | },
51 | {
52 | "idiom" : "ipad",
53 | "size" : "40x40",
54 | "scale" : "1x",
55 | "filename" : "Icon-40.png"
56 | },
57 | {
58 | "idiom" : "ipad",
59 | "size" : "40x40",
60 | "scale" : "2x",
61 | "filename" : "Icon-40@2x.png"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "76x76",
66 | "scale" : "1x",
67 | "filename" : "Icon-76.png"
68 | },
69 | {
70 | "idiom" : "ipad",
71 | "size" : "76x76",
72 | "scale" : "2x",
73 | "filename" : "Icon-76@2x.png"
74 | },
75 | {
76 | "idiom" : "ipad",
77 | "size" : "83.5x83.5",
78 | "scale" : "2x",
79 | "filename" : "Icon-83.5@2x.png"
80 | }
81 | ],
82 | "info" : {
83 | "version" : 1,
84 | "author" : "makeappicon"
85 | }
86 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/LaunchLogo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchLogo.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/LaunchLogo.imageset/LaunchLogo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/LaunchLogo.imageset/LaunchLogo.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "back.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/back.imageset/back.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/back.imageset/back.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/settings.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "settings.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/settings.imageset/settings.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/settings.imageset/settings.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/spider.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "spider.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode",
11 | "template-rendering-intent" : "template"
12 | }
13 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/spider.imageset/spider.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/spider.imageset/spider.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/web.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "web.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode",
11 | "template-rendering-intent" : "template"
12 | }
13 | }
--------------------------------------------------------------------------------
/SoManyBugs/Assets.xcassets/web.imageset/web.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Assets.xcassets/web.imageset/web.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SoManyBugs/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
36 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
63 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
139 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
216 |
225 |
234 |
243 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
350 |
359 |
368 |
377 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
484 |
493 |
502 |
511 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
618 |
627 |
636 |
645 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
742 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
807 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
872 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
--------------------------------------------------------------------------------
/SoManyBugs/BreakpointBugViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BreakpointBugViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/16/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - BreakpointBugViewController: UIViewController
12 |
13 | class BreakpointBugViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 | let maxBugs = 0
19 | let moveDuration = 3.0
20 | let disperseDuration = 1.0
21 | var bugs = [UIImageView]()
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
28 | view.addGestureRecognizer(singleTapRecognizer)
29 | }
30 |
31 | // MARK: Bug Functions
32 |
33 | func addBugToView() {
34 | if bugs.count < maxBugs {
35 | let newBug = bugFactory.createBug()
36 | bugs.append(newBug)
37 | moveBugsAnimation()
38 | }
39 | }
40 |
41 | func emptyBugsFromView() {
42 | for bug in self.bugs {
43 | bug.removeFromSuperview()
44 | }
45 | self.bugs.removeAll(keepingCapacity: true)
46 | }
47 |
48 | // MARK: View Animations
49 |
50 | func moveBugsAnimation() {
51 | UIView.animate(withDuration: moveDuration) {
52 | for bug in self.bugs {
53 | let randomPosition = CGPoint(x: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxX - bug.frame.size.width))) + UInt32(bug.frame.size.width/2)), y: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxY - bug.frame.size.height))) + UInt32(bug.frame.size.height/2)))
54 | bug.frame = CGRect(x: randomPosition.x - bug.frame.size.width/1.5, y: randomPosition.y - bug.frame.size.height/1.5, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
55 | }
56 | }
57 | addBugToView()
58 | }
59 |
60 | func disperseBugsAnimation() {
61 | UIView.animate(withDuration: disperseDuration, animations: { () -> Void in
62 | for bug in self.bugs {
63 | let offScreenPosition = CGPoint(x: (bug.center.x - self.view.center.x) * 20, y: (bug.center.y - self.view.center.y) * 20)
64 | bug.frame = CGRect(x: offScreenPosition.x, y: offScreenPosition.y, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
65 | }
66 | }, completion: { (finished) -> Void in
67 | if finished { self.emptyBugsFromView() }
68 | })
69 | }
70 |
71 | // MARK: Actions
72 |
73 | @IBAction func popToMasterView() {
74 | let _ = navigationController?.popToRootViewController(animated: true)
75 | }
76 | }
77 |
78 | // MARK: - BreakpointBugViewController (UIResponder)
79 |
80 | extension BreakpointBugViewController {
81 | override var canBecomeFirstResponder: Bool { return true }
82 | override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
83 | if motion == .motionShake { disperseBugsAnimation() }
84 | }
85 | @objc func handleSingleTap(_ recognizer: UITapGestureRecognizer) {
86 | addBugToView()
87 | addBugToView()
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/SoManyBugs/BreakpointSettingsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BreakpointSettingsViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - BreakpointSettingsViewController: UIViewController
12 |
13 | class BreakpointSettingsViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 |
19 | // MARK: Outlets
20 |
21 | @IBOutlet weak var currentBugTypeImageView: UIImageView!
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | currentBugTypeImageView.tintColor = BugFactory.bugTints[bugFactory.currentBugType.rawValue]
28 | }
29 |
30 | // MARK: - Actions
31 |
32 | @IBAction func dismissSettingsTouched(_ sender: AnyObject) {
33 | self.dismiss(animated: true, completion: nil)
34 | }
35 |
36 | @IBAction func bugTypeSelected(_ sender: UIButton) {
37 | bugFactory.currentBugType = BugFactory.BugType(rawValue: Int(sender.currentTitle!)!)!
38 | self.dismiss(animated: true, completion: nil)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/SoManyBugs/BugFactory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BugFactory.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Foundation
11 |
12 | // MARK: - BugFactory
13 |
14 | class BugFactory {
15 |
16 | // MARK: Properties
17 |
18 | static let bugTints: [UIColor] = [.black, .brightBlueColor, .brightRedColor, .brightGreenColor]
19 | static let shakeRotations = [Double.pi/16, Double.pi/8, Double.pi/8, Double.pi/24]
20 | static let shakeDurations = [0.3, 3.0, 0.1, 0.5]
21 | static let bugSize = CGSize(width: 128, height: 128)
22 |
23 | enum BugType: Int {
24 | case basic, slow, fast, smooth
25 | }
26 |
27 | var currentBugType = BugType.basic
28 |
29 | // MARK: Create Bug
30 |
31 | func createBug() -> UIImageView {
32 | let bug = UIImageView(frame: CGRect(x: -100, y: -100, width: 128, height: 128))
33 | bug.image = UIImage(named: "spider")
34 | bug.tintColor = BugFactory.bugTints[currentBugType.rawValue]
35 |
36 | // add simple "shake" key-frame animation
37 | // for explanation, see http://www.objc.io/issue-12/animations-explained.html
38 | let shakeAnimation = CABasicAnimation(keyPath: "transform.rotation")
39 | shakeAnimation.toValue = 0.0
40 | shakeAnimation.fromValue = BugFactory.shakeRotations[currentBugType.rawValue]
41 | shakeAnimation.duration = BugFactory.shakeDurations[currentBugType.rawValue]
42 | shakeAnimation.repeatCount = Float.infinity
43 | shakeAnimation.autoreverses = true
44 | shakeAnimation.isRemovedOnCompletion = false
45 | bug.layer.add(shakeAnimation, forKey: "shake")
46 |
47 | return bug
48 | }
49 |
50 | // MARK: Shared Instance
51 |
52 | class func sharedInstance() -> BugFactory {
53 |
54 | struct Singleton {
55 | static var sharedInstance = BugFactory()
56 | }
57 |
58 | return Singleton.sharedInstance
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/SoManyBugs/FinalBugViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FinalBugViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/16/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - FinalBugViewController: UIViewController
12 |
13 | class FinalBugViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 | let maxBugs = 100
19 | let moveDuration = 3.0
20 | let disperseDuration = 1.0
21 | var bugs = [UIImageView]()
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
28 | view.addGestureRecognizer(singleTapRecognizer)
29 | }
30 |
31 | // MARK: Bug Functions
32 |
33 | func addBugToView() {
34 | if bugs.count < maxBugs {
35 | let newBug = bugFactory.createBug()
36 | bugs.append(newBug)
37 | view.addSubview(newBug)
38 | moveBugsAnimation()
39 | }
40 | }
41 |
42 | func emptyBugsFromView() {
43 | for bug in self.bugs {
44 | bug.removeFromSuperview()
45 | }
46 | self.bugs.removeAll(keepingCapacity: true)
47 | }
48 |
49 | // MARK: View Animations
50 |
51 | func moveBugsAnimation() {
52 | UIView.animate(withDuration: moveDuration) {
53 | for bug in self.bugs {
54 | let randomPosition = CGPoint(x: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxX - bug.frame.size.width))) + UInt32(bug.frame.size.width/2)), y: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxY - bug.frame.size.height))) + UInt32(bug.frame.size.height/2)))
55 | bug.frame = CGRect(x: randomPosition.x - bug.frame.size.width/1.5, y: randomPosition.y - bug.frame.size.height/1.5, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
56 | }
57 | }
58 | }
59 |
60 | func disperseBugsAnimation() {
61 | UIView.animate(withDuration: disperseDuration, animations: { () -> Void in
62 | for bug in self.bugs {
63 | let offScreenPosition = CGPoint(x: (bug.center.x - self.view.center.x) * 20, y: (bug.center.y - self.view.center.y) * 20)
64 | bug.frame = CGRect(x: offScreenPosition.x, y: offScreenPosition.y, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
65 | }
66 | }, completion: { (finished) -> Void in
67 | if finished { self.emptyBugsFromView() }
68 | })
69 | }
70 |
71 | // MARK: Actions
72 |
73 | @IBAction func popToMasterView() {
74 | self.navigationController!.popToRootViewController(animated: true)
75 | }
76 | }
77 |
78 | // MARK: - FinalBugViewController (UIResponder)
79 |
80 | extension FinalBugViewController {
81 | override var canBecomeFirstResponder: Bool { return true }
82 | override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
83 | if motion == .motionShake { disperseBugsAnimation() }
84 | }
85 | @objc func handleSingleTap(_ recognizer: UITapGestureRecognizer) { addBugToView() }
86 | }
87 |
88 | // MARK: - FinalBugViewController (CustomStringConvertible)
89 |
90 | // NOTE: You don't have to conform to CustomStringConvertible since this is already done by FinalBugViewController's superclasses (via NSObject).
91 |
92 | extension FinalBugViewController {
93 |
94 | override var description: String {
95 | return "FinalBugViewController contains \(bugs.count) bugs\n"
96 | }
97 |
98 | }
99 |
100 | // MARK: - FinalBugViewController (CustomDebugStringConvertible)
101 |
102 | // NOTE: You don't have to conform to CustomDebugStringConvertible since this is already done by FinalBugViewController's superclasses (via NSObject).
103 |
104 | extension FinalBugViewController {
105 |
106 | override var debugDescription: String {
107 | var index = 0
108 | var debugString = "FinalBugViewController contains \(bugs.count) bugs...\n"
109 | for bug in bugs {
110 | debugString = debugString + "Bug\(index): \(bug.frame)\n"
111 | index += 1
112 | }
113 | return debugString
114 | }
115 | }
116 |
117 | // MARK: - FinalBugViewController (debugQuickLookObject)
118 |
119 | extension FinalBugViewController {
120 |
121 | func debugQuickLookObject() -> AnyObject? {
122 |
123 | let singleSquareLength: CGFloat = 10.0
124 | let squaresInRow = 10
125 | let imageSize = CGSize(width: singleSquareLength * CGFloat(squaresInRow), height: singleSquareLength * CGFloat(bugs.count / squaresInRow + 1))
126 |
127 | UIGraphicsBeginImageContextWithOptions(imageSize, true, 0)
128 | var x: CGFloat = 0.0
129 | var y: CGFloat = 0.0
130 | for bug in bugs {
131 | bug.tintColor.set()
132 | UIRectFill(CGRect(x: x, y: y, width: singleSquareLength, height: singleSquareLength))
133 | x += singleSquareLength
134 | if x > CGFloat(squaresInRow) * singleSquareLength {
135 | y += singleSquareLength
136 | x = 0.0
137 | }
138 | }
139 | UIColor.yellow.set()
140 | UIRectFill(CGRect(x: x, y: y, width: singleSquareLength, height: singleSquareLength))
141 | let image = UIGraphicsGetImageFromCurrentImageContext()
142 | UIGraphicsEndImageContext()
143 |
144 | return image
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/SoManyBugs/FinalSettingsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FinalSettingsViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - FinalSettingsViewController: UIViewController
12 |
13 | class FinalSettingsViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 |
19 | // MARK: Outlets
20 |
21 | @IBOutlet weak var currentBugTypeImageView: UIImageView!
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | currentBugTypeImageView.tintColor = BugFactory.bugTints[bugFactory.currentBugType.rawValue]
28 | }
29 |
30 | // MARK: Actions
31 |
32 | @IBAction func dismissSettingsTouched(_ sender: AnyObject) { self.dismiss(animated: true, completion: nil) }
33 |
34 | @IBAction func bugTypeSelected(_ sender: UIButton) {
35 | bugFactory.currentBugType = BugFactory.BugType(rawValue: Int(sender.currentTitle!)!)!
36 | self.dismiss(animated: true, completion: nil)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/SoManyBugs/Images/back.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Images/back.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Images/settings.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Images/settings.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Images/spider.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Images/spider.pdf
--------------------------------------------------------------------------------
/SoManyBugs/Images/web.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-debugging/ff1145b970e8f1badcb96fe3585f1808e5d7ab7c/SoManyBugs/Images/web.pdf
--------------------------------------------------------------------------------
/SoManyBugs/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 |
--------------------------------------------------------------------------------
/SoManyBugs/PrintBugViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrintBugViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/16/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - PrintBugViewController: UIViewController
12 |
13 | class PrintBugViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 | let maxBugs = 100
19 | let moveDuration = 3.0
20 | let disperseDuration = 1.0
21 | var bugs = [UIImageView]()
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
28 | view.addGestureRecognizer(singleTapRecognizer)
29 | }
30 |
31 | // MARK: Bug Functions
32 |
33 | func addBugToView() {
34 | if bugs.count < maxBugs {
35 | let newBug = bugFactory.createBug()
36 | bugs.append(newBug)
37 | moveBugsAnimation()
38 | }
39 | }
40 |
41 | func emptyBugsFromView() {
42 | for bug in self.bugs {
43 | bug.removeFromSuperview()
44 | }
45 | self.bugs.removeAll(keepingCapacity: true)
46 | }
47 |
48 | // MARK: View Animations
49 |
50 | func moveBugsAnimation() {
51 | UIView.animate(withDuration: moveDuration) {
52 | for bug in self.bugs {
53 | let randomPosition = CGPoint(x: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxX - bug.frame.size.width))) + UInt32(bug.frame.size.width/2)), y: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxY - bug.frame.size.height))) + UInt32(bug.frame.size.height/2)))
54 | bug.frame = CGRect(x: randomPosition.x - bug.frame.size.width/1.5, y: randomPosition.y - bug.frame.size.height/1.5, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
55 | }
56 | }
57 | }
58 |
59 | func disperseBugsAnimation() {
60 | UIView.animate(withDuration: disperseDuration, animations: { () -> Void in
61 | for bug in self.bugs {
62 | let offScreenPosition = CGPoint(x: (bug.center.x - self.view.center.x) * 20, y: (bug.center.y - self.view.center.y) * 20)
63 | bug.frame = CGRect(x: offScreenPosition.x, y: offScreenPosition.y, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
64 | }
65 | }, completion: { (finished) -> Void in
66 | if finished { self.emptyBugsFromView() }
67 | })
68 | }
69 |
70 | // MARK: Actions
71 |
72 | @IBAction func popToMasterView() {
73 | let _ = navigationController?.popToRootViewController(animated: true)
74 | }
75 | }
76 |
77 | // MARK: - UIResponder
78 |
79 | extension PrintBugViewController {
80 | override var canBecomeFirstResponder: Bool { return true }
81 | override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
82 | if motion == .motionShake { disperseBugsAnimation() }
83 | }
84 | @objc func handleSingleTap(_ recognizer: UITapGestureRecognizer) { addBugToView() }
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/SoManyBugs/PrintSettingsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrintSettingsViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - PrintSettingsViewController: UIViewController
12 |
13 | class PrintSettingsViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 |
19 | // MARK: Outlets
20 |
21 | @IBOutlet weak var currentBugTypeImageView: UIImageView!
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | currentBugTypeImageView.tintColor = BugFactory.bugTints[bugFactory.currentBugType.rawValue]
28 | }
29 |
30 | // MARK: Actions
31 |
32 | @IBAction func dismissSettingsTouched(_ sender: AnyObject) { self.dismiss(animated: true, completion: nil) }
33 |
34 | @IBAction func bugTypeSelected(_ sender: UIButton) {
35 | bugFactory.currentBugType = BugFactory.BugType(rawValue: Int(sender.currentTitle!)!)!
36 | self.dismiss(animated: true, completion: nil)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/SoManyBugs/UIColor+BugTheme.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+BugTheme.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: UIColor Extensions
12 |
13 | extension UIColor {
14 | open class var brightRedColor: UIColor {
15 | return UIColor(red: 255.0/255.0, green: 59.0/255.0, blue: 48.0/255.0, alpha: 1.0)
16 | }
17 | open class var brightGreenColor: UIColor {
18 | return UIColor(red: 76.0/255.0, green: 217.0/255.0, blue: 100.0/255.0, alpha: 1.0)
19 | }
20 | open class var brightBlueColor: UIColor {
21 | return UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/SoManyBugs/VisualBugViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VisualBugViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/16/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - VisualBugViewController: UIViewController
12 |
13 | class VisualBugViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 | let maxBugs = 100
19 | let moveDuration = 3.0
20 | let disperseDuration = 1.0
21 | var bugs = [UIImageView]()
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
28 | view.addGestureRecognizer(singleTapRecognizer)
29 | }
30 |
31 | // MARK: Bug Functions
32 |
33 | func addBugToView() {
34 | if bugs.count < maxBugs {
35 | let newBug = bugFactory.createBug()
36 | bugs.append(newBug)
37 | view.addSubview(newBug)
38 | moveBugsAnimation()
39 | }
40 | }
41 |
42 | func emptyBugsFromView() {
43 | // TODO: Empty the bugs from view!
44 | }
45 |
46 | // MARK: View Animations
47 |
48 | func moveBugsAnimation() {
49 | UIView.animate(withDuration: moveDuration) {
50 | for bug in self.bugs {
51 | let randomPosition = CGPoint(x: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxX - bug.frame.size.width))) + UInt32(bug.frame.size.width/2)), y: CGFloat(arc4random_uniform(UInt32(UInt(self.view.bounds.maxY - bug.frame.size.height))) + UInt32(bug.frame.size.height/2)))
52 | bug.bounds = CGRect(x: randomPosition.x - bug.frame.size.width/1.5, y: randomPosition.y - bug.frame.size.height/1.5, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
53 | }
54 | }
55 | }
56 |
57 | func disperseBugsAnimation() {
58 | UIView.animate(withDuration: disperseDuration, animations: { () -> Void in
59 | for bug in self.bugs {
60 | let offScreenPosition = CGPoint(x: (bug.center.x - self.view.center.x) * -20, y: (bug.center.y - self.view.center.y) * -20)
61 | bug.frame = CGRect(x: offScreenPosition.x, y: offScreenPosition.y, width: BugFactory.bugSize.width, height: BugFactory.bugSize.height)
62 | }
63 | }, completion: { (finished) -> Void in
64 | if finished { self.emptyBugsFromView() }
65 | })
66 | }
67 |
68 | // MARK: Actions
69 |
70 | @IBAction func popToMasterView() {
71 | let _ = navigationController?.popToRootViewController(animated: true)
72 | }
73 | }
74 |
75 | // MARK: - VisualBugViewController (UIResponder)
76 |
77 | extension VisualBugViewController {
78 | override var canBecomeFirstResponder: Bool { return true }
79 | override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
80 | if motion == .motionShake { disperseBugsAnimation() }
81 | }
82 | @objc func handleSingleTap(_ recognizer: UITapGestureRecognizer) { addBugToView() }
83 | }
84 |
85 |
86 | // MARK: - VisualBugViewController (debugQuickLookObject)
87 |
88 | extension VisualBugViewController {
89 |
90 | func debugQuickLookObject() -> AnyObject? {
91 |
92 | let singleSquareLength: CGFloat = 10.0
93 | let squaresInRow = 10
94 | let imageSize = CGSize(width: singleSquareLength * CGFloat(squaresInRow), height: singleSquareLength * CGFloat(bugs.count / squaresInRow + 1))
95 |
96 | UIGraphicsBeginImageContextWithOptions(imageSize, true, 0)
97 | var x: CGFloat = 0.0
98 | var y: CGFloat = 0.0
99 | for bug in bugs {
100 | bug.tintColor.set()
101 | UIRectFill(CGRect(x: x, y: y, width: singleSquareLength, height: singleSquareLength))
102 | x += singleSquareLength
103 | if x > CGFloat(squaresInRow) * singleSquareLength {
104 | y += singleSquareLength
105 | x = 0.0
106 | }
107 | }
108 | UIColor.yellow.set()
109 | UIRectFill(CGRect(x: x, y: y, width: singleSquareLength, height: singleSquareLength))
110 | let image = UIGraphicsGetImageFromCurrentImageContext()
111 | UIGraphicsEndImageContext()
112 |
113 | return image
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/SoManyBugs/VisualSettingsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VisualSettingsViewController.swift
3 | // SoManyBugs
4 | //
5 | // Created by Jarrod Parkes on 4/17/15.
6 | // Copyright (c) 2015 Jarrod Parkes. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - VisualSettingsViewController: UIViewController
12 |
13 | class VisualSettingsViewController: UIViewController {
14 |
15 | // MARK: Properties
16 |
17 | let bugFactory = BugFactory.sharedInstance()
18 |
19 | // MARK: Outlets
20 |
21 | @IBOutlet weak var currentBugTypeImageView: UIImageView!
22 |
23 | // MARK: Life Cycle
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 | currentBugTypeImageView.tintColor = BugFactory.bugTints[bugFactory.currentBugType.rawValue]
28 | }
29 |
30 | // MARK: Actions
31 |
32 | @IBAction func dismissSettingsTouched(_ sender: AnyObject) { self.dismiss(animated: true, completion: nil) }
33 |
34 | @IBAction func bugTypeSelected(_ sender: UIButton) {
35 | bugFactory.currentBugType = BugFactory.BugType(rawValue: Int(sender.currentTitle!)!)!
36 | self.dismiss(animated: true, completion: nil)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------