├── CODEOWNERS
├── Mooskine
├── Mooskine-complete
│ ├── Mooskine
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ ├── texture-cow.imageset
│ │ │ │ ├── texture-cow.png
│ │ │ │ └── Contents.json
│ │ │ ├── toolbar-cow.imageset
│ │ │ │ ├── 1184-cow-toolbar.png
│ │ │ │ ├── 1184-cow-toolbar@2x.png
│ │ │ │ ├── 1184-cow-toolbar@3x.png
│ │ │ │ └── Contents.json
│ │ │ ├── toolbar-bold.imageset
│ │ │ │ ├── 1171-bold-toolbar.png
│ │ │ │ ├── 1171-bold-toolbar@2x.png
│ │ │ │ ├── 1171-bold-toolbar@3x.png
│ │ │ │ └── Contents.json
│ │ │ ├── toolbar-underline.imageset
│ │ │ │ ├── 1173-underline-toolbar.png
│ │ │ │ ├── 1173-underline-toolbar@2x.png
│ │ │ │ ├── 1173-underline-toolbar@3x.png
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── OpenSans-Bold.ttf
│ │ ├── OpenSans-Regular.ttf
│ │ ├── OpenSans-Semibold.ttf
│ │ ├── Model
│ │ │ ├── Mooskine.xcdatamodeld
│ │ │ │ ├── .xccurrentversion
│ │ │ │ ├── Mooskine.xcdatamodel
│ │ │ │ │ └── contents
│ │ │ │ └── Mooskine-2017-11-10-AttributedString.xcdatamodel
│ │ │ │ │ └── contents
│ │ │ ├── Managed Object Extensions
│ │ │ │ ├── Note+Extensions.swift
│ │ │ │ └── Notebook+Extensions.swift
│ │ │ ├── UpdateToAttributedStringsPolicy.swift
│ │ │ ├── DataController.swift
│ │ │ └── Pathifier.swift
│ │ ├── Views
│ │ │ ├── Cells
│ │ │ │ ├── NoteCell.swift
│ │ │ │ └── NotebookCell.swift
│ │ │ └── Protocols
│ │ │ │ └── Cell.swift
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── AppDelegate.swift
│ │ └── View Controllers
│ │ │ ├── NotesListViewController.swift
│ │ │ ├── NotebooksListViewController.swift
│ │ │ └── NoteDetailsViewController.swift
│ ├── Mooskine.xcodeproj
│ │ └── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── MooskineTests
│ │ ├── Info.plist
│ │ └── MooskineTests.swift
└── Mooskine-starter
│ ├── Mooskine
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── texture-cow.imageset
│ │ │ ├── texture-cow.png
│ │ │ └── Contents.json
│ │ ├── toolbar-cow.imageset
│ │ │ ├── 1184-cow-toolbar.png
│ │ │ ├── 1184-cow-toolbar@2x.png
│ │ │ ├── 1184-cow-toolbar@3x.png
│ │ │ └── Contents.json
│ │ ├── toolbar-bold.imageset
│ │ │ ├── 1171-bold-toolbar.png
│ │ │ ├── 1171-bold-toolbar@2x.png
│ │ │ ├── 1171-bold-toolbar@3x.png
│ │ │ └── Contents.json
│ │ ├── toolbar-underline.imageset
│ │ │ ├── 1173-underline-toolbar.png
│ │ │ ├── 1173-underline-toolbar@2x.png
│ │ │ ├── 1173-underline-toolbar@3x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── OpenSans-Bold.ttf
│ ├── OpenSans-Regular.ttf
│ ├── OpenSans-Semibold.ttf
│ ├── Model
│ │ ├── Note.swift
│ │ └── Notebook.swift
│ ├── Views
│ │ ├── Cells
│ │ │ ├── NoteCell.swift
│ │ │ └── NotebookCell.swift
│ │ └── Protocols
│ │ │ └── Cell.swift
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── Info.plist
│ ├── View Controllers
│ │ ├── NoteDetailsViewController.swift
│ │ ├── NotesListViewController.swift
│ │ └── NotebooksListViewController.swift
│ └── AppDelegate.swift
│ ├── Mooskine.xcodeproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── MooskineTests
│ ├── Info.plist
│ └── MooskineTests.swift
├── PickYourPitch-NoPersistence
├── PickYourPitch
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Icon-40.png
│ │ │ ├── Icon-76.png
│ │ │ ├── Icon-40@2x.png
│ │ │ ├── Icon-40@3x.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.png
│ │ │ ├── Icon-76@2x.png
│ │ │ ├── Icon-83.5@2x.png
│ │ │ ├── Icon-Small.png
│ │ │ ├── 1024-mark-blue.png
│ │ │ ├── Icon-Small@2x.png
│ │ │ ├── Icon-Small@3x.png
│ │ │ └── Contents.json
│ │ ├── play.imageset
│ │ │ ├── play@2x~iphone.png
│ │ │ └── Contents.json
│ │ ├── stop.imageset
│ │ │ ├── stop@2x~iphone.png
│ │ │ └── Contents.json
│ │ ├── LaunchLogo.imageset
│ │ │ ├── LaunchLogo.pdf
│ │ │ └── Contents.json
│ │ └── microphone.imageset
│ │ │ ├── microphone~iphone.png
│ │ │ ├── microphone@2x~iphone.png
│ │ │ └── Contents.json
│ ├── RecordedAudio.swift
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.xib
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ ├── PlaySoundsViewController.swift
│ └── RecordSoundsViewController.swift
└── PickYourPitch.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── PickYourPitch.xcscmblueprint
│ └── project.pbxproj
├── SandboxPlayground-Empty
├── SandboxPlayground
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Icon-40.png
│ │ │ ├── Icon-76.png
│ │ │ ├── Icon-40@2x.png
│ │ │ ├── Icon-40@3x.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.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
│ │ │ ├── LaunchLogo.pdf
│ │ │ └── Contents.json
│ ├── ViewController.swift
│ ├── AppDelegate.swift
│ ├── Info.plist
│ └── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.xib
└── SandboxPlayground.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── .gitignore
├── README.md
├── LICENSE
└── .github
└── workflows
└── manual.yml
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @batmanimal
2 |
3 | * @udacity/active-public-content
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/OpenSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/OpenSans-Bold.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/OpenSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/OpenSans-Bold.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/OpenSans-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/OpenSans-Semibold.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/OpenSans-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/OpenSans-Semibold.ttf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/texture-cow.imageset/texture-cow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/texture-cow.imageset/texture-cow.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/texture-cow.imageset/texture-cow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/texture-cow.imageset/texture-cow.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/play.imageset/play@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/play.imageset/play@2x~iphone.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/stop.imageset/stop@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/stop.imageset/stop@2x~iphone.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/LaunchLogo.imageset/LaunchLogo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/LaunchLogo.imageset/LaunchLogo.pdf
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/LaunchLogo.imageset/LaunchLogo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/LaunchLogo.imageset/LaunchLogo.pdf
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@3x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/1024-mark-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/1024-mark-blue.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@3x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/1184-cow-toolbar@3x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/1171-bold-toolbar@3x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/microphone.imageset/microphone~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/microphone.imageset/microphone~iphone.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/microphone.imageset/microphone@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/microphone.imageset/microphone@2x~iphone.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@3x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@2x.png
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/ios-nd-persistence/HEAD/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/1173-underline-toolbar@3x.png
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.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 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/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 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Mooskine.xcdatamodeld/.xccurrentversion:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | _XCCurrentVersionName
6 | Mooskine-2017-11-10-AttributedString.xcdatamodel
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // SandboxPlayground
4 | //
5 | // Created by Fernando Rodríguez Romero on 13/05/16.
6 | // Copyright © 2016 udacity.com. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - ViewController: UIViewController
12 |
13 | class ViewController: UIViewController {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/RecordedAudio.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecordedAudio.swift
3 | // Pick Your Pitch
4 | //
5 | // Created by Udacity on 1/5/15.
6 | // Copyright (c) 2014 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | // MARK: - RecordedAudio
12 |
13 | struct RecordedAudio {
14 |
15 | // MARK: Properties
16 |
17 | var filePathUrl: URL!
18 | var title: String!
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Managed Object Extensions/Note+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Note+Extensions.swift
3 | // Mooskine
4 | //
5 | // Created by Kathryn Rotondo on 10/21/17.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreData
11 |
12 | extension Note {
13 | public override func awakeFromInsert() {
14 | super.awakeFromInsert()
15 | creationDate = Date()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/texture-cow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "texture-cow.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Managed Object Extensions/Notebook+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Notebook+Extensions.swift
3 | // Mooskine
4 | //
5 | // Created by Kathryn Rotondo on 10/21/17.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreData
11 |
12 | extension Notebook {
13 | public override func awakeFromInsert() {
14 | super.awakeFromInsert()
15 | creationDate = Date()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/texture-cow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "texture-cow.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/play.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "play@2x~iphone.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/stop.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "stop@2x~iphone.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Model/Note.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Note.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Note {
12 | /// The date the note was created
13 | let creationDate: Date
14 |
15 | /// The note's text
16 | var text: String
17 |
18 | init(text: String = "New note") {
19 | self.text = text
20 | creationDate = Date()
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/microphone.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "microphone~iphone.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "microphone@2x~iphone.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-cow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1184-cow-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1184-cow-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1184-cow-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-cow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1184-cow-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1184-cow-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1184-cow-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-bold.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1171-bold-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1171-bold-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1171-bold-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-bold.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1171-bold-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1171-bold-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1171-bold-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Views/Cells/NoteCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteCell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | internal final class NoteCell: UITableViewCell, Cell {
12 | // Outlets
13 | @IBOutlet weak var textPreviewLabel: UILabel!
14 | @IBOutlet weak var dateLabel: UILabel!
15 |
16 | override func prepareForReuse() {
17 | super.prepareForReuse()
18 | textPreviewLabel.text = nil
19 | dateLabel.text = nil
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/toolbar-underline.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1173-underline-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1173-underline-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1173-underline-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Views/Cells/NoteCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteCell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | internal final class NoteCell: UITableViewCell, Cell {
12 | // Outlets
13 | @IBOutlet weak var textPreviewLabel: UILabel!
14 | @IBOutlet weak var dateLabel: UILabel!
15 |
16 | override func prepareForReuse() {
17 | super.prepareForReuse()
18 | textPreviewLabel.text = nil
19 | dateLabel.text = nil
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/toolbar-underline.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1173-underline-toolbar.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "1173-underline-toolbar@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "1173-underline-toolbar@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Views/Cells/NotebookCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotebookCell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | internal final class NotebookCell: UITableViewCell, Cell {
12 | // Outlets
13 | @IBOutlet weak var nameLabel: UILabel!
14 | @IBOutlet weak var pageCountLabel: UILabel!
15 |
16 | override func prepareForReuse() {
17 | super.prepareForReuse()
18 | nameLabel.text = nil
19 | pageCountLabel.text = nil
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Views/Cells/NotebookCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotebookCell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | internal final class NotebookCell: UITableViewCell, Cell {
12 | // Outlets
13 | @IBOutlet weak var nameLabel: UILabel!
14 | @IBOutlet weak var pageCountLabel: UILabel!
15 |
16 | override func prepareForReuse() {
17 | super.prepareForReuse()
18 | nameLabel.text = nil
19 | pageCountLabel.text = nil
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Views/Protocols/Cell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Cell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol Cell: class {
12 | /// A default reuse identifier for the cell class
13 | static var defaultReuseIdentifier: String { get }
14 | }
15 |
16 | extension Cell {
17 | static var defaultReuseIdentifier: String {
18 | // Should return the class's name, without namespacing or mangling.
19 | // This works as of Swift 3.1.1, but might be fragile.
20 | return "\(self)"
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Views/Protocols/Cell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Cell.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol Cell: class {
12 | /// A default reuse identifier for the cell class
13 | static var defaultReuseIdentifier: String { get }
14 | }
15 |
16 | extension Cell {
17 | static var defaultReuseIdentifier: String {
18 | // Should return the class's name, without namespacing or mangling.
19 | // This works as of Swift 3.1.1, but might be fragile.
20 | return "\(self)"
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/MooskineTests/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 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/MooskineTests/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 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SandboxPlayground
4 | //
5 | // Created by Fernando Rodríguez Romero on 13/05/16.
6 | // Copyright © 2016 udacity.com. 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
21 |
22 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
23 | // Override point for customization after application launch.
24 | return true
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Model/Notebook.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Notebook.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Notebook {
12 | /// The name for the notebook
13 | let name: String
14 |
15 | /// The date the notebook was created
16 | let creationDate: Date
17 |
18 | /// The notes contained by the notebook
19 | var notes: [Note] = []
20 |
21 | init(name: String) {
22 | self.name = name
23 | creationDate = Date()
24 | notes = []
25 | }
26 | }
27 |
28 | extension Notebook {
29 | /// Add a new note to the notebook
30 | func addNote() {
31 | notes.append(Note())
32 | }
33 |
34 | /// Removes the note at a specific index
35 | func removeNote(at index: Int) {
36 | notes.remove(at: index)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # iOS Persistence and Core Data
4 |
5 | 
6 |
7 | This repository contains resources for Udacity's iOS Persistence and Core Data course.
8 |
9 | ## Overview
10 |
11 | iOS Persistence and Core Data teach common persistence techniques using Apple's frameworks for storing data locally on the device. The course includes:
12 |
13 | * PickYourPitch, which has a small user preference we'll store in UserDefaults
14 | * SandboxPlayground, which we'll use to explore saving and reading files using FileManager
15 | * Mooskine, a note-taking app which we'll convert to Core Data
16 |
17 | ## Setup
18 |
19 | Generally speaking, most projects can run without any additional setup. However, consult the iOS Persistence and Core Data course for more information.
20 |
21 | ## Maintainers
22 |
23 | @OwenLaRosa
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/MooskineTests/MooskineTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MooskineTests.swift
3 | // MooskineTests
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Mooskine
11 |
12 | class MooskineTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/MooskineTests/MooskineTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MooskineTests.swift
3 | // MooskineTests
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Mooskine
11 |
12 | class MooskineTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/UpdateToAttributedStringsPolicy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UpdateToAttributedStringsPolicy.swift
3 | // Mooskine
4 | //
5 | // Created by Kathryn Rotondo on 11/10/17.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import CoreData
12 |
13 | class UpdateToAttributedStringsPolicy: NSEntityMigrationPolicy {
14 |
15 | override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
16 | // Call super
17 | try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
18 |
19 | // Get the (updated) destination Note instance we're modifying
20 | guard let destination = manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]).first else { return }
21 |
22 | // Use the (original) source Note instance, and instantiate a new
23 | // NSAttributedString using the original string
24 | if let text = sInstance.value(forKey: "text") as? String {
25 | destination.setValue(NSAttributedString(string: text), forKey: "attributedText")
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/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 |
40 |
41 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/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 |
40 |
41 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Mooskine.xcdatamodeld/Mooskine.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Mooskine.xcdatamodeld/Mooskine-2017-11-10-AttributedString.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIAppFonts
6 |
7 | OpenSans-Bold.ttf
8 | OpenSans-Regular.ttf
9 | OpenSans-Semibold.ttf
10 |
11 | CFBundleDevelopmentRegion
12 | en
13 | CFBundleExecutable
14 | $(EXECUTABLE_NAME)
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | $(PRODUCT_NAME)
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.0
25 | CFBundleVersion
26 | 1
27 | LSRequiresIPhoneOS
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 | UIInterfaceOrientationPortraitUpsideDown
43 |
44 | UISupportedInterfaceOrientations~ipad
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationPortraitUpsideDown
48 | UIInterfaceOrientationLandscapeLeft
49 | UIInterfaceOrientationLandscapeRight
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIAppFonts
6 |
7 | OpenSans-Bold.ttf
8 | OpenSans-Regular.ttf
9 | OpenSans-Semibold.ttf
10 |
11 | CFBundleDevelopmentRegion
12 | en
13 | CFBundleExecutable
14 | $(EXECUTABLE_NAME)
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | $(PRODUCT_NAME)
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.0
25 | CFBundleVersion
26 | 1
27 | LSRequiresIPhoneOS
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UIRequiredDeviceCapabilities
34 |
35 | armv7
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 | UIInterfaceOrientationPortraitUpsideDown
43 |
44 | UISupportedInterfaceOrientations~ipad
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationPortraitUpsideDown
48 | UIInterfaceOrientationLandscapeLeft
49 | UIInterfaceOrientationLandscapeRight
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/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 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/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 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/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 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/DataController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataController.swift
3 | // Mooskine
4 | //
5 | // Created by Kathryn Rotondo on 10/11/17.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CoreData
11 |
12 | class DataController {
13 |
14 | let persistentContainer:NSPersistentContainer
15 |
16 | var viewContext:NSManagedObjectContext {
17 | return persistentContainer.viewContext
18 | }
19 |
20 | let backgroundContext:NSManagedObjectContext!
21 |
22 | init(modelName:String) {
23 | persistentContainer = NSPersistentContainer(name: modelName)
24 |
25 | backgroundContext = persistentContainer.newBackgroundContext()
26 | }
27 |
28 | func configureContexts() {
29 | viewContext.automaticallyMergesChangesFromParent = true
30 | backgroundContext.automaticallyMergesChangesFromParent = true
31 |
32 | backgroundContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
33 | viewContext.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump
34 | }
35 |
36 | func load(completion: (() -> Void)? = nil) {
37 | persistentContainer.loadPersistentStores { storeDescription, error in
38 | guard error == nil else {
39 | fatalError(error!.localizedDescription)
40 | }
41 | self.autoSaveViewContext()
42 | self.configureContexts()
43 | completion?()
44 | }
45 | }
46 | }
47 |
48 | // MARK: - Autosaving
49 |
50 | extension DataController {
51 | func autoSaveViewContext(interval:TimeInterval = 30) {
52 | print("autosaving")
53 |
54 | guard interval > 0 else {
55 | print("cannot set negative autosave interval")
56 | return
57 | }
58 |
59 | if viewContext.hasChanges {
60 | try? viewContext.save()
61 | }
62 |
63 | DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
64 | self.autoSaveViewContext(interval: interval)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/View Controllers/NoteDetailsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteDetailsViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NoteDetailsViewController: UIViewController {
12 | /// A text view that displays a note's text
13 | @IBOutlet weak var textView: UITextView!
14 |
15 | /// The note being displayed and edited
16 | var note: Note!
17 |
18 | /// A closure that is run when the user asks to delete the current note
19 | var onDelete: (() -> Void)?
20 |
21 | /// A date formatter for the view controller's title text
22 | let dateFormatter: DateFormatter = {
23 | let df = DateFormatter()
24 | df.dateStyle = .medium
25 | return df
26 | }()
27 |
28 | override func viewDidLoad() {
29 | super.viewDidLoad()
30 |
31 | navigationItem.title = dateFormatter.string(from: note.creationDate)
32 | textView.text = note.text
33 | }
34 |
35 | @IBAction func deleteNote(sender: Any) {
36 | presentDeleteNotebookAlert()
37 | }
38 | }
39 |
40 | // -----------------------------------------------------------------------------
41 | // MARK: - Editing
42 |
43 | extension NoteDetailsViewController {
44 | func presentDeleteNotebookAlert() {
45 | let alert = UIAlertController(title: "Delete Note", message: "Do you want to delete this note?", preferredStyle: .alert)
46 | alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
47 | alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: deleteHandler))
48 | present(alert, animated: true, completion: nil)
49 | }
50 |
51 | func deleteHandler(alertAction: UIAlertAction) {
52 | onDelete?()
53 | }
54 | }
55 |
56 | // -----------------------------------------------------------------------------
57 | // MARK: - UITextViewDelegate
58 |
59 | extension NoteDetailsViewController: UITextViewDelegate {
60 | func textViewDidEndEditing(_ textView: UITextView) {
61 | note.text = textView.text
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // 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.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // 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.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // 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.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch.xcodeproj/project.xcworkspace/xcshareddata/PickYourPitch.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "110AB89DE05ABD8A5A321ADE3254A1BB5198BC51",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "CD28FA6A2CFC634512324DD7C91B7993C5276BCE" : 0,
8 | "5E32233CC4B3D004BDE8903D03F6C0AFCAF27AFC" : 0,
9 | "110AB89DE05ABD8A5A321ADE3254A1BB5198BC51" : 0
10 | },
11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "D4A82946-9A7F-4557-B337-2BB27D41E2A7",
12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
13 | "CD28FA6A2CFC634512324DD7C91B7993C5276BCE" : "ios-persistence",
14 | "5E32233CC4B3D004BDE8903D03F6C0AFCAF27AFC" : "ios-persistence-2.0\/",
15 | "110AB89DE05ABD8A5A321ADE3254A1BB5198BC51" : "ios-nd-persistence\/"
16 | },
17 | "DVTSourceControlWorkspaceBlueprintNameKey" : "PickYourPitch",
18 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
19 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "PickYourPitch\/PickYourPitch.xcodeproj",
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
21 | {
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/udacity\/ios-nd-persistence",
23 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "110AB89DE05ABD8A5A321ADE3254A1BB5198BC51"
25 | },
26 | {
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/udacity\/ios-persistence-2.0",
28 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
29 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5E32233CC4B3D004BDE8903D03F6C0AFCAF27AFC"
30 | },
31 | {
32 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/udacity\/ios-persistence",
33 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
34 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CD28FA6A2CFC634512324DD7C91B7993C5276BCE"
35 | }
36 | ]
37 | }
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "size" : "29x29",
15 | "idiom" : "iphone",
16 | "filename" : "Icon-Small@2x.png",
17 | "scale" : "2x"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "iphone",
22 | "filename" : "Icon-Small@3x.png",
23 | "scale" : "3x"
24 | },
25 | {
26 | "size" : "40x40",
27 | "idiom" : "iphone",
28 | "filename" : "Icon-40@2x.png",
29 | "scale" : "2x"
30 | },
31 | {
32 | "size" : "40x40",
33 | "idiom" : "iphone",
34 | "filename" : "Icon-40@3x.png",
35 | "scale" : "3x"
36 | },
37 | {
38 | "size" : "60x60",
39 | "idiom" : "iphone",
40 | "filename" : "Icon-60@2x.png",
41 | "scale" : "2x"
42 | },
43 | {
44 | "size" : "60x60",
45 | "idiom" : "iphone",
46 | "filename" : "Icon-60@3x.png",
47 | "scale" : "3x"
48 | },
49 | {
50 | "idiom" : "ipad",
51 | "size" : "20x20",
52 | "scale" : "1x"
53 | },
54 | {
55 | "idiom" : "ipad",
56 | "size" : "20x20",
57 | "scale" : "2x"
58 | },
59 | {
60 | "size" : "29x29",
61 | "idiom" : "ipad",
62 | "filename" : "Icon-Small.png",
63 | "scale" : "1x"
64 | },
65 | {
66 | "size" : "29x29",
67 | "idiom" : "ipad",
68 | "filename" : "Icon-Small@2x.png",
69 | "scale" : "2x"
70 | },
71 | {
72 | "size" : "40x40",
73 | "idiom" : "ipad",
74 | "filename" : "Icon-40.png",
75 | "scale" : "1x"
76 | },
77 | {
78 | "size" : "40x40",
79 | "idiom" : "ipad",
80 | "filename" : "Icon-40@2x.png",
81 | "scale" : "2x"
82 | },
83 | {
84 | "size" : "76x76",
85 | "idiom" : "ipad",
86 | "filename" : "Icon-76.png",
87 | "scale" : "1x"
88 | },
89 | {
90 | "size" : "76x76",
91 | "idiom" : "ipad",
92 | "filename" : "Icon-76@2x.png",
93 | "scale" : "2x"
94 | },
95 | {
96 | "size" : "83.5x83.5",
97 | "idiom" : "ipad",
98 | "filename" : "Icon-83.5@2x.png",
99 | "scale" : "2x"
100 | }
101 | ],
102 | "info" : {
103 | "version" : 1,
104 | "author" : "xcode"
105 | }
106 | }
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "size" : "29x29",
15 | "idiom" : "iphone",
16 | "filename" : "Icon-Small@2x.png",
17 | "scale" : "2x"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "iphone",
22 | "filename" : "Icon-Small@3x.png",
23 | "scale" : "3x"
24 | },
25 | {
26 | "size" : "40x40",
27 | "idiom" : "iphone",
28 | "filename" : "Icon-40@2x.png",
29 | "scale" : "2x"
30 | },
31 | {
32 | "size" : "40x40",
33 | "idiom" : "iphone",
34 | "filename" : "Icon-40@3x.png",
35 | "scale" : "3x"
36 | },
37 | {
38 | "size" : "60x60",
39 | "idiom" : "iphone",
40 | "filename" : "Icon-60@2x.png",
41 | "scale" : "2x"
42 | },
43 | {
44 | "size" : "60x60",
45 | "idiom" : "iphone",
46 | "filename" : "Icon-60@3x.png",
47 | "scale" : "3x"
48 | },
49 | {
50 | "idiom" : "ipad",
51 | "size" : "20x20",
52 | "scale" : "1x"
53 | },
54 | {
55 | "idiom" : "ipad",
56 | "size" : "20x20",
57 | "scale" : "2x"
58 | },
59 | {
60 | "size" : "29x29",
61 | "idiom" : "ipad",
62 | "filename" : "Icon-Small.png",
63 | "scale" : "1x"
64 | },
65 | {
66 | "size" : "29x29",
67 | "idiom" : "ipad",
68 | "filename" : "Icon-Small@2x.png",
69 | "scale" : "2x"
70 | },
71 | {
72 | "size" : "40x40",
73 | "idiom" : "ipad",
74 | "filename" : "Icon-40.png",
75 | "scale" : "1x"
76 | },
77 | {
78 | "size" : "40x40",
79 | "idiom" : "ipad",
80 | "filename" : "Icon-40@2x.png",
81 | "scale" : "2x"
82 | },
83 | {
84 | "size" : "76x76",
85 | "idiom" : "ipad",
86 | "filename" : "Icon-76.png",
87 | "scale" : "1x"
88 | },
89 | {
90 | "size" : "76x76",
91 | "idiom" : "ipad",
92 | "filename" : "Icon-76@2x.png",
93 | "scale" : "2x"
94 | },
95 | {
96 | "size" : "83.5x83.5",
97 | "idiom" : "ipad",
98 | "filename" : "Icon-83.5@2x.png",
99 | "scale" : "2x"
100 | },
101 | {
102 | "size" : "1024x1024",
103 | "idiom" : "ios-marketing",
104 | "filename" : "1024-mark-blue.png",
105 | "scale" : "1x"
106 | }
107 | ],
108 | "info" : {
109 | "version" : 1,
110 | "author" : "xcode"
111 | }
112 | }
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-29.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | let dataController = DataController(modelName: "Mooskine")
17 |
18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
19 | // Override point for customization after application launch.
20 |
21 | dataController.load()
22 |
23 | let navigationController = window?.rootViewController as! UINavigationController
24 | let notebooksListViewController = navigationController.topViewController as! NotebooksListViewController
25 | notebooksListViewController.dataController = dataController
26 |
27 | return true
28 | }
29 |
30 | func applicationWillResignActive(_ application: UIApplication) {
31 | // 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.
32 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
33 | }
34 |
35 | func applicationDidEnterBackground(_ application: UIApplication) {
36 | // 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.
37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38 | saveViewContext()
39 | }
40 |
41 | func applicationWillEnterForeground(_ application: UIApplication) {
42 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 | func applicationDidBecomeActive(_ application: UIApplication) {
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 |
49 | func applicationWillTerminate(_ application: UIApplication) {
50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
51 | saveViewContext()
52 | }
53 |
54 | func saveViewContext() {
55 | try? dataController.viewContext.save()
56 | }
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Pick Your Pitch
4 | //
5 | // Created by Udacity on 1/5/15.
6 | // Copyright (c) 2015 Udacity. 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
21 |
22 | func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
23 | // Usually this is not overridden. Using the "did finish launching" method is more typical
24 | print("App Delegate: will finish launching")
25 |
26 | return true
27 | }
28 |
29 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
30 | // Override point for customization after application launch.
31 |
32 | print("App Delegate: did finish launching")
33 |
34 | return true
35 | }
36 |
37 | func applicationDidBecomeActive(_ application: UIApplication) {
38 | // 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.
39 |
40 | print("App Delegate: did become active")
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 | print("App Delegate: will resign active")
48 | }
49 |
50 | func applicationDidEnterBackground(_ application: UIApplication) {
51 | // 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.
52 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
53 |
54 | print("App Delegate: did enter background")
55 | }
56 |
57 | func applicationWillEnterForeground(_ application: UIApplication) {
58 | // 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.
59 |
60 | print("App Delegate: will enter foreground")
61 | }
62 |
63 | func applicationWillTerminate(_ application: UIApplication) {
64 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
65 |
66 | print("App Delegate: will terminate")
67 | }
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/PlaySoundsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PlaySoundsViewController.swift
3 | // Pick Your Pitch
4 | //
5 | // Created by Udacity on 1/5/15.
6 | // Copyright (c) 2014 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | // MARK: - PlaySoundsViewController: UIViewController
13 |
14 | class PlaySoundsViewController: UIViewController {
15 |
16 | // MARK: Properties
17 |
18 | let SliderValueKey = "Slider Value Key"
19 | var audioPlayer:AVAudioPlayer!
20 | var receivedAudio:RecordedAudio!
21 | var audioEngine:AVAudioEngine!
22 | var audioFile:AVAudioFile!
23 |
24 | // MARK: Outlets
25 |
26 | @IBOutlet weak var sliderView: UISlider!
27 | @IBOutlet weak var startButton: UIButton!
28 | @IBOutlet weak var stopButton: UIButton!
29 |
30 | // MARK: Life Cycle
31 |
32 | override func viewDidLoad() {
33 | super.viewDidLoad()
34 |
35 | do {
36 | audioPlayer = try AVAudioPlayer(contentsOf: receivedAudio.filePathUrl as URL)
37 | } catch _ {
38 | audioPlayer = nil
39 | }
40 | audioPlayer.enableRate = true
41 |
42 | audioEngine = AVAudioEngine()
43 | do {
44 | audioFile = try AVAudioFile(forReading: receivedAudio.filePathUrl as URL)
45 | } catch _ {
46 | audioFile = nil
47 | }
48 |
49 | setUserInterfaceToPlayMode(false)
50 | }
51 |
52 | // MARK: Set Interface
53 |
54 | func setUserInterfaceToPlayMode(_ isPlayMode: Bool) {
55 | startButton.isHidden = isPlayMode
56 | stopButton.isHidden = !isPlayMode
57 | sliderView.isEnabled = !isPlayMode
58 | }
59 |
60 | // MARK: Actions
61 |
62 | @IBAction func playAudio(_ sender: UIButton) {
63 |
64 | // Get the pitch from the slider
65 | let pitch = sliderView.value
66 |
67 | // Play the sound
68 | playAudioWithVariablePitch(pitch)
69 |
70 | // Set the UI
71 | setUserInterfaceToPlayMode(true)
72 |
73 | }
74 |
75 | @IBAction func stopAudio(_ sender: UIButton) {
76 | audioPlayer.stop()
77 | audioEngine.stop()
78 | audioEngine.reset()
79 | }
80 |
81 | @IBAction func sliderDidMove(_ sender: UISlider) {
82 | print("Slider value: \(sliderView.value)")
83 | }
84 |
85 | // MARK: Play Audio
86 |
87 | func playAudioWithVariablePitch(_ pitch: Float){
88 | audioPlayer.stop()
89 | audioEngine.stop()
90 | audioEngine.reset()
91 |
92 | let audioPlayerNode = AVAudioPlayerNode()
93 | audioEngine.attach(audioPlayerNode)
94 |
95 | let changePitchEffect = AVAudioUnitTimePitch()
96 | changePitchEffect.pitch = pitch
97 | audioEngine.attach(changePitchEffect)
98 |
99 | audioEngine.connect(audioPlayerNode, to: changePitchEffect, format: nil)
100 | audioEngine.connect(changePitchEffect, to: audioEngine.outputNode, format: nil)
101 |
102 | audioPlayerNode.scheduleFile(audioFile, at: nil) {
103 | // When the audio completes, set the user interface on the main thread
104 | DispatchQueue.main.async {self.setUserInterfaceToPlayMode(false) }
105 | }
106 |
107 | do {
108 | try audioEngine.start()
109 | } catch _ {
110 | }
111 |
112 | audioPlayerNode.play()
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/RecordSoundsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecordSoundsViewController.swift
3 | // Pick Your Pitch
4 | //
5 | // Created by Udacity on 1/5/15.
6 | // Copyright (c) 2014 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | // MARK: - RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate
13 |
14 | class RecordSoundsViewController: UIViewController, AVAudioRecorderDelegate {
15 |
16 | // MARK: Properties
17 |
18 | var audioRecorder:AVAudioRecorder!
19 | var recordedAudio:RecordedAudio!
20 | var shouldSegueToSoundPlayer = false
21 |
22 | // MARK: Outlets
23 |
24 | @IBOutlet weak var recordingInProgress: UILabel!
25 | @IBOutlet weak var stopButton: UIButton!
26 | @IBOutlet weak var recordButton: UIButton!
27 |
28 | // MARK: Life Cycle
29 |
30 | override func viewWillAppear(_ animated: Bool) {
31 | //Hide the stop button
32 | stopButton.isHidden = true
33 | recordButton.isEnabled = true
34 | }
35 |
36 | // MARK: Actions
37 |
38 | @IBAction func recordAudio(_ sender: UIButton) {
39 | // Update the UI
40 | stopButton.isHidden = false
41 | recordingInProgress.isHidden = false
42 | recordButton.isEnabled = false
43 |
44 | // Setup audio session
45 | let session = AVAudioSession.sharedInstance()
46 | do {
47 | try session.setCategory(.playAndRecord)
48 | } catch _ {
49 | }
50 |
51 | // Create a name for the file. This is the code that you are looking for
52 | let filename = "usersVoice.wav"
53 | let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
54 | let pathArray = [dirPath, filename]
55 | let fileURL = URL(string: pathArray.joined(separator: "/"))
56 |
57 | do {
58 | // Initialize and prepare the recorder
59 | audioRecorder = try AVAudioRecorder(url: fileURL!, settings: [String: AnyObject]())
60 | } catch _ {
61 | }
62 | audioRecorder.delegate = self
63 | audioRecorder.isMeteringEnabled = true;
64 | audioRecorder.prepareToRecord()
65 |
66 | audioRecorder.record()
67 | }
68 |
69 | @IBAction func stopAudio(_ sender: UIButton) {
70 | recordingInProgress.isHidden = true
71 | audioRecorder.stop()
72 | let audioSession = AVAudioSession.sharedInstance();
73 | do {
74 | try audioSession.setActive(false)
75 | } catch _ {
76 | }
77 |
78 | // This function stops the audio. We will then wait to hear back from the recorder,
79 | // through the audioRecorderDidFinishRecording method
80 | }
81 |
82 | // MARK: Audio Recorded
83 |
84 | func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
85 |
86 | if flag {
87 | recordedAudio = RecordedAudio(filePathUrl: recorder.url, title: recorder.url.pathExtension)
88 | self.performSegue(withIdentifier: "stopRecording", sender: self)
89 | } else {
90 | print("Recording was not successful")
91 | recordButton.isEnabled = true
92 | stopButton.isHidden = true
93 | }
94 | }
95 |
96 | // MARK: Segue
97 |
98 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
99 |
100 | if segue.identifier == "stopRecording" {
101 | let playSoundsVC:PlaySoundsViewController = segue.destination as! PlaySoundsViewController
102 | let data = recordedAudio
103 | playSoundsVC.receivedAudio = data
104 | }
105 | }
106 | }
107 |
108 |
109 | // Helper function inserted by Swift 4.2 migrator.
110 | fileprivate func convertFromAVAudioSessionCategory(_ input: AVAudioSession.Category) -> String {
111 | return input.rawValue
112 | }
113 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/Model/Pathifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Pathifier.swift
3 | // Mooskine
4 | //
5 | // Copyright © 2017 Udacity. All rights reserved.
6 | //
7 |
8 | import UIKit
9 | import CoreText
10 |
11 | internal struct Pathifier {
12 | /// Creates a UIBezierPath from a supplied attributed string and font (the
13 | /// font will be applied to the entire attributed string).
14 | static func makeBezierPath(for attributedString: NSAttributedString, withFont font: UIFont) -> UIBezierPath {
15 | // To generate the bezier path, we'll break the attributed string into
16 | // a series of `NSGlyph`s using TextKit, and use a CoreText function to
17 | // create individual individual paths for each glyph.
18 |
19 | // Apply the supplied font
20 | let text = NSMutableAttributedString(string: attributedString.string)
21 | text.addAttribute(NSAttributedString.Key.font, value: font, range: NSMakeRange(0, text.length))
22 |
23 | // Create a NSLayoutManager to generate the glyphs
24 | let layoutManager = NSLayoutManager()
25 | let textContainer = NSTextContainer()
26 | let textStorage = NSTextStorage(attributedString: text)
27 | textStorage.addLayoutManager(layoutManager)
28 | layoutManager.addTextContainer(textContainer)
29 |
30 | // Use the layout manager to loop through the glyphs, adding to a bezier
31 | // path as we go
32 | let path = UIBezierPath()
33 | let font = CTFontCreateWithFontDescriptor(font.fontDescriptor, font.pointSize, nil)
34 | for glyphIndex in 0 ..< layoutManager.numberOfGlyphs {
35 | let glyph = layoutManager.cgGlyph(at: glyphIndex)
36 | let position = layoutManager.location(forGlyphAt: glyphIndex)
37 | if let glyphPath = CTFontCreatePathForGlyph(font, glyph, nil) {
38 | let glyphBezierPath = UIBezierPath(cgPath: glyphPath)
39 | glyphBezierPath.apply(CGAffineTransform(translationX: position.x, y: 0))
40 | path.append(glyphBezierPath)
41 | }
42 | }
43 |
44 | return path
45 | }
46 |
47 | /// Generate an image for an attributed string, using `makeBezierPath(for:withFont:)`
48 | static func makeImage(for attributedString: NSAttributedString, withFont font: UIFont, withPatternImage patternImage: UIImage) -> UIImage {
49 | let path = makeBezierPath(for: attributedString, withFont: font)
50 | let bounds = path.bounds
51 | let pad = CGSize(width: 4, height: 6) // Add some padding so the wide lines don't clip - should figure out the metrics for this via Core Text. :)
52 | let size = CGSize(width: bounds.size.width + bounds.origin.x + pad.width, height: bounds.size.height + pad.height)
53 |
54 | UIGraphicsBeginImageContextWithOptions(size, false, 0)
55 | let context = UIGraphicsGetCurrentContext()
56 |
57 | // Flip the orientation vertically
58 | context?.scaleBy(x: 1, y: -1)
59 | context?.translateBy(x: 0, y: -size.height)
60 |
61 | // Adjust positioning for the padding
62 | context?.translateBy(x: -pad.width / 2, y: pad.height / 2)
63 |
64 | // Draw the path
65 | context?.setFillColor(UIColor(patternImage: patternImage).cgColor)
66 | path.fill()
67 | context?.setStrokeColor(UIColor.black.cgColor)
68 | path.stroke()
69 | let image = UIGraphicsGetImageFromCurrentImageContext()
70 | UIGraphicsEndImageContext()
71 |
72 | return image!
73 | }
74 |
75 | static func makeMutableAttributedString(for attributedString: NSAttributedString, withFont font: UIFont, withPatternImage patternImage: UIImage) -> NSMutableAttributedString {
76 |
77 | // converts text to image using patternimage
78 | let image = Pathifier.makeImage(for: attributedString, withFont: font, withPatternImage: patternImage)
79 |
80 | // creates a text attachment with the image
81 | let attachment = NSTextAttachment()
82 | attachment.image = image
83 |
84 | // converts attachment to mutable attributed string
85 | let attachmentAsText = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment))
86 | return attachmentAsText
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/View Controllers/NotesListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotesListViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NotesListViewController: UIViewController, UITableViewDataSource {
12 | /// A table view that displays a list of notes for a notebook
13 | @IBOutlet weak var tableView: UITableView!
14 |
15 | /// The notebook whose notes are being displayed
16 | var notebook: Notebook!
17 |
18 | /// A date formatter for date text in note cells
19 | let dateFormatter: DateFormatter = {
20 | let df = DateFormatter()
21 | df.dateStyle = .medium
22 | return df
23 | }()
24 |
25 | override func viewDidLoad() {
26 | super.viewDidLoad()
27 |
28 | navigationItem.title = notebook.name
29 | navigationItem.rightBarButtonItem = editButtonItem
30 | updateEditButtonState()
31 | }
32 |
33 | override func viewWillAppear(_ animated: Bool) {
34 | super.viewWillAppear(animated)
35 |
36 | if let indexPath = tableView.indexPathForSelectedRow {
37 | tableView.deselectRow(at: indexPath, animated: false)
38 | tableView.reloadRows(at: [indexPath], with: .fade)
39 | }
40 | }
41 |
42 | // -------------------------------------------------------------------------
43 | // MARK: - Actions
44 |
45 | @IBAction func addTapped(sender: Any) {
46 | addNote()
47 | }
48 |
49 | // -------------------------------------------------------------------------
50 | // MARK: - Editing
51 |
52 | // Adds a new `Note` to the end of the `notebook`'s `notes` array
53 | func addNote() {
54 | notebook.addNote()
55 | tableView.insertRows(at: [IndexPath(row: numberOfNotes - 1, section: 0)], with: .fade)
56 | updateEditButtonState()
57 | }
58 |
59 | // Deletes the `Note` at the specified index path
60 | func deleteNote(at indexPath: IndexPath) {
61 | notebook.removeNote(at: indexPath.row)
62 | tableView.deleteRows(at: [indexPath], with: .fade)
63 | if numberOfNotes == 0 {
64 | setEditing(false, animated: true)
65 | }
66 | updateEditButtonState()
67 | }
68 |
69 | func updateEditButtonState() {
70 | navigationItem.rightBarButtonItem?.isEnabled = numberOfNotes > 0
71 | }
72 |
73 | override func setEditing(_ editing: Bool, animated: Bool) {
74 | super.setEditing(editing, animated: animated)
75 | tableView.setEditing(editing, animated: animated)
76 | }
77 |
78 | // -------------------------------------------------------------------------
79 | // MARK: - Table view data source
80 |
81 | func numberOfSections(in tableView: UITableView) -> Int {
82 | return 1
83 | }
84 |
85 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
86 | return numberOfNotes
87 | }
88 |
89 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
90 | let aNote = note(at: indexPath)
91 | let cell = tableView.dequeueReusableCell(withIdentifier: NoteCell.defaultReuseIdentifier, for: indexPath) as! NoteCell
92 |
93 | // Configure cell
94 | cell.textPreviewLabel.text = aNote.text
95 | cell.dateLabel.text = dateFormatter.string(from: aNote.creationDate)
96 |
97 | return cell
98 | }
99 |
100 | func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
101 | switch editingStyle {
102 | case .delete: deleteNote(at: indexPath)
103 | default: () // Unsupported
104 | }
105 | }
106 |
107 | // Helpers
108 |
109 | var numberOfNotes: Int { return notebook.notes.count }
110 |
111 | func note(at indexPath: IndexPath) -> Note {
112 | return notebook.notes[indexPath.row]
113 | }
114 |
115 | // -------------------------------------------------------------------------
116 | // MARK: - Navigation
117 |
118 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
119 | // If this is a NoteDetailsViewController, we'll configure its `Note`
120 | // and its delete action
121 | if let vc = segue.destination as? NoteDetailsViewController {
122 | if let indexPath = tableView.indexPathForSelectedRow {
123 | vc.note = note(at: indexPath)
124 |
125 | vc.onDelete = { [weak self] in
126 | if let indexPath = self?.tableView.indexPathForSelectedRow {
127 | self?.deleteNote(at: indexPath)
128 | self?.navigationController?.popViewController(animated: true)
129 | }
130 | }
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-starter/Mooskine/View Controllers/NotebooksListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotebooksListViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NotebooksListViewController: UIViewController, UITableViewDataSource {
12 | /// A table view that displays a list of notebooks
13 | @IBOutlet weak var tableView: UITableView!
14 |
15 | /// The `Notebook` objects being presented
16 | var notebooks: [Notebook] = []
17 |
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 | navigationItem.titleView = UIImageView(image: #imageLiteral(resourceName: "toolbar-cow"))
21 | navigationItem.rightBarButtonItem = editButtonItem
22 | updateEditButtonState()
23 | }
24 |
25 | override func viewWillAppear(_ animated: Bool) {
26 | super.viewWillAppear(animated)
27 |
28 | if let indexPath = tableView.indexPathForSelectedRow {
29 | tableView.deselectRow(at: indexPath, animated: false)
30 | tableView.reloadRows(at: [indexPath], with: .fade)
31 | }
32 | }
33 |
34 | // -------------------------------------------------------------------------
35 | // MARK: - Actions
36 |
37 | @IBAction func addTapped(sender: Any) {
38 | presentNewNotebookAlert()
39 | }
40 |
41 | // -------------------------------------------------------------------------
42 | // MARK: - Editing
43 |
44 | /// Display an alert prompting the user to name a new notebook. Calls
45 | /// `addNotebook(name:)`.
46 | func presentNewNotebookAlert() {
47 | let alert = UIAlertController(title: "New Notebook", message: "Enter a name for this notebook", preferredStyle: .alert)
48 |
49 | // Create actions
50 | let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
51 | let saveAction = UIAlertAction(title: "Save", style: .default) { [weak self] action in
52 | if let name = alert.textFields?.first?.text {
53 | self?.addNotebook(name: name)
54 | }
55 | }
56 | saveAction.isEnabled = false
57 |
58 | // Add a text field
59 | alert.addTextField { textField in
60 | textField.placeholder = "Name"
61 | NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification, object: textField, queue: .main) { notif in
62 | if let text = textField.text, !text.isEmpty {
63 | saveAction.isEnabled = true
64 | } else {
65 | saveAction.isEnabled = false
66 | }
67 | }
68 | }
69 |
70 | alert.addAction(cancelAction)
71 | alert.addAction(saveAction)
72 | present(alert, animated: true, completion: nil)
73 | }
74 |
75 | /// Adds a new notebook to the end of the `notebooks` array
76 | func addNotebook(name: String) {
77 | let notebook = Notebook(name: name)
78 | notebooks.append(notebook)
79 | tableView.insertRows(at: [IndexPath(row: numberOfNotebooks - 1, section: 0)], with: .fade)
80 | updateEditButtonState()
81 | }
82 |
83 | /// Deletes the notebook at the specified index path
84 | func deleteNotebook(at indexPath: IndexPath) {
85 | notebooks.remove(at: indexPath.row)
86 | tableView.deleteRows(at: [indexPath], with: .fade)
87 | if numberOfNotebooks == 0 {
88 | setEditing(false, animated: true)
89 | }
90 | updateEditButtonState()
91 | }
92 |
93 | func updateEditButtonState() {
94 | navigationItem.rightBarButtonItem?.isEnabled = numberOfNotebooks > 0
95 | }
96 |
97 | override func setEditing(_ editing: Bool, animated: Bool) {
98 | super.setEditing(editing, animated: animated)
99 | tableView.setEditing(editing, animated: animated)
100 | }
101 |
102 | // -------------------------------------------------------------------------
103 | // MARK: - Table view data source
104 |
105 | func numberOfSections(in tableView: UITableView) -> Int {
106 | return 1
107 | }
108 |
109 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
110 | return numberOfNotebooks
111 | }
112 |
113 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
114 | let aNotebook = notebook(at: indexPath)
115 | let cell = tableView.dequeueReusableCell(withIdentifier: NotebookCell.defaultReuseIdentifier, for: indexPath) as! NotebookCell
116 |
117 | // Configure cell
118 | cell.nameLabel.text = aNotebook.name
119 | let pageString = aNotebook.notes.count == 1 ? "page" : "pages"
120 | cell.pageCountLabel.text = "\(aNotebook.notes.count) \(pageString)"
121 |
122 | return cell
123 | }
124 |
125 | func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
126 | switch editingStyle {
127 | case .delete: deleteNotebook(at: indexPath)
128 | default: () // Unsupported
129 | }
130 | }
131 |
132 | // Helper
133 |
134 | var numberOfNotebooks: Int { return notebooks.count }
135 |
136 | func notebook(at indexPath: IndexPath) -> Notebook {
137 | return notebooks[indexPath.row]
138 | }
139 |
140 | // -------------------------------------------------------------------------
141 | // MARK: - Navigation
142 |
143 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
144 | // If this is a NotesListViewController, we'll configure its `Notebook`
145 | if let vc = segue.destination as? NotesListViewController {
146 | if let indexPath = tableView.indexPathForSelectedRow {
147 | vc.notebook = notebook(at: indexPath)
148 | }
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/View Controllers/NotesListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotesListViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CoreData
11 |
12 | class NotesListViewController: UIViewController, UITableViewDataSource {
13 | /// A table view that displays a list of notes for a notebook
14 | @IBOutlet weak var tableView: UITableView!
15 |
16 | /// The notebook whose notes are being displayed
17 | var notebook: Notebook!
18 |
19 | var dataController:DataController!
20 |
21 | var fetchedResultsController:NSFetchedResultsController!
22 |
23 | /// A date formatter for date text in note cells
24 | let dateFormatter: DateFormatter = {
25 | let df = DateFormatter()
26 | df.dateStyle = .medium
27 | return df
28 | }()
29 |
30 | fileprivate func setupFetchedResultsController() {
31 | let fetchRequest:NSFetchRequest = Note.fetchRequest()
32 | let predicate = NSPredicate(format: "notebook == %@", notebook)
33 | fetchRequest.predicate = predicate
34 | let sortDescriptor = NSSortDescriptor(key: "creationDate", ascending: true)
35 | fetchRequest.sortDescriptors = [sortDescriptor]
36 |
37 | fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: dataController.viewContext, sectionNameKeyPath: nil, cacheName: "\(notebook)-notes")
38 | fetchedResultsController.delegate = self
39 |
40 | do {
41 | try fetchedResultsController.performFetch()
42 | } catch {
43 | fatalError("The fetch could not be performed: \(error.localizedDescription)")
44 | }
45 | }
46 |
47 | override func viewDidLoad() {
48 | super.viewDidLoad()
49 |
50 | navigationItem.title = notebook.name
51 | navigationItem.rightBarButtonItem = editButtonItem
52 |
53 | setupFetchedResultsController()
54 |
55 | updateEditButtonState()
56 | }
57 |
58 | override func viewWillAppear(_ animated: Bool) {
59 | super.viewWillAppear(animated)
60 | setupFetchedResultsController()
61 | if let indexPath = tableView.indexPathForSelectedRow {
62 | tableView.deselectRow(at: indexPath, animated: false)
63 | tableView.reloadRows(at: [indexPath], with: .fade)
64 | }
65 | }
66 |
67 | override func viewDidDisappear(_ animated: Bool) {
68 | super.viewDidDisappear(animated)
69 | fetchedResultsController = nil
70 | }
71 |
72 | // -------------------------------------------------------------------------
73 | // MARK: - Actions
74 |
75 | @IBAction func addTapped(sender: Any) {
76 | addNote()
77 | }
78 |
79 | // -------------------------------------------------------------------------
80 | // MARK: - Editing
81 |
82 | // Adds a new `Note` to the end of the `notebook`'s `notes` array
83 | func addNote() {
84 | let note = Note(context: dataController.viewContext)
85 | note.creationDate = Date()
86 | note.notebook = notebook
87 | try? dataController.viewContext.save()
88 | }
89 |
90 | // Deletes the `Note` at the specified index path
91 | func deleteNote(at indexPath: IndexPath) {
92 | let noteToDelete = fetchedResultsController.object(at: indexPath)
93 | dataController.viewContext.delete(noteToDelete)
94 | try? dataController.viewContext.save()
95 | }
96 |
97 | func updateEditButtonState() {
98 | navigationItem.rightBarButtonItem?.isEnabled = fetchedResultsController.sections![0].numberOfObjects > 0
99 | }
100 |
101 | override func setEditing(_ editing: Bool, animated: Bool) {
102 | super.setEditing(editing, animated: animated)
103 | tableView.setEditing(editing, animated: animated)
104 | }
105 |
106 | // -------------------------------------------------------------------------
107 | // MARK: - Table view data source
108 |
109 | func numberOfSections(in tableView: UITableView) -> Int {
110 | return fetchedResultsController.sections?.count ?? 1
111 | }
112 |
113 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
114 | return fetchedResultsController.sections?[0].numberOfObjects ?? 0
115 | }
116 |
117 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
118 | let aNote = fetchedResultsController.object(at: indexPath)
119 | let cell = tableView.dequeueReusableCell(withIdentifier: NoteCell.defaultReuseIdentifier, for: indexPath) as! NoteCell
120 |
121 | // Configure cell
122 | cell.textPreviewLabel.attributedText = aNote.attributedText
123 |
124 | if let creationDate = aNote.creationDate {
125 | cell.dateLabel.text = dateFormatter.string(from: creationDate)
126 | }
127 |
128 | return cell
129 | }
130 |
131 | func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
132 | switch editingStyle {
133 | case .delete: deleteNote(at: indexPath)
134 | default: () // Unsupported
135 | }
136 | }
137 |
138 | // -------------------------------------------------------------------------
139 | // MARK: - Navigation
140 |
141 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
142 | // If this is a NoteDetailsViewController, we'll configure its `Note`
143 | // and its delete action
144 | if let vc = segue.destination as? NoteDetailsViewController {
145 | if let indexPath = tableView.indexPathForSelectedRow {
146 | vc.note = fetchedResultsController.object(at: indexPath)
147 | vc.dataController = dataController
148 |
149 | vc.onDelete = { [weak self] in
150 | if let indexPath = self?.tableView.indexPathForSelectedRow {
151 | self?.deleteNote(at: indexPath)
152 | self?.navigationController?.popViewController(animated: true)
153 | }
154 | }
155 | }
156 | }
157 | }
158 | }
159 |
160 | extension NotesListViewController:NSFetchedResultsControllerDelegate {
161 |
162 | func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
163 | switch type {
164 | case .insert:
165 | tableView.insertRows(at: [newIndexPath!], with: .fade)
166 | break
167 | case .delete:
168 | tableView.deleteRows(at: [indexPath!], with: .fade)
169 | break
170 | case .update:
171 | tableView.reloadRows(at: [indexPath!], with: .fade)
172 | case .move:
173 | tableView.moveRow(at: indexPath!, to: newIndexPath!)
174 | }
175 | }
176 |
177 | func controller(_ controller: NSFetchedResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
178 | let indexSet = IndexSet(integer: sectionIndex)
179 | switch type {
180 | case .insert: tableView.insertSections(indexSet, with: .fade)
181 | case .delete: tableView.deleteSections(indexSet, with: .fade)
182 | case .update, .move:
183 | fatalError("Invalid change type in controller(_:didChange:atSectionIndex:for:). Only .insert or .delete should be possible.")
184 | }
185 | }
186 |
187 |
188 | func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
189 | tableView.beginUpdates()
190 | }
191 |
192 | func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
193 | tableView.endUpdates()
194 | }
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/View Controllers/NotebooksListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotebooksListViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CoreData
11 |
12 | class NotebooksListViewController: UIViewController, UITableViewDataSource {
13 | /// A table view that displays a list of notebooks
14 | @IBOutlet weak var tableView: UITableView!
15 |
16 | var dataController:DataController!
17 |
18 | var fetchedResultsController:NSFetchedResultsController!
19 |
20 | fileprivate func setupFetchedResultsController() {
21 | let fetchRequest:NSFetchRequest = Notebook.fetchRequest()
22 | let sortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
23 | fetchRequest.sortDescriptors = [sortDescriptor]
24 |
25 | fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: dataController.viewContext, sectionNameKeyPath: nil, cacheName: "notebooks")
26 | fetchedResultsController.delegate = self
27 | do {
28 | try fetchedResultsController.performFetch()
29 | } catch {
30 | fatalError("The fetch could not be performed: \(error.localizedDescription)")
31 | }
32 | }
33 |
34 | override func viewDidLoad() {
35 | super.viewDidLoad()
36 | navigationItem.titleView = UIImageView(image: #imageLiteral(resourceName: "toolbar-cow"))
37 | navigationItem.rightBarButtonItem = editButtonItem
38 |
39 | setupFetchedResultsController()
40 | }
41 |
42 | override func viewWillAppear(_ animated: Bool) {
43 | super.viewWillAppear(animated)
44 | setupFetchedResultsController()
45 | if let indexPath = tableView.indexPathForSelectedRow {
46 | tableView.deselectRow(at: indexPath, animated: false)
47 | tableView.reloadRows(at: [indexPath], with: .fade)
48 | }
49 | }
50 |
51 | override func viewDidDisappear(_ animated: Bool) {
52 | super.viewDidDisappear(animated)
53 | fetchedResultsController = nil
54 | }
55 |
56 | // -------------------------------------------------------------------------
57 | // MARK: - Actions
58 |
59 | @IBAction func addTapped(sender: Any) {
60 | presentNewNotebookAlert()
61 | }
62 |
63 | // -------------------------------------------------------------------------
64 | // MARK: - Editing
65 |
66 | /// Display an alert prompting the user to name a new notebook. Calls
67 | /// `addNotebook(name:)`.
68 | func presentNewNotebookAlert() {
69 | let alert = UIAlertController(title: "New Notebook", message: "Enter a name for this notebook", preferredStyle: .alert)
70 |
71 | // Create actions
72 | let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
73 | let saveAction = UIAlertAction(title: "Save", style: .default) { [weak self] action in
74 | if let name = alert.textFields?.first?.text {
75 | self?.addNotebook(name: name)
76 | }
77 | }
78 | saveAction.isEnabled = false
79 |
80 | // Add a text field
81 | alert.addTextField { textField in
82 | textField.placeholder = "Name"
83 | NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification, object: textField, queue: .main) { notif in
84 | if let text = textField.text, !text.isEmpty {
85 | saveAction.isEnabled = true
86 | } else {
87 | saveAction.isEnabled = false
88 | }
89 | }
90 | }
91 |
92 | alert.addAction(cancelAction)
93 | alert.addAction(saveAction)
94 | present(alert, animated: true, completion: nil)
95 | }
96 |
97 | /// Adds a new notebook to the end of the `notebooks` array
98 | func addNotebook(name: String) {
99 | let notebook = Notebook(context: dataController.viewContext)
100 | notebook.name = name
101 | notebook.creationDate = Date()
102 | try? dataController.viewContext.save()
103 | }
104 |
105 | /// Deletes the notebook at the specified index path
106 | func deleteNotebook(at indexPath: IndexPath) {
107 | let notebookToDelete = fetchedResultsController.object(at: indexPath)
108 | dataController.viewContext.delete(notebookToDelete)
109 | try? dataController.viewContext.save()
110 | }
111 |
112 | func updateEditButtonState() {
113 | if let sections = fetchedResultsController.sections {
114 | navigationItem.rightBarButtonItem?.isEnabled = sections[0].numberOfObjects > 0
115 | }
116 | }
117 |
118 | override func setEditing(_ editing: Bool, animated: Bool) {
119 | super.setEditing(editing, animated: animated)
120 | tableView.setEditing(editing, animated: animated)
121 | }
122 |
123 | // -------------------------------------------------------------------------
124 | // MARK: - Table view data source
125 |
126 | func numberOfSections(in tableView: UITableView) -> Int {
127 | return fetchedResultsController.sections?.count ?? 1
128 | }
129 |
130 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
131 | return fetchedResultsController.sections?[section].numberOfObjects ?? 0
132 | }
133 |
134 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
135 | let aNotebook = fetchedResultsController.object(at: indexPath)
136 | let cell = tableView.dequeueReusableCell(withIdentifier: NotebookCell.defaultReuseIdentifier, for: indexPath) as! NotebookCell
137 |
138 | // Configure cell
139 | cell.nameLabel.text = aNotebook.name
140 |
141 | if let count = aNotebook.notes?.count {
142 | let pageString = count == 1 ? "page" : "pages"
143 | cell.pageCountLabel.text = "\(count) \(pageString)"
144 | }
145 |
146 | return cell
147 | }
148 |
149 | func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
150 | switch editingStyle {
151 | case .delete: deleteNotebook(at: indexPath)
152 | default: () // Unsupported
153 | }
154 | }
155 |
156 | // -------------------------------------------------------------------------
157 | // MARK: - Navigation
158 |
159 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
160 | // If this is a NotesListViewController, we'll configure its `Notebook`
161 | if let vc = segue.destination as? NotesListViewController {
162 | if let indexPath = tableView.indexPathForSelectedRow {
163 | vc.notebook = fetchedResultsController.object(at: indexPath)
164 | vc.dataController = dataController
165 | }
166 | }
167 | }
168 | }
169 |
170 | extension NotebooksListViewController:NSFetchedResultsControllerDelegate {
171 |
172 | func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
173 | switch type {
174 | case .insert:
175 | tableView.insertRows(at: [newIndexPath!], with: .fade)
176 | break
177 | case .delete:
178 | tableView.deleteRows(at: [indexPath!], with: .fade)
179 | break
180 | case .update:
181 | tableView.reloadRows(at: [indexPath!], with: .fade)
182 | case .move:
183 | tableView.moveRow(at: indexPath!, to: newIndexPath!)
184 | }
185 | }
186 |
187 | func controller(_ controller: NSFetchedResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
188 | let indexSet = IndexSet(integer: sectionIndex)
189 | switch type {
190 | case .insert: tableView.insertSections(indexSet, with: .fade)
191 | case .delete: tableView.deleteSections(indexSet, with: .fade)
192 | case .update, .move:
193 | fatalError("Invalid change type in controller(_:didChange:atSectionIndex:for:). Only .insert or .delete should be possible.")
194 | }
195 | }
196 |
197 |
198 | func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
199 | tableView.beginUpdates()
200 | }
201 |
202 | func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
203 | tableView.endUpdates()
204 | }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/View Controllers/NoteDetailsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteDetailsViewController.swift
3 | // Mooskine
4 | //
5 | // Created by Josh Svatek on 2017-05-31.
6 | // Copyright © 2017 Udacity. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CoreData
11 |
12 | class NoteDetailsViewController: UIViewController {
13 | /// A text view that displays a note's text
14 | @IBOutlet weak var textView: UITextView!
15 |
16 | /// The note being displayed and edited
17 | var note: Note!
18 |
19 | var dataController:DataController!
20 |
21 | var saveObserverToken: Any?
22 |
23 | /// A closure that is run when the user asks to delete the current note
24 | var onDelete: (() -> Void)?
25 |
26 | /// A date formatter for the view controller's title text
27 | let dateFormatter: DateFormatter = {
28 | let df = DateFormatter()
29 | df.dateStyle = .medium
30 | return df
31 | }()
32 |
33 | /// The accessory view used when displaying the keyboard
34 | var keyboardToolbar: UIToolbar?
35 |
36 | override func viewDidLoad() {
37 | super.viewDidLoad()
38 |
39 | if let creationDate = note.creationDate {
40 | navigationItem.title = dateFormatter.string(from: creationDate)
41 | }
42 | textView.attributedText = note.attributedText
43 |
44 | // keyboard toolbar configuration
45 | configureToolbarItems()
46 | configureTextViewInputAccessoryView()
47 |
48 | addSaveNotificationObserver()
49 | }
50 |
51 | deinit {
52 | removeSaveNotificationObserver()
53 | }
54 |
55 | @IBAction func deleteNote(sender: Any) {
56 | presentDeleteNotebookAlert()
57 | }
58 | }
59 |
60 | // -----------------------------------------------------------------------------
61 | // MARK: - Editing
62 |
63 | extension NoteDetailsViewController {
64 | func presentDeleteNotebookAlert() {
65 | let alert = UIAlertController(title: "Delete Note", message: "Do you want to delete this note?", preferredStyle: .alert)
66 | alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
67 | alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: deleteHandler))
68 | present(alert, animated: true, completion: nil)
69 | }
70 |
71 | func deleteHandler(alertAction: UIAlertAction) {
72 | onDelete?()
73 | }
74 | }
75 |
76 | // -----------------------------------------------------------------------------
77 | // MARK: - UITextViewDelegate
78 |
79 | extension NoteDetailsViewController: UITextViewDelegate {
80 | func textViewDidEndEditing(_ textView: UITextView) {
81 | note.attributedText = textView.attributedText
82 | try? dataController.viewContext.save()
83 | }
84 | }
85 |
86 | // MARK: - Toolbar
87 |
88 | extension NoteDetailsViewController {
89 | /// Returns an array of toolbar items. Used to configure the view controller's
90 | /// `toolbarItems' property, and to configure an accessory view for the
91 | /// text view's keyboard that also displays these items.
92 | func makeToolbarItems() -> [UIBarButtonItem] {
93 | let trash = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(deleteTapped(sender:)))
94 | let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
95 | let bold = UIBarButtonItem(image: #imageLiteral(resourceName: "toolbar-bold"), style: .plain, target: self, action: #selector(boldTapped(sender:)))
96 | let red = UIBarButtonItem(image: #imageLiteral(resourceName: "toolbar-underline"), style: .plain, target: self, action: #selector(redTapped(sender:)))
97 | let cow = UIBarButtonItem(image: #imageLiteral(resourceName: "toolbar-cow"), style: .plain, target: self, action: #selector(cowTapped(sender:)))
98 |
99 | return [space, trash, space, bold, space, red, space, cow, space]
100 | }
101 |
102 | /// Configure the current toolbar
103 | func configureToolbarItems() {
104 | toolbarItems = makeToolbarItems()
105 | navigationController?.setToolbarHidden(false, animated: false)
106 | }
107 |
108 | /// Configure the text view's input accessory view -- this is the view that
109 | /// appears above the keyboard. We'll return a toolbar populated with our
110 | /// view controller's toolbar items, so that the toolbar functionality isn't
111 | /// hidden when the keyboard appears
112 | func configureTextViewInputAccessoryView() {
113 | let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 44))
114 | toolbar.items = makeToolbarItems()
115 | textView.inputAccessoryView = toolbar
116 | }
117 |
118 | @IBAction func deleteTapped(sender: Any) {
119 | showDeleteAlert()
120 | }
121 |
122 | @IBAction func boldTapped(sender: Any) {
123 | let newText = textView.attributedText.mutableCopy() as! NSMutableAttributedString
124 | newText.addAttribute(.font, value: UIFont(name: "OpenSans-Bold", size: 22) as Any, range: textView.selectedRange)
125 |
126 | let selectedTextRange = textView.selectedTextRange
127 |
128 | textView.attributedText = newText
129 | textView.selectedTextRange = selectedTextRange
130 | note.attributedText = textView.attributedText
131 | ((try? dataController?.viewContext.save()) as ()??)
132 | }
133 |
134 | @IBAction func redTapped(sender: Any) {
135 | let newText = textView.attributedText.mutableCopy() as! NSMutableAttributedString
136 | let attributes: [NSAttributedString.Key: Any] = [
137 | .foregroundColor: UIColor.red,
138 | .underlineStyle: 1,
139 | .underlineColor: UIColor.red
140 | ]
141 | newText.addAttributes(attributes, range: textView.selectedRange)
142 |
143 | let selectedTextRange = textView.selectedTextRange
144 |
145 | textView.attributedText = newText
146 | textView.selectedTextRange = selectedTextRange
147 | note.attributedText = textView.attributedText
148 | try? dataController?.viewContext.save()
149 | }
150 |
151 | @IBAction func cowTapped(sender: Any) {
152 | let backgroundContext:NSManagedObjectContext! = dataController?.backgroundContext
153 |
154 | let newText = textView.attributedText.mutableCopy() as! NSMutableAttributedString
155 |
156 | let selectedRange = textView.selectedRange
157 | let selectedText = textView.attributedText.attributedSubstring(from: selectedRange)
158 |
159 | let noteID = note.objectID
160 |
161 | dataController?.backgroundContext.perform {
162 | let backgroundNote = backgroundContext.object(with: noteID) as! Note
163 |
164 | let cowText = Pathifier.makeMutableAttributedString(for: selectedText, withFont: UIFont(name: "AvenirNext-Heavy", size: 56)!, withPatternImage: #imageLiteral(resourceName: "texture-cow"))
165 |
166 | sleep(5)
167 |
168 | newText.replaceCharacters(in: selectedRange, with: cowText)
169 |
170 | backgroundNote.attributedText = newText
171 | try? backgroundContext.save()
172 | }
173 | }
174 |
175 | // MARK: Helper methods for actions
176 | private func showDeleteAlert() {
177 | let alert = UIAlertController(title: "Delete Note?", message: "Are you sure you want to delete the current note?", preferredStyle: .alert)
178 |
179 | let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
180 | let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { [weak self] _ in
181 | guard let strongSelf = self else { return }
182 | strongSelf.onDelete?()
183 | }
184 |
185 | alert.addAction(cancelAction)
186 | alert.addAction(deleteAction)
187 | present(alert, animated: true, completion: nil)
188 | }
189 | }
190 |
191 | extension NoteDetailsViewController {
192 |
193 | func addSaveNotificationObserver() {
194 | removeSaveNotificationObserver()
195 | saveObserverToken = NotificationCenter.default.addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: dataController?.viewContext, queue: nil, using: handleSaveNotification(notification:))
196 | }
197 |
198 | func removeSaveNotificationObserver() {
199 | if let token = saveObserverToken {
200 | NotificationCenter.default.removeObserver(token)
201 | }
202 | }
203 |
204 | fileprivate func reloadText() {
205 | textView.attributedText = note.attributedText
206 | }
207 |
208 | func handleSaveNotification(notification:Notification) {
209 | DispatchQueue.main.async {
210 | self.reloadText()
211 | }
212 | }
213 | }
214 |
215 |
--------------------------------------------------------------------------------
/SandboxPlayground-Empty/SandboxPlayground.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A9CCAFD51D37C53C00E00DAF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9CCAFD31D37C53C00E00DAF /* LaunchScreen.xib */; };
11 | EDA163371CE69ECA009671EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA163361CE69ECA009671EE /* AppDelegate.swift */; };
12 | EDA163391CE69ECA009671EE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA163381CE69ECA009671EE /* ViewController.swift */; };
13 | EDA1633C1CE69ECA009671EE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EDA1633A1CE69ECA009671EE /* Main.storyboard */; };
14 | EDA1633E1CE69ECA009671EE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EDA1633D1CE69ECA009671EE /* Assets.xcassets */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | A9CCAFD41D37C53C00E00DAF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
19 | EDA163331CE69ECA009671EE /* SandboxPlayground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SandboxPlayground.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | EDA163361CE69ECA009671EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
21 | EDA163381CE69ECA009671EE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
22 | EDA1633B1CE69ECA009671EE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
23 | EDA1633D1CE69ECA009671EE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
24 | EDA163421CE69ECB009671EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
25 | /* End PBXFileReference section */
26 |
27 | /* Begin PBXFrameworksBuildPhase section */
28 | EDA163301CE69ECA009671EE /* Frameworks */ = {
29 | isa = PBXFrameworksBuildPhase;
30 | buildActionMask = 2147483647;
31 | files = (
32 | );
33 | runOnlyForDeploymentPostprocessing = 0;
34 | };
35 | /* End PBXFrameworksBuildPhase section */
36 |
37 | /* Begin PBXGroup section */
38 | A9CCAFD61D37C54100E00DAF /* Assets */ = {
39 | isa = PBXGroup;
40 | children = (
41 | EDA1633A1CE69ECA009671EE /* Main.storyboard */,
42 | A9CCAFD31D37C53C00E00DAF /* LaunchScreen.xib */,
43 | EDA1633D1CE69ECA009671EE /* Assets.xcassets */,
44 | );
45 | name = Assets;
46 | sourceTree = "";
47 | };
48 | A9CCAFD71D37C54500E00DAF /* Supporting Files */ = {
49 | isa = PBXGroup;
50 | children = (
51 | EDA163421CE69ECB009671EE /* Info.plist */,
52 | );
53 | name = "Supporting Files";
54 | sourceTree = "";
55 | };
56 | EDA1632A1CE69ECA009671EE = {
57 | isa = PBXGroup;
58 | children = (
59 | EDA163351CE69ECA009671EE /* SandboxPlayground */,
60 | EDA163341CE69ECA009671EE /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | EDA163341CE69ECA009671EE /* Products */ = {
65 | isa = PBXGroup;
66 | children = (
67 | EDA163331CE69ECA009671EE /* SandboxPlayground.app */,
68 | );
69 | name = Products;
70 | sourceTree = "";
71 | };
72 | EDA163351CE69ECA009671EE /* SandboxPlayground */ = {
73 | isa = PBXGroup;
74 | children = (
75 | EDA163361CE69ECA009671EE /* AppDelegate.swift */,
76 | EDA163381CE69ECA009671EE /* ViewController.swift */,
77 | A9CCAFD61D37C54100E00DAF /* Assets */,
78 | A9CCAFD71D37C54500E00DAF /* Supporting Files */,
79 | );
80 | path = SandboxPlayground;
81 | sourceTree = "";
82 | };
83 | /* End PBXGroup section */
84 |
85 | /* Begin PBXNativeTarget section */
86 | EDA163321CE69ECA009671EE /* SandboxPlayground */ = {
87 | isa = PBXNativeTarget;
88 | buildConfigurationList = EDA163501CE69ECB009671EE /* Build configuration list for PBXNativeTarget "SandboxPlayground" */;
89 | buildPhases = (
90 | EDA1632F1CE69ECA009671EE /* Sources */,
91 | EDA163301CE69ECA009671EE /* Frameworks */,
92 | EDA163311CE69ECA009671EE /* Resources */,
93 | );
94 | buildRules = (
95 | );
96 | dependencies = (
97 | );
98 | name = SandboxPlayground;
99 | productName = SandboxPlayground;
100 | productReference = EDA163331CE69ECA009671EE /* SandboxPlayground.app */;
101 | productType = "com.apple.product-type.application";
102 | };
103 | /* End PBXNativeTarget section */
104 |
105 | /* Begin PBXProject section */
106 | EDA1632B1CE69ECA009671EE /* Project object */ = {
107 | isa = PBXProject;
108 | attributes = {
109 | LastSwiftUpdateCheck = 0730;
110 | LastUpgradeCheck = 1020;
111 | ORGANIZATIONNAME = udacity.com;
112 | TargetAttributes = {
113 | EDA163321CE69ECA009671EE = {
114 | CreatedOnToolsVersion = 7.3;
115 | LastSwiftMigration = 0800;
116 | };
117 | };
118 | };
119 | buildConfigurationList = EDA1632E1CE69ECA009671EE /* Build configuration list for PBXProject "SandboxPlayground" */;
120 | compatibilityVersion = "Xcode 3.2";
121 | developmentRegion = en;
122 | hasScannedForEncodings = 0;
123 | knownRegions = (
124 | en,
125 | Base,
126 | );
127 | mainGroup = EDA1632A1CE69ECA009671EE;
128 | productRefGroup = EDA163341CE69ECA009671EE /* Products */;
129 | projectDirPath = "";
130 | projectRoot = "";
131 | targets = (
132 | EDA163321CE69ECA009671EE /* SandboxPlayground */,
133 | );
134 | };
135 | /* End PBXProject section */
136 |
137 | /* Begin PBXResourcesBuildPhase section */
138 | EDA163311CE69ECA009671EE /* Resources */ = {
139 | isa = PBXResourcesBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | EDA1633E1CE69ECA009671EE /* Assets.xcassets in Resources */,
143 | A9CCAFD51D37C53C00E00DAF /* LaunchScreen.xib in Resources */,
144 | EDA1633C1CE69ECA009671EE /* Main.storyboard in Resources */,
145 | );
146 | runOnlyForDeploymentPostprocessing = 0;
147 | };
148 | /* End PBXResourcesBuildPhase section */
149 |
150 | /* Begin PBXSourcesBuildPhase section */
151 | EDA1632F1CE69ECA009671EE /* Sources */ = {
152 | isa = PBXSourcesBuildPhase;
153 | buildActionMask = 2147483647;
154 | files = (
155 | EDA163391CE69ECA009671EE /* ViewController.swift in Sources */,
156 | EDA163371CE69ECA009671EE /* AppDelegate.swift in Sources */,
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | /* End PBXSourcesBuildPhase section */
161 |
162 | /* Begin PBXVariantGroup section */
163 | A9CCAFD31D37C53C00E00DAF /* LaunchScreen.xib */ = {
164 | isa = PBXVariantGroup;
165 | children = (
166 | A9CCAFD41D37C53C00E00DAF /* Base */,
167 | );
168 | name = LaunchScreen.xib;
169 | sourceTree = "";
170 | };
171 | EDA1633A1CE69ECA009671EE /* Main.storyboard */ = {
172 | isa = PBXVariantGroup;
173 | children = (
174 | EDA1633B1CE69ECA009671EE /* Base */,
175 | );
176 | name = Main.storyboard;
177 | sourceTree = "";
178 | };
179 | /* End PBXVariantGroup section */
180 |
181 | /* Begin XCBuildConfiguration section */
182 | EDA1634E1CE69ECB009671EE /* Debug */ = {
183 | isa = XCBuildConfiguration;
184 | buildSettings = {
185 | ALWAYS_SEARCH_USER_PATHS = NO;
186 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
187 | CLANG_ANALYZER_NONNULL = YES;
188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
189 | CLANG_CXX_LIBRARY = "libc++";
190 | CLANG_ENABLE_MODULES = YES;
191 | CLANG_ENABLE_OBJC_ARC = YES;
192 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
193 | CLANG_WARN_BOOL_CONVERSION = YES;
194 | CLANG_WARN_COMMA = YES;
195 | CLANG_WARN_CONSTANT_CONVERSION = YES;
196 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
197 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
198 | CLANG_WARN_EMPTY_BODY = YES;
199 | CLANG_WARN_ENUM_CONVERSION = YES;
200 | CLANG_WARN_INFINITE_RECURSION = YES;
201 | CLANG_WARN_INT_CONVERSION = YES;
202 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
203 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
204 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
206 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
207 | CLANG_WARN_STRICT_PROTOTYPES = YES;
208 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
209 | CLANG_WARN_UNREACHABLE_CODE = YES;
210 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
211 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
212 | COPY_PHASE_STRIP = NO;
213 | DEBUG_INFORMATION_FORMAT = dwarf;
214 | ENABLE_STRICT_OBJC_MSGSEND = YES;
215 | ENABLE_TESTABILITY = YES;
216 | GCC_C_LANGUAGE_STANDARD = gnu99;
217 | GCC_DYNAMIC_NO_PIC = NO;
218 | GCC_NO_COMMON_BLOCKS = YES;
219 | GCC_OPTIMIZATION_LEVEL = 0;
220 | GCC_PREPROCESSOR_DEFINITIONS = (
221 | "DEBUG=1",
222 | "$(inherited)",
223 | );
224 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
225 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
226 | GCC_WARN_UNDECLARED_SELECTOR = YES;
227 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
228 | GCC_WARN_UNUSED_FUNCTION = YES;
229 | GCC_WARN_UNUSED_VARIABLE = YES;
230 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
231 | MTL_ENABLE_DEBUG_INFO = YES;
232 | ONLY_ACTIVE_ARCH = YES;
233 | SDKROOT = iphoneos;
234 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
235 | SWIFT_VERSION = 5.0;
236 | };
237 | name = Debug;
238 | };
239 | EDA1634F1CE69ECB009671EE /* Release */ = {
240 | isa = XCBuildConfiguration;
241 | buildSettings = {
242 | ALWAYS_SEARCH_USER_PATHS = NO;
243 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
244 | CLANG_ANALYZER_NONNULL = YES;
245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
246 | CLANG_CXX_LIBRARY = "libc++";
247 | CLANG_ENABLE_MODULES = YES;
248 | CLANG_ENABLE_OBJC_ARC = YES;
249 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
250 | CLANG_WARN_BOOL_CONVERSION = YES;
251 | CLANG_WARN_COMMA = YES;
252 | CLANG_WARN_CONSTANT_CONVERSION = YES;
253 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
254 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
255 | CLANG_WARN_EMPTY_BODY = YES;
256 | CLANG_WARN_ENUM_CONVERSION = YES;
257 | CLANG_WARN_INFINITE_RECURSION = YES;
258 | CLANG_WARN_INT_CONVERSION = YES;
259 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
260 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
261 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
262 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
263 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
264 | CLANG_WARN_STRICT_PROTOTYPES = YES;
265 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
266 | CLANG_WARN_UNREACHABLE_CODE = YES;
267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
269 | COPY_PHASE_STRIP = NO;
270 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
271 | ENABLE_NS_ASSERTIONS = NO;
272 | ENABLE_STRICT_OBJC_MSGSEND = YES;
273 | GCC_C_LANGUAGE_STANDARD = gnu99;
274 | GCC_NO_COMMON_BLOCKS = YES;
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
277 | GCC_WARN_UNDECLARED_SELECTOR = YES;
278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
279 | GCC_WARN_UNUSED_FUNCTION = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
282 | MTL_ENABLE_DEBUG_INFO = NO;
283 | SDKROOT = iphoneos;
284 | SWIFT_VERSION = 5.0;
285 | VALIDATE_PRODUCT = YES;
286 | };
287 | name = Release;
288 | };
289 | EDA163511CE69ECB009671EE /* Debug */ = {
290 | isa = XCBuildConfiguration;
291 | buildSettings = {
292 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
293 | INFOPLIST_FILE = SandboxPlayground/Info.plist;
294 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
295 | PRODUCT_BUNDLE_IDENTIFIER = com.udacity.SandboxPlayground;
296 | PRODUCT_NAME = "$(TARGET_NAME)";
297 | SWIFT_VERSION = 5.0;
298 | };
299 | name = Debug;
300 | };
301 | EDA163521CE69ECB009671EE /* Release */ = {
302 | isa = XCBuildConfiguration;
303 | buildSettings = {
304 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
305 | INFOPLIST_FILE = SandboxPlayground/Info.plist;
306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
307 | PRODUCT_BUNDLE_IDENTIFIER = com.udacity.SandboxPlayground;
308 | PRODUCT_NAME = "$(TARGET_NAME)";
309 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
310 | SWIFT_VERSION = 5.0;
311 | };
312 | name = Release;
313 | };
314 | /* End XCBuildConfiguration section */
315 |
316 | /* Begin XCConfigurationList section */
317 | EDA1632E1CE69ECA009671EE /* Build configuration list for PBXProject "SandboxPlayground" */ = {
318 | isa = XCConfigurationList;
319 | buildConfigurations = (
320 | EDA1634E1CE69ECB009671EE /* Debug */,
321 | EDA1634F1CE69ECB009671EE /* Release */,
322 | );
323 | defaultConfigurationIsVisible = 0;
324 | defaultConfigurationName = Release;
325 | };
326 | EDA163501CE69ECB009671EE /* Build configuration list for PBXNativeTarget "SandboxPlayground" */ = {
327 | isa = XCConfigurationList;
328 | buildConfigurations = (
329 | EDA163511CE69ECB009671EE /* Debug */,
330 | EDA163521CE69ECB009671EE /* Release */,
331 | );
332 | defaultConfigurationIsVisible = 0;
333 | defaultConfigurationName = Release;
334 | };
335 | /* End XCConfigurationList section */
336 | };
337 | rootObject = EDA1632B1CE69ECA009671EE /* Project object */;
338 | }
339 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4D37A77C1A5B089600294894 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D37A77B1A5B089600294894 /* AppDelegate.swift */; };
11 | 4D37A7811A5B089600294894 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4D37A77F1A5B089600294894 /* Main.storyboard */; };
12 | 4D37A7831A5B089600294894 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4D37A7821A5B089600294894 /* Images.xcassets */; };
13 | 4D37A7861A5B089600294894 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4D37A7841A5B089600294894 /* LaunchScreen.xib */; };
14 | 4D37A79E1A5B095200294894 /* PlaySoundsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D37A79B1A5B095200294894 /* PlaySoundsViewController.swift */; };
15 | 4D37A79F1A5B095200294894 /* RecordedAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D37A79C1A5B095200294894 /* RecordedAudio.swift */; };
16 | 4D37A7A01A5B095200294894 /* RecordSoundsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D37A79D1A5B095200294894 /* RecordSoundsViewController.swift */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | 4D37A7761A5B089600294894 /* PickYourPitch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PickYourPitch.app; sourceTree = BUILT_PRODUCTS_DIR; };
21 | 4D37A77A1A5B089600294894 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
22 | 4D37A77B1A5B089600294894 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
23 | 4D37A7801A5B089600294894 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
24 | 4D37A7821A5B089600294894 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
25 | 4D37A7851A5B089600294894 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
26 | 4D37A79B1A5B095200294894 /* PlaySoundsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaySoundsViewController.swift; sourceTree = ""; };
27 | 4D37A79C1A5B095200294894 /* RecordedAudio.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecordedAudio.swift; sourceTree = ""; };
28 | 4D37A79D1A5B095200294894 /* RecordSoundsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecordSoundsViewController.swift; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 4D37A7731A5B089600294894 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 4D37A76D1A5B089600294894 = {
43 | isa = PBXGroup;
44 | children = (
45 | 4D37A7781A5B089600294894 /* PickYourPitch */,
46 | 4D37A7771A5B089600294894 /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | 4D37A7771A5B089600294894 /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 4D37A7761A5B089600294894 /* PickYourPitch.app */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | 4D37A7781A5B089600294894 /* PickYourPitch */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 4D37A77B1A5B089600294894 /* AppDelegate.swift */,
62 | 4D37A79C1A5B095200294894 /* RecordedAudio.swift */,
63 | 4D37A79B1A5B095200294894 /* PlaySoundsViewController.swift */,
64 | 4D37A79D1A5B095200294894 /* RecordSoundsViewController.swift */,
65 | A9CCAFD21D37C43C00E00DAF /* Assets */,
66 | 4D37A7791A5B089600294894 /* Supporting Files */,
67 | );
68 | path = PickYourPitch;
69 | sourceTree = "";
70 | };
71 | 4D37A7791A5B089600294894 /* Supporting Files */ = {
72 | isa = PBXGroup;
73 | children = (
74 | 4D37A77A1A5B089600294894 /* Info.plist */,
75 | );
76 | name = "Supporting Files";
77 | sourceTree = "";
78 | };
79 | A9CCAFD21D37C43C00E00DAF /* Assets */ = {
80 | isa = PBXGroup;
81 | children = (
82 | 4D37A77F1A5B089600294894 /* Main.storyboard */,
83 | 4D37A7821A5B089600294894 /* Images.xcassets */,
84 | 4D37A7841A5B089600294894 /* LaunchScreen.xib */,
85 | );
86 | name = Assets;
87 | sourceTree = "";
88 | };
89 | /* End PBXGroup section */
90 |
91 | /* Begin PBXNativeTarget section */
92 | 4D37A7751A5B089600294894 /* PickYourPitch */ = {
93 | isa = PBXNativeTarget;
94 | buildConfigurationList = 4D37A7951A5B089600294894 /* Build configuration list for PBXNativeTarget "PickYourPitch" */;
95 | buildPhases = (
96 | 4D37A7721A5B089600294894 /* Sources */,
97 | 4D37A7731A5B089600294894 /* Frameworks */,
98 | 4D37A7741A5B089600294894 /* Resources */,
99 | );
100 | buildRules = (
101 | );
102 | dependencies = (
103 | );
104 | name = PickYourPitch;
105 | productName = PickYourPitch;
106 | productReference = 4D37A7761A5B089600294894 /* PickYourPitch.app */;
107 | productType = "com.apple.product-type.application";
108 | };
109 | /* End PBXNativeTarget section */
110 |
111 | /* Begin PBXProject section */
112 | 4D37A76E1A5B089600294894 /* Project object */ = {
113 | isa = PBXProject;
114 | attributes = {
115 | LastSwiftUpdateCheck = 0700;
116 | LastUpgradeCheck = 1020;
117 | ORGANIZATIONNAME = Udacity;
118 | TargetAttributes = {
119 | 4D37A7751A5B089600294894 = {
120 | CreatedOnToolsVersion = 6.1.1;
121 | LastSwiftMigration = 1020;
122 | };
123 | };
124 | };
125 | buildConfigurationList = 4D37A7711A5B089600294894 /* Build configuration list for PBXProject "PickYourPitch" */;
126 | compatibilityVersion = "Xcode 3.2";
127 | developmentRegion = en;
128 | hasScannedForEncodings = 0;
129 | knownRegions = (
130 | en,
131 | Base,
132 | );
133 | mainGroup = 4D37A76D1A5B089600294894;
134 | productRefGroup = 4D37A7771A5B089600294894 /* Products */;
135 | projectDirPath = "";
136 | projectRoot = "";
137 | targets = (
138 | 4D37A7751A5B089600294894 /* PickYourPitch */,
139 | );
140 | };
141 | /* End PBXProject section */
142 |
143 | /* Begin PBXResourcesBuildPhase section */
144 | 4D37A7741A5B089600294894 /* Resources */ = {
145 | isa = PBXResourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 4D37A7811A5B089600294894 /* Main.storyboard in Resources */,
149 | 4D37A7861A5B089600294894 /* LaunchScreen.xib in Resources */,
150 | 4D37A7831A5B089600294894 /* Images.xcassets in Resources */,
151 | );
152 | runOnlyForDeploymentPostprocessing = 0;
153 | };
154 | /* End PBXResourcesBuildPhase section */
155 |
156 | /* Begin PBXSourcesBuildPhase section */
157 | 4D37A7721A5B089600294894 /* Sources */ = {
158 | isa = PBXSourcesBuildPhase;
159 | buildActionMask = 2147483647;
160 | files = (
161 | 4D37A79F1A5B095200294894 /* RecordedAudio.swift in Sources */,
162 | 4D37A79E1A5B095200294894 /* PlaySoundsViewController.swift in Sources */,
163 | 4D37A7A01A5B095200294894 /* RecordSoundsViewController.swift in Sources */,
164 | 4D37A77C1A5B089600294894 /* AppDelegate.swift in Sources */,
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | /* End PBXSourcesBuildPhase section */
169 |
170 | /* Begin PBXVariantGroup section */
171 | 4D37A77F1A5B089600294894 /* Main.storyboard */ = {
172 | isa = PBXVariantGroup;
173 | children = (
174 | 4D37A7801A5B089600294894 /* Base */,
175 | );
176 | name = Main.storyboard;
177 | sourceTree = "";
178 | };
179 | 4D37A7841A5B089600294894 /* LaunchScreen.xib */ = {
180 | isa = PBXVariantGroup;
181 | children = (
182 | 4D37A7851A5B089600294894 /* Base */,
183 | );
184 | name = LaunchScreen.xib;
185 | sourceTree = "";
186 | };
187 | /* End PBXVariantGroup section */
188 |
189 | /* Begin XCBuildConfiguration section */
190 | 4D37A7931A5B089600294894 /* Debug */ = {
191 | isa = XCBuildConfiguration;
192 | buildSettings = {
193 | ALWAYS_SEARCH_USER_PATHS = NO;
194 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
195 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
196 | CLANG_CXX_LIBRARY = "libc++";
197 | CLANG_ENABLE_MODULES = YES;
198 | CLANG_ENABLE_OBJC_ARC = YES;
199 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
200 | CLANG_WARN_BOOL_CONVERSION = YES;
201 | CLANG_WARN_COMMA = YES;
202 | CLANG_WARN_CONSTANT_CONVERSION = YES;
203 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
204 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
205 | CLANG_WARN_EMPTY_BODY = YES;
206 | CLANG_WARN_ENUM_CONVERSION = YES;
207 | CLANG_WARN_INFINITE_RECURSION = YES;
208 | CLANG_WARN_INT_CONVERSION = YES;
209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
210 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
213 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
214 | CLANG_WARN_STRICT_PROTOTYPES = YES;
215 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
216 | CLANG_WARN_UNREACHABLE_CODE = YES;
217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
218 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
219 | COPY_PHASE_STRIP = NO;
220 | ENABLE_STRICT_OBJC_MSGSEND = YES;
221 | ENABLE_TESTABILITY = YES;
222 | GCC_C_LANGUAGE_STANDARD = gnu99;
223 | GCC_DYNAMIC_NO_PIC = NO;
224 | GCC_NO_COMMON_BLOCKS = YES;
225 | GCC_OPTIMIZATION_LEVEL = 0;
226 | GCC_PREPROCESSOR_DEFINITIONS = (
227 | "DEBUG=1",
228 | "$(inherited)",
229 | );
230 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
233 | GCC_WARN_UNDECLARED_SELECTOR = YES;
234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
235 | GCC_WARN_UNUSED_FUNCTION = YES;
236 | GCC_WARN_UNUSED_VARIABLE = YES;
237 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
238 | MTL_ENABLE_DEBUG_INFO = YES;
239 | ONLY_ACTIVE_ARCH = YES;
240 | SDKROOT = iphoneos;
241 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
242 | };
243 | name = Debug;
244 | };
245 | 4D37A7941A5B089600294894 /* Release */ = {
246 | isa = XCBuildConfiguration;
247 | buildSettings = {
248 | ALWAYS_SEARCH_USER_PATHS = NO;
249 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
251 | CLANG_CXX_LIBRARY = "libc++";
252 | CLANG_ENABLE_MODULES = YES;
253 | CLANG_ENABLE_OBJC_ARC = YES;
254 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
255 | CLANG_WARN_BOOL_CONVERSION = YES;
256 | CLANG_WARN_COMMA = YES;
257 | CLANG_WARN_CONSTANT_CONVERSION = YES;
258 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
260 | CLANG_WARN_EMPTY_BODY = YES;
261 | CLANG_WARN_ENUM_CONVERSION = YES;
262 | CLANG_WARN_INFINITE_RECURSION = YES;
263 | CLANG_WARN_INT_CONVERSION = YES;
264 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
265 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
266 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
268 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
269 | CLANG_WARN_STRICT_PROTOTYPES = YES;
270 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
271 | CLANG_WARN_UNREACHABLE_CODE = YES;
272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
273 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
274 | COPY_PHASE_STRIP = YES;
275 | ENABLE_NS_ASSERTIONS = NO;
276 | ENABLE_STRICT_OBJC_MSGSEND = YES;
277 | GCC_C_LANGUAGE_STANDARD = gnu99;
278 | GCC_NO_COMMON_BLOCKS = YES;
279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
281 | GCC_WARN_UNDECLARED_SELECTOR = YES;
282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
283 | GCC_WARN_UNUSED_FUNCTION = YES;
284 | GCC_WARN_UNUSED_VARIABLE = YES;
285 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
286 | MTL_ENABLE_DEBUG_INFO = NO;
287 | SDKROOT = iphoneos;
288 | VALIDATE_PRODUCT = YES;
289 | };
290 | name = Release;
291 | };
292 | 4D37A7961A5B089600294894 /* Debug */ = {
293 | isa = XCBuildConfiguration;
294 | buildSettings = {
295 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
296 | INFOPLIST_FILE = PickYourPitch/Info.plist;
297 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
298 | PRODUCT_BUNDLE_IDENTIFIER = "UD.$(PRODUCT_NAME:rfc1034identifier)";
299 | PRODUCT_NAME = "$(TARGET_NAME)";
300 | SWIFT_VERSION = 5.0;
301 | };
302 | name = Debug;
303 | };
304 | 4D37A7971A5B089600294894 /* Release */ = {
305 | isa = XCBuildConfiguration;
306 | buildSettings = {
307 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
308 | INFOPLIST_FILE = PickYourPitch/Info.plist;
309 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
310 | PRODUCT_BUNDLE_IDENTIFIER = "UD.$(PRODUCT_NAME:rfc1034identifier)";
311 | PRODUCT_NAME = "$(TARGET_NAME)";
312 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
313 | SWIFT_VERSION = 5.0;
314 | };
315 | name = Release;
316 | };
317 | /* End XCBuildConfiguration section */
318 |
319 | /* Begin XCConfigurationList section */
320 | 4D37A7711A5B089600294894 /* Build configuration list for PBXProject "PickYourPitch" */ = {
321 | isa = XCConfigurationList;
322 | buildConfigurations = (
323 | 4D37A7931A5B089600294894 /* Debug */,
324 | 4D37A7941A5B089600294894 /* Release */,
325 | );
326 | defaultConfigurationIsVisible = 0;
327 | defaultConfigurationName = Release;
328 | };
329 | 4D37A7951A5B089600294894 /* Build configuration list for PBXNativeTarget "PickYourPitch" */ = {
330 | isa = XCConfigurationList;
331 | buildConfigurations = (
332 | 4D37A7961A5B089600294894 /* Debug */,
333 | 4D37A7971A5B089600294894 /* Release */,
334 | );
335 | defaultConfigurationIsVisible = 0;
336 | defaultConfigurationName = Release;
337 | };
338 | /* End XCConfigurationList section */
339 | };
340 | rootObject = 4D37A76E1A5B089600294894 /* Project object */;
341 | }
342 |
--------------------------------------------------------------------------------
/PickYourPitch-NoPersistence/PickYourPitch/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 |
33 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
97 |
102 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/Mooskine/Mooskine-complete/Mooskine/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 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
146 |
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 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------