├── .gitignore ├── LICENSE ├── README.md ├── art ├── Xcode.png ├── cs193p-Lecture-01.png ├── cs193p.jpg ├── iTunesU.png └── play.png ├── democode ├── Archive │ ├── Cassini-L7.zip │ ├── Cassini-L8.zip │ ├── DropIt-L14.zip │ ├── FaceIt-L13.zip │ ├── FaceIt-L4.zip │ ├── FaceIt-L5.zip │ ├── FaceIt-L6.zip │ ├── Pollster-L16.zip │ ├── Smashtag-L11.zip │ ├── Smashtag-L9.zip │ └── Trax-L18.zip ├── Cassini-L7 │ ├── Cassini.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Cassini │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── DemoURL.swift │ │ ├── ImageViewController.swift │ │ └── Info.plist ├── Cassini-L8 │ ├── Cassini.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Cassini │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CassiniViewController.swift │ │ ├── DemoURL.swift │ │ ├── ImageViewController.swift │ │ └── Info.plist ├── DropIt-L14 │ ├── DropIt.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── DropIt │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── DropItView.swift │ │ ├── DropItViewController.swift │ │ ├── FallingObjectBehavior.swift │ │ ├── Info.plist │ │ ├── NamedBezierPathsView.swift │ │ └── UIKit Extensions.swift ├── FaceIt-L13 │ ├── FaceIt.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── FaceIt │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── BlinkingFaceViewController.swift │ │ ├── EmotionsViewController.swift │ │ ├── EyeView.swift │ │ ├── FaceView.swift │ │ ├── FaceViewController.swift │ │ ├── FacialExpression.swift │ │ ├── Info.plist │ │ └── VCL.swift ├── FaceIt-L4 │ ├── FaceIt.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── FaceIt │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── FaceView.swift │ │ ├── FaceViewController.swift │ │ └── Info.plist ├── FaceIt-L5 │ ├── FaceIt.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── FaceIt │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── FaceView.swift │ │ ├── FaceViewController.swift │ │ ├── FacialExpression.swift │ │ └── Info.plist ├── FaceIt-L6 │ ├── FaceIt.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── FaceIt │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── EmotionsViewController.swift │ │ ├── FaceView.swift │ │ ├── FaceViewController.swift │ │ ├── FacialExpression.swift │ │ ├── Info.plist │ │ └── VCL.swift ├── Pollster-L16 │ ├── Pollster.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Pollster │ │ ├── AllQandAsTableViewController.swift │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CloudKitExtensions.swift │ │ ├── CloudQandATableViewController.swift │ │ ├── Info.plist │ │ ├── Pollster.entitlements │ │ ├── QandAAccessoryTableViewController.swift │ │ ├── QandATableViewController.swift │ │ └── TextTableViewController.swift ├── README.md ├── Smashtag-L11 │ ├── Smashtag.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Smashtag │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CoreDataTableViewController.swift │ │ ├── Info.plist │ │ ├── Model.xcdatamodeld │ │ └── Model.xcdatamodel │ │ │ └── contents │ │ ├── Tweet+CoreDataProperties.swift │ │ ├── Tweet.swift │ │ ├── TweetTableViewCell.swift │ │ ├── TweetTableViewController.swift │ │ ├── TweetersTableViewController.swift │ │ ├── TwitterUser+CoreDataProperties.swift │ │ └── TwitterUser.swift ├── Smashtag-L9 │ ├── Smashtag │ │ ├── Smashtag.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ └── Smashtag │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ ├── TweetTableViewCell.swift │ │ │ └── TweetTableViewController.swift │ └── Twitter │ │ ├── Twitter.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── Twitter │ │ ├── Info.plist │ │ ├── MediaItem.swift │ │ ├── Request.swift │ │ ├── Tweet.swift │ │ ├── Twitter.h │ │ └── User.swift └── Trax-L18 │ ├── Trax.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── Trax │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── EditWaypointViewController.swift │ ├── GPX.swift │ ├── GPXViewController.swift │ ├── ImageViewController.swift │ ├── Info.plist │ └── MKGPX.swift ├── problemsets ├── Programming_Project_1_Calculator.pdf ├── Programming_Project_2_Calculator_Brain.pdf ├── Programming_Project_3_Graphic_Calculator.pdf ├── Programming_Project_4_Smashtag_Mentions.pdf ├── Programming_Project_5_Smashtag_Ment.pdf ├── Programming_Project_6_Animation.pdf └── assignment-1 │ ├── Art │ ├── AppIcon │ │ ├── AppIcon.png │ │ ├── AppIcon.xcf │ │ └── IconSet │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-72.png │ │ │ ├── Icon-72@2x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-83.5@2x.png │ │ │ ├── Icon-Small-50.png │ │ │ ├── Icon-Small-50@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ ├── Icon.png │ │ │ ├── Icon@2x.png │ │ │ ├── iTunesArtwork.png │ │ │ └── iTunesArtwork@2x.png │ └── Screenshot │ │ ├── Calculator00.gif │ │ ├── Calculator01.gif │ │ ├── Calculator02.gif │ │ ├── Calculator03.gif │ │ ├── Calculator04.gif │ │ ├── Calculator05.gif │ │ ├── Calculator06.gif │ │ └── Calculator07.gif │ ├── CONTRIBUTING.md │ ├── Calculator │ ├── Calculator.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Calculator │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x-1.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-83.5@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x-1.png │ │ │ ├── Icon-Small@2x.png │ │ │ └── Icon-Small@3x.png │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── CalculatorBrain.swift │ │ ├── Info.plist │ │ ├── RoundedButton.swift │ │ └── ViewController.swift │ ├── LICENSE │ └── README.md ├── reading ├── Reading_1_Intro_to_Swift.pdf ├── Reading_2_More_Swift.pdf └── Reading_3_The_Rest_of_Swift.pdf └── slides ├── Lecture-1-Slides.pdf ├── Lecture-10-Slides.pdf ├── Lecture-11-Slides.pdf ├── Lecture-12-Slides.pdf ├── Lecture-13-Slides.pdf ├── Lecture-14-Slides.pdf ├── Lecture-15-Slides.pdf ├── Lecture-16-Slides.pdf ├── Lecture-17-Slides.pdf ├── Lecture-18-Slides.pdf ├── Lecture-2-Slides.pdf ├── Lecture-3-Slides.pdf ├── Lecture-4-Slides.pdf ├── Lecture-5-Slides.pdf ├── Lecture-6-Slides.pdf ├── Lecture-7-Slides.pdf ├── Lecture-8-Slides.pdf └── Lecture-9-Slides.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | ## Mac Specific 31 | .DS_Store 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 64 | 65 | fastlane/report.xml 66 | fastlane/screenshots 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Dulio Denis 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 | -------------------------------------------------------------------------------- /art/Xcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/art/Xcode.png -------------------------------------------------------------------------------- /art/cs193p-Lecture-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/art/cs193p-Lecture-01.png -------------------------------------------------------------------------------- /art/cs193p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/art/cs193p.jpg -------------------------------------------------------------------------------- /art/iTunesU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/art/iTunesU.png -------------------------------------------------------------------------------- /art/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/art/play.png -------------------------------------------------------------------------------- /democode/Archive/Cassini-L7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Cassini-L7.zip -------------------------------------------------------------------------------- /democode/Archive/Cassini-L8.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Cassini-L8.zip -------------------------------------------------------------------------------- /democode/Archive/DropIt-L14.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/DropIt-L14.zip -------------------------------------------------------------------------------- /democode/Archive/FaceIt-L13.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/FaceIt-L13.zip -------------------------------------------------------------------------------- /democode/Archive/FaceIt-L4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/FaceIt-L4.zip -------------------------------------------------------------------------------- /democode/Archive/FaceIt-L5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/FaceIt-L5.zip -------------------------------------------------------------------------------- /democode/Archive/FaceIt-L6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/FaceIt-L6.zip -------------------------------------------------------------------------------- /democode/Archive/Pollster-L16.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Pollster-L16.zip -------------------------------------------------------------------------------- /democode/Archive/Smashtag-L11.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Smashtag-L11.zip -------------------------------------------------------------------------------- /democode/Archive/Smashtag-L9.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Smashtag-L9.zip -------------------------------------------------------------------------------- /democode/Archive/Trax-L18.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/democode/Archive/Trax-L18.zip -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Cassini 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/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 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/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 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/DemoURL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URL.swift 3 | // 4 | // Created by CS193p Instructor. 5 | // Copyright (c) 2016 Stanford University. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | struct DemoURL 11 | { 12 | static let Stanford = "http://comm.stanford.edu/wp-content/uploads/2013/01/stanford-campus.png" 13 | 14 | static let NASA = [ 15 | "Cassini" : "http://www.jpl.nasa.gov/images/cassini/20090202/pia03883-full.jpg", 16 | "Earth" : "http://www.nasa.gov/sites/default/files/wave_earth_mosaic_3.jpg", 17 | "Saturn" : "http://www.nasa.gov/sites/default/files/saturn_collage.jpg" 18 | ] 19 | 20 | static func NASAImageNamed(imageName: String?) -> NSURL? { 21 | if let urlstring = NASA[imageName ?? ""] { 22 | return NSURL(string: urlstring) 23 | } else { 24 | return nil 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/ImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.swift 3 | // Cassini 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ImageViewController: UIViewController 12 | { 13 | var imageURL: NSURL? { 14 | didSet { 15 | image = nil 16 | fetchImage() 17 | } 18 | } 19 | 20 | private func fetchImage() { 21 | if let url = imageURL { 22 | if let imageData = NSData(contentsOfURL: url) { 23 | image = UIImage(data: imageData) 24 | } 25 | } 26 | } 27 | 28 | @IBOutlet weak var scrollView: UIScrollView! { 29 | didSet { 30 | scrollView.contentSize = imageView.frame.size 31 | } 32 | } 33 | 34 | private var imageView = UIImageView() 35 | 36 | private var image: UIImage? { 37 | get { 38 | return imageView.image 39 | } 40 | set { 41 | imageView.image = newValue 42 | imageView.sizeToFit() 43 | scrollView?.contentSize = imageView.frame.size 44 | } 45 | } 46 | 47 | override func viewDidLoad() { 48 | super.viewDidLoad() 49 | scrollView.addSubview(imageView) 50 | imageURL = NSURL(string: DemoURL.Stanford) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /democode/Cassini-L7/Cassini/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 | NSAppTransportSecurity 40 | 41 | NSAllowsArbitraryLoads 42 | 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Cassini 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/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 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/CassiniViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CassiniViewController.swift 3 | // Cassini 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CassiniViewController: UIViewController, UISplitViewControllerDelegate 12 | { 13 | // this is just our normal "put constants in a struct" thing 14 | // but we call it Storyboard, because all the constants in it 15 | // are strings in our Storyboard 16 | 17 | private struct Storyboard { 18 | static let ShowImageSegue = "Show Image" 19 | } 20 | 21 | // prepare for segue is called 22 | // even if we invoke the segue from code using performSegue (see below) 23 | 24 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 25 | if segue.identifier == Storyboard.ShowImageSegue { 26 | if let ivc = segue.destinationViewController.contentViewController as? ImageViewController { 27 | let imageName = (sender as? UIButton)?.currentTitle 28 | ivc.imageURL = DemoURL.NASAImageNamed(imageName) 29 | ivc.title = imageName 30 | } 31 | } 32 | } 33 | 34 | // we changed the buttons to this target/action method 35 | // so that we could either 36 | // a) just set our imageURL in the detail if we're in a split view, or 37 | // b) cause the segue to happen from code with performSegue 38 | // to make the latter work, we had to create a segue in our storyboard 39 | // that was ctrl-dragged from the view controller icon (orange one at the top) 40 | 41 | @IBAction func showImage(sender: UIButton) { 42 | if let ivc = splitViewController?.viewControllers.last?.contentViewController as? ImageViewController { 43 | let imageName = sender.currentTitle 44 | ivc.imageURL = DemoURL.NASAImageNamed(imageName) 45 | ivc.title = imageName 46 | } else { 47 | performSegueWithIdentifier(Storyboard.ShowImageSegue, sender: sender) 48 | } 49 | } 50 | 51 | // if we are in a split view, we set ourselves as its delegate 52 | // this is so we can prevent an empty detail from collapsing on top of our master 53 | // see split view delegate method below 54 | 55 | override func viewDidLoad() { 56 | super.viewDidLoad() 57 | splitViewController?.delegate = self 58 | } 59 | 60 | // this method lets the split view's delegate 61 | // collapse the detail on top of the master when it's the detail's time to appear 62 | // this method returns whether we (the delegate) handled doing this 63 | // we don't want an empty detail to collapse on top of our master 64 | // so if the detail is an empty ImageViewController, we return true 65 | // (which tells the split view controller that we handled the collapse) 66 | // of course, we didn't actually handle it, we did nothing 67 | // but that's exactly what we want (i.e. no collapse if the detail ivc is empty) 68 | 69 | func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool 70 | { 71 | if primaryViewController.contentViewController == self { 72 | if let ivc = secondaryViewController.contentViewController as? ImageViewController where ivc.imageURL == nil { 73 | return true 74 | } 75 | } 76 | return false 77 | } 78 | } 79 | 80 | // a little helper extension 81 | // which either returns the view controller you send it to 82 | // or, if you send it to a UINavigationController, 83 | // it returns its visibleViewController 84 | // (if any, otherwise the UINavigationController itself) 85 | 86 | extension UIViewController { 87 | var contentViewController: UIViewController { 88 | if let navcon = self as? UINavigationController { 89 | return navcon.visibleViewController ?? self 90 | } else { 91 | return self 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/DemoURL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URL.swift 3 | // 4 | // Created by CS193p Instructor. 5 | // Copyright (c) 2016 Stanford University. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | struct DemoURL 11 | { 12 | static let Stanford = "http://comm.stanford.edu/wp-content/uploads/2013/01/stanford-campus.png" 13 | 14 | static let NASA = [ 15 | "Cassini" : "http://www.jpl.nasa.gov/images/cassini/20090202/pia03883-full.jpg", 16 | "Earth" : "http://www.nasa.gov/sites/default/files/wave_earth_mosaic_3.jpg", 17 | "Saturn" : "http://www.nasa.gov/sites/default/files/saturn_collage.jpg" 18 | ] 19 | 20 | static func NASAImageNamed(imageName: String?) -> NSURL? { 21 | if let urlstring = NASA[imageName ?? ""] { 22 | return NSURL(string: urlstring) 23 | } else { 24 | return nil 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /democode/Cassini-L8/Cassini/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 | NSAppTransportSecurity 40 | 41 | NSAllowsArbitraryLoads 42 | 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DropIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/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 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/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 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/DropItViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DropItViewController.swift 3 | // DropIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DropItViewController: UIViewController 12 | { 13 | @IBOutlet weak var gameView: DropItView! { 14 | didSet { 15 | gameView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addDrop(_:)))) 16 | gameView.addGestureRecognizer(UIPanGestureRecognizer(target: gameView, action: #selector(DropItView.grabDrop(_:)))) 17 | gameView.realGravity = true 18 | } 19 | } 20 | 21 | func addDrop(recognizer: UITapGestureRecognizer) { 22 | if recognizer.state == .Ended { 23 | gameView.addDrop() 24 | } 25 | } 26 | 27 | override func viewDidAppear(animated: Bool) { 28 | super.viewDidAppear(animated) 29 | gameView.animating = true 30 | } 31 | 32 | override func viewWillDisappear(animated: Bool) { 33 | super.viewWillDisappear(animated) 34 | gameView.animating = false 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/FallingObjectBehavior.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FallingObjectBehavior.swift 3 | // DropIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FallingObjectBehavior: UIDynamicBehavior 12 | { 13 | let gravity = UIGravityBehavior() 14 | 15 | private let collider: UICollisionBehavior = { 16 | let collider = UICollisionBehavior() 17 | collider.translatesReferenceBoundsIntoBoundary = true 18 | return collider 19 | }() 20 | 21 | private let itemBehavior: UIDynamicItemBehavior = { 22 | let dib = UIDynamicItemBehavior() 23 | dib.allowsRotation = true 24 | dib.elasticity = 0.75 25 | return dib 26 | }() 27 | 28 | func addBarrier(path: UIBezierPath, named name: String) { 29 | collider.removeBoundaryWithIdentifier(name) 30 | collider.addBoundaryWithIdentifier(name, forPath: path) 31 | } 32 | 33 | override init() { 34 | super.init() 35 | addChildBehavior(gravity) 36 | addChildBehavior(collider) 37 | addChildBehavior(itemBehavior) 38 | } 39 | 40 | func addItem(item: UIDynamicItem) { 41 | gravity.addItem(item) 42 | collider.addItem(item) 43 | itemBehavior.addItem(item) 44 | } 45 | 46 | func removeItem(item: UIDynamicItem) { 47 | gravity.removeItem(item) 48 | collider.removeItem(item) 49 | itemBehavior.removeItem(item) 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/NamedBezierPathsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NamedBezierPathsView.swift 3 | // DropIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class NamedBezierPathsView: UIView 12 | { 13 | var bezierPaths = [String:UIBezierPath]() { didSet { setNeedsDisplay() } } 14 | 15 | override func drawRect(rect: CGRect) { 16 | for (_, path) in bezierPaths { 17 | path.stroke() 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /democode/DropIt-L14/DropIt/UIKit Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // DropIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension CGFloat { 12 | static func random(max: Int) -> CGFloat { 13 | return CGFloat(arc4random() % UInt32(max)) 14 | } 15 | } 16 | 17 | extension UIColor { 18 | class var random: UIColor { 19 | switch arc4random()%5 { 20 | case 0: return UIColor.greenColor() 21 | case 1: return UIColor.blueColor() 22 | case 2: return UIColor.orangeColor() 23 | case 3: return UIColor.redColor() 24 | case 4: return UIColor.purpleColor() 25 | default: return UIColor.blackColor() 26 | } 27 | } 28 | } 29 | 30 | extension CGRect { 31 | var mid: CGPoint { return CGPoint(x: midX, y: midY) } 32 | var upperLeft: CGPoint { return CGPoint(x: minX, y: minY) } 33 | var lowerLeft: CGPoint { return CGPoint(x: minX, y: maxY) } 34 | var upperRight: CGPoint { return CGPoint(x: maxX, y: minY) } 35 | var lowerRight: CGPoint { return CGPoint(x: maxX, y: maxY) } 36 | 37 | init(center: CGPoint, size: CGSize) { 38 | let upperLeft = CGPoint(x: center.x-size.width/2, y: center.y-size.height/2) 39 | self.init(origin: upperLeft, size: size) 40 | } 41 | } 42 | 43 | extension UIView { 44 | func hitTest(p: CGPoint) -> UIView? { 45 | return hitTest(p, withEvent: nil) 46 | } 47 | } 48 | 49 | extension UIBezierPath { 50 | class func lineFrom(from: CGPoint, to: CGPoint) -> UIBezierPath { 51 | let path = UIBezierPath() 52 | path.moveToPoint(from) 53 | path.addLineToPoint(to) 54 | return path 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/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 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/BlinkingFaceViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlinkingFaceViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BlinkingFaceViewController: FaceViewController 12 | { 13 | var blinking: Bool = false { 14 | didSet { 15 | startBlink() 16 | } 17 | } 18 | 19 | private struct BlinkRate { 20 | static let ClosedDuration = 0.4 21 | static let OpenDuration = 2.5 22 | } 23 | 24 | func startBlink() { 25 | if blinking { 26 | faceView.eyesOpen = false 27 | NSTimer.scheduledTimerWithTimeInterval( 28 | BlinkRate.ClosedDuration, 29 | target: self, selector: #selector(BlinkingFaceViewController.endBlink), 30 | userInfo: nil, 31 | repeats: false 32 | ) 33 | } 34 | } 35 | 36 | func endBlink() { 37 | faceView.eyesOpen = true 38 | NSTimer.scheduledTimerWithTimeInterval( 39 | BlinkRate.OpenDuration, 40 | target: self, selector: #selector(BlinkingFaceViewController.startBlink), 41 | userInfo: nil, 42 | repeats: false 43 | ) 44 | } 45 | 46 | override func viewDidAppear(animated: Bool) { 47 | super.viewDidAppear(animated) 48 | blinking = true 49 | } 50 | 51 | override func viewWillDisappear(animated: Bool) { 52 | super.viewWillDisappear(animated) 53 | blinking = false 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/EmotionsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmotionsViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class EmotionsViewController: UIViewController 12 | { 13 | private let emotionalFaces: Dictionary = [ 14 | "angry" : FacialExpression(eyes: .Closed, eyeBrows: .Furrowed, mouth: .Frown), 15 | "happy" : FacialExpression(eyes: .Open, eyeBrows: .Normal, mouth: .Smile), 16 | "worried" : FacialExpression(eyes: .Open, eyeBrows: .Relaxed, mouth: .Smirk), 17 | "mischievious" : FacialExpression(eyes: .Open, eyeBrows: .Furrowed, mouth: .Grin) 18 | ] 19 | 20 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 21 | var destinationvc = segue.destinationViewController 22 | if let navcon = destinationvc as? UINavigationController { 23 | destinationvc = navcon.visibleViewController ?? destinationvc 24 | } 25 | if let facevc = destinationvc as? FaceViewController { 26 | if let identifier = segue.identifier { 27 | if let expression = emotionalFaces[identifier] { 28 | facevc.expression = expression 29 | if let sendingButton = sender as? UIButton { 30 | facevc.navigationItem.title = sendingButton.currentTitle 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | // let instance = getEmotionsMVCinstanceCount() 38 | } 39 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/EyeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EyeView.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2015 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class EyeView: UIView 12 | { 13 | var lineWidth: CGFloat = 5.0 { didSet { setNeedsDisplay() } } 14 | var color: UIColor = UIColor.blueColor() { didSet { setNeedsDisplay() } } 15 | 16 | var _eyesOpen: Bool = true { didSet { setNeedsDisplay() } } 17 | 18 | var eyesOpen: Bool { 19 | get { 20 | return _eyesOpen 21 | } 22 | set { 23 | UIView.transitionWithView( 24 | self, 25 | duration: 0.2, 26 | options: [.TransitionFlipFromTop,.CurveLinear], 27 | animations: { 28 | self._eyesOpen = newValue 29 | }, 30 | completion: nil 31 | ) 32 | } 33 | } 34 | 35 | override func drawRect(rect: CGRect) 36 | { 37 | var path: UIBezierPath! 38 | 39 | if eyesOpen { 40 | path = UIBezierPath(ovalInRect: bounds.insetBy(dx: lineWidth/2, dy: lineWidth/2)) 41 | } else { 42 | path = UIBezierPath() 43 | path.moveToPoint(CGPoint(x: bounds.minX, y: bounds.midY)) 44 | path.addLineToPoint(CGPoint(x: bounds.maxX, y: bounds.midY)) 45 | } 46 | 47 | path.lineWidth = lineWidth 48 | color.setStroke() 49 | path.stroke() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/FacialExpression.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FacialExpression.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2015-16 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // UI-independent representation of a facial expression 12 | 13 | struct FacialExpression 14 | { 15 | enum Eyes: Int { 16 | case Open 17 | case Closed 18 | case Squinting 19 | } 20 | 21 | enum EyeBrows: Int { 22 | case Relaxed 23 | case Normal 24 | case Furrowed 25 | 26 | func moreRelaxedBrow() -> EyeBrows { 27 | return EyeBrows(rawValue: rawValue - 1) ?? .Relaxed 28 | } 29 | func moreFurrowedBrow() -> EyeBrows { 30 | return EyeBrows(rawValue: rawValue + 1) ?? .Furrowed 31 | } 32 | } 33 | 34 | enum Mouth: Int { 35 | case Frown 36 | case Smirk 37 | case Neutral 38 | case Grin 39 | case Smile 40 | 41 | func sadderMouth() -> Mouth { 42 | return Mouth(rawValue: rawValue - 1) ?? .Frown 43 | } 44 | func happierMouth() -> Mouth { 45 | return Mouth(rawValue: rawValue + 1) ?? .Smile 46 | } 47 | } 48 | 49 | var eyes: Eyes 50 | var eyeBrows: EyeBrows 51 | var mouth: Mouth 52 | } 53 | -------------------------------------------------------------------------------- /democode/FaceIt-L13/FaceIt/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/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 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/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 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/FaceView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FaceView.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FaceView: UIView 12 | { 13 | var scale: CGFloat = 0.90 14 | var mouthCurvature: Double = 1.0 // 1 full smile, -1 full frown 15 | 16 | private var skullRadius: CGFloat { 17 | return min(bounds.size.width, bounds.size.height) / 2 * scale 18 | } 19 | private var skullCenter: CGPoint { 20 | return CGPoint(x: bounds.midX, y: bounds.midY) 21 | } 22 | 23 | private struct Ratios { 24 | static let SkullRadiusToEyeOffset: CGFloat = 3 25 | static let SkullRadiusToEyeRadius: CGFloat = 10 26 | static let SkullRadiusToMouthWidth: CGFloat = 1 27 | static let SkullRadiusToMouthHeight: CGFloat = 3 28 | static let SkullRadiusToMouthOffset: CGFloat = 3 29 | } 30 | 31 | private enum Eye { 32 | case Left 33 | case Right 34 | } 35 | 36 | private func pathForCircleCenteredAtPoint(midPoint: CGPoint, withRadius radius: CGFloat) -> UIBezierPath 37 | { 38 | let path = UIBezierPath( 39 | arcCenter: midPoint, 40 | radius: radius, 41 | startAngle: 0.0, 42 | endAngle: CGFloat(2*M_PI), 43 | clockwise: false 44 | ) 45 | path.lineWidth = 5.0 46 | return path 47 | } 48 | 49 | private func getEyeCenter(eye: Eye) -> CGPoint 50 | { 51 | let eyeOffset = skullRadius / Ratios.SkullRadiusToEyeOffset 52 | var eyeCenter = skullCenter 53 | eyeCenter.y -= eyeOffset 54 | switch eye { 55 | case .Left: eyeCenter.x -= eyeOffset 56 | case .Right: eyeCenter.x += eyeOffset 57 | } 58 | return eyeCenter 59 | } 60 | 61 | private func pathForEye(eye: Eye) -> UIBezierPath 62 | { 63 | let eyeRadius = skullRadius / Ratios.SkullRadiusToEyeRadius 64 | let eyeCenter = getEyeCenter(eye) 65 | return pathForCircleCenteredAtPoint(eyeCenter, withRadius: eyeRadius) 66 | } 67 | 68 | private func pathForMouth() -> UIBezierPath 69 | { 70 | let mouthWidth = skullRadius / Ratios.SkullRadiusToMouthWidth 71 | let mouthHeight = skullRadius / Ratios.SkullRadiusToMouthHeight 72 | let mouthOffset = skullRadius / Ratios.SkullRadiusToMouthOffset 73 | 74 | let mouthRect = CGRect(x: skullCenter.x - mouthWidth/2, y: skullCenter.y + mouthOffset, width: mouthWidth, height: mouthHeight) 75 | 76 | let smileOffset = CGFloat(max(-1, min(mouthCurvature, 1))) * mouthRect.height 77 | let start = CGPoint(x: mouthRect.minX, y: mouthRect.minY) 78 | let end = CGPoint(x: mouthRect.maxX, y: mouthRect.minY) 79 | let cp1 = CGPoint(x: mouthRect.minX + mouthRect.width / 3, y: mouthRect.minY + smileOffset) 80 | let cp2 = CGPoint(x: mouthRect.maxX - mouthRect.width / 3, y: mouthRect.minY + smileOffset) 81 | 82 | let path = UIBezierPath() 83 | path.moveToPoint(start) 84 | path.addCurveToPoint(end, controlPoint1: cp1, controlPoint2: cp2) 85 | path.lineWidth = 5.0 86 | 87 | return path 88 | } 89 | 90 | override func drawRect(rect: CGRect) 91 | { 92 | UIColor.blueColor().set() 93 | pathForCircleCenteredAtPoint(skullCenter, withRadius: skullRadius).stroke() 94 | pathForEye(.Left).stroke() 95 | pathForEye(.Right).stroke() 96 | pathForMouth().stroke() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/FaceViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FaceViewController: UIViewController 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /democode/FaceIt-L4/FaceIt/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/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 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/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 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/FaceViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FaceViewController: UIViewController 12 | { 13 | // MARK: Model 14 | 15 | var expression = FacialExpression(eyes: .Closed, eyeBrows: .Relaxed, mouth: .Smirk) { 16 | didSet { 17 | updateUI() // Model changed, so update the View 18 | } 19 | } 20 | 21 | // MARK: View 22 | 23 | // the didSet here is called only once 24 | // when the outlet is connected up by iOS 25 | @IBOutlet weak var faceView: FaceView! { 26 | didSet { 27 | faceView.addGestureRecognizer(UIPinchGestureRecognizer( 28 | target: faceView, action: #selector(FaceView.changeScale(_:)) 29 | )) 30 | 31 | let happierSwipeGestureRecognizer = UISwipeGestureRecognizer( 32 | target: self, action: #selector(FaceViewController.increaseHappiness) 33 | ) 34 | happierSwipeGestureRecognizer.direction = .Up 35 | faceView.addGestureRecognizer(happierSwipeGestureRecognizer) 36 | 37 | let sadderSwipeGestureRecognizer = UISwipeGestureRecognizer( 38 | target: self, action: #selector(FaceViewController.decreaseHappiness) 39 | ) 40 | sadderSwipeGestureRecognizer.direction = .Down 41 | faceView.addGestureRecognizer(sadderSwipeGestureRecognizer) 42 | 43 | // ADDED AFTER LECTURE 5 44 | faceView.addGestureRecognizer(UIRotationGestureRecognizer( 45 | target: self, action: #selector(FaceViewController.changeBrows(_:)) 46 | )) 47 | 48 | updateUI() // View connected for first time, update it from Model 49 | } 50 | } 51 | 52 | // here the Controller is doing its job 53 | // of interpreting the Model (expression) for the View (faceView) 54 | 55 | private func updateUI() { 56 | switch expression.eyes { 57 | case .Open: faceView.eyesOpen = true 58 | case .Closed: faceView.eyesOpen = false 59 | case .Squinting: faceView.eyesOpen = false 60 | } 61 | faceView.mouthCurvature = mouthCurvatures[expression.mouth] ?? 0.0 62 | faceView.eyeBrowTilt = eyeBrowTilts[expression.eyeBrows] ?? 0.0 63 | } 64 | 65 | private var mouthCurvatures = [FacialExpression.Mouth.Frown:-1.0,.Grin:0.5,.Smile:1.0,.Smirk:-0.5,.Neutral:0.0 ] 66 | private var eyeBrowTilts = [FacialExpression.EyeBrows.Relaxed:0.5,.Furrowed:-0.5,.Normal:0.0] 67 | 68 | // MARK: Gesture Handlers 69 | 70 | // gesture handler for swipe to increase happiness 71 | // changes the Model (which will, in turn, updateUI()) 72 | func increaseHappiness() { 73 | expression.mouth = expression.mouth.happierMouth() 74 | } 75 | 76 | // gesture handler for swipe to decrease happiness 77 | // changes the Model (which will, in turn, updateUI()) 78 | func decreaseHappiness() { 79 | expression.mouth = expression.mouth.sadderMouth() 80 | } 81 | 82 | // gesture handler for taps 83 | // 84 | // toggles the open/closed state of the eyes in the Model 85 | // and all changes to the Model automatically updateUI() 86 | // (see the didSet for the Model var expression above) 87 | // so our faceView will also change its eyes 88 | // 89 | // this handler was added directly in the storyboard 90 | // by dragging a UITapGestureHandler onto the faceView 91 | // then ctrl-dragging from the tap gesture 92 | // (at the top of the scene in the storyboard) 93 | // here to our Controller 94 | // (so there's no need to call addGestureRecognizer) 95 | 96 | @IBAction func toggleEyes(recognizer: UITapGestureRecognizer) { 97 | if recognizer.state == .Ended { 98 | switch expression.eyes { 99 | case .Open: expression.eyes = .Closed 100 | case .Closed: expression.eyes = .Open 101 | case .Squinting: break // we don't know how to toggle "Squinting" 102 | } 103 | } 104 | } 105 | 106 | // ADDED AFTER LECTURE 5 107 | // gesture handler to change the Model's brows with a rotation gesture 108 | func changeBrows(recognizer: UIRotationGestureRecognizer) { 109 | switch recognizer.state { 110 | case .Changed,.Ended: 111 | if recognizer.rotation > CGFloat(M_PI/4) { 112 | expression.eyeBrows = expression.eyeBrows.moreRelaxedBrow() 113 | recognizer.rotation = 0.0 114 | } else if recognizer.rotation < -CGFloat(M_PI/4) { 115 | expression.eyeBrows = expression.eyeBrows.moreFurrowedBrow() 116 | recognizer.rotation = 0.0 117 | } 118 | default: 119 | break 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/FacialExpression.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FacialExpression.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2015-16 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // UI-independent representation of a facial expression 12 | 13 | struct FacialExpression 14 | { 15 | enum Eyes: Int { 16 | case Open 17 | case Closed 18 | case Squinting 19 | } 20 | 21 | enum EyeBrows: Int { 22 | case Relaxed 23 | case Normal 24 | case Furrowed 25 | 26 | func moreRelaxedBrow() -> EyeBrows { 27 | return EyeBrows(rawValue: rawValue - 1) ?? .Relaxed 28 | } 29 | func moreFurrowedBrow() -> EyeBrows { 30 | return EyeBrows(rawValue: rawValue + 1) ?? .Furrowed 31 | } 32 | } 33 | 34 | enum Mouth: Int { 35 | case Frown 36 | case Smirk 37 | case Neutral 38 | case Grin 39 | case Smile 40 | 41 | func sadderMouth() -> Mouth { 42 | return Mouth(rawValue: rawValue - 1) ?? .Frown 43 | } 44 | func happierMouth() -> Mouth { 45 | return Mouth(rawValue: rawValue + 1) ?? .Smile 46 | } 47 | } 48 | 49 | var eyes: Eyes 50 | var eyeBrows: EyeBrows 51 | var mouth: Mouth 52 | } 53 | -------------------------------------------------------------------------------- /democode/FaceIt-L5/FaceIt/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/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 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/EmotionsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmotionsViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class EmotionsViewController: UIViewController 12 | { 13 | private let emotionalFaces: Dictionary = [ 14 | "angry" : FacialExpression(eyes: .Closed, eyeBrows: .Furrowed, mouth: .Frown), 15 | "happy" : FacialExpression(eyes: .Open, eyeBrows: .Normal, mouth: .Smile), 16 | "worried" : FacialExpression(eyes: .Open, eyeBrows: .Relaxed, mouth: .Smirk), 17 | "mischievious" : FacialExpression(eyes: .Open, eyeBrows: .Furrowed, mouth: .Grin) 18 | ] 19 | 20 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 21 | var destinationvc = segue.destinationViewController 22 | if let navcon = destinationvc as? UINavigationController { 23 | destinationvc = navcon.visibleViewController ?? destinationvc 24 | } 25 | if let facevc = destinationvc as? FaceViewController { 26 | if let identifier = segue.identifier { 27 | if let expression = emotionalFaces[identifier] { 28 | facevc.expression = expression 29 | if let sendingButton = sender as? UIButton { 30 | facevc.navigationItem.title = sendingButton.currentTitle 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | let instance = getEmotionsMVCinstanceCount() 38 | } 39 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/FaceViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FaceViewController: UIViewController 12 | { 13 | // MARK: Model 14 | 15 | var expression = FacialExpression(eyes: .Closed, eyeBrows: .Relaxed, mouth: .Smirk) { 16 | didSet { 17 | updateUI() // Model changed, so update the View 18 | } 19 | } 20 | 21 | // MARK: View 22 | 23 | @IBOutlet weak var faceView: FaceView! { 24 | didSet { 25 | faceView.addGestureRecognizer(UIPinchGestureRecognizer( 26 | target: faceView, action: #selector(FaceView.changeScale(_:)) 27 | )) 28 | 29 | let happierSwipeGestureRecognizer = UISwipeGestureRecognizer( 30 | target: self, action: #selector(FaceViewController.increaseHappiness) 31 | ) 32 | happierSwipeGestureRecognizer.direction = .Up 33 | faceView.addGestureRecognizer(happierSwipeGestureRecognizer) 34 | 35 | let sadderSwipeGestureRecognizer = UISwipeGestureRecognizer( 36 | target: self, action: #selector(FaceViewController.decreaseHappiness) 37 | ) 38 | sadderSwipeGestureRecognizer.direction = .Down 39 | faceView.addGestureRecognizer(sadderSwipeGestureRecognizer) 40 | 41 | faceView.addGestureRecognizer(UIRotationGestureRecognizer( 42 | target: self, action: #selector(FaceViewController.changeBrows(_:)) 43 | )) 44 | 45 | updateUI() 46 | } 47 | } 48 | 49 | private func updateUI() { 50 | if faceView != nil { 51 | switch expression.eyes { 52 | case .Open: faceView.eyesOpen = true 53 | case .Closed: faceView.eyesOpen = false 54 | case .Squinting: faceView.eyesOpen = false 55 | } 56 | faceView.mouthCurvature = mouthCurvatures[expression.mouth] ?? 0.0 57 | faceView.eyeBrowTilt = eyeBrowTilts[expression.eyeBrows] ?? 0.0 58 | } 59 | } 60 | 61 | private var mouthCurvatures = [FacialExpression.Mouth.Frown:-1.0,.Grin:0.5,.Smile:1.0,.Smirk:-0.5,.Neutral:0.0 ] 62 | private var eyeBrowTilts = [FacialExpression.EyeBrows.Relaxed:0.5,.Furrowed:-0.5,.Normal:0.0] 63 | 64 | // MARK: Gesture Handlers 65 | 66 | func increaseHappiness() { 67 | expression.mouth = expression.mouth.happierMouth() 68 | } 69 | 70 | func decreaseHappiness() { 71 | expression.mouth = expression.mouth.sadderMouth() 72 | } 73 | 74 | @IBAction func toggleEyes(recognizer: UITapGestureRecognizer) { 75 | if recognizer.state == .Ended { 76 | switch expression.eyes { 77 | case .Open: expression.eyes = .Closed 78 | case .Closed: expression.eyes = .Open 79 | case .Squinting: break // we don't know how to toggle "Squinting" 80 | } 81 | } 82 | } 83 | 84 | func changeBrows(recognizer: UIRotationGestureRecognizer) { 85 | switch recognizer.state { 86 | case .Changed,.Ended: 87 | if recognizer.rotation > CGFloat(M_PI/4) { 88 | expression.eyeBrows = expression.eyeBrows.moreRelaxedBrow() 89 | recognizer.rotation = 0.0 90 | } else if recognizer.rotation < -CGFloat(M_PI/4) { 91 | expression.eyeBrows = expression.eyeBrows.moreFurrowedBrow() 92 | recognizer.rotation = 0.0 93 | } 94 | default: 95 | break 96 | } 97 | } 98 | 99 | let instance = getFaceMVCinstanceCount() 100 | } 101 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/FacialExpression.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FacialExpression.swift 3 | // FaceIt 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2015-16 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // UI-independent representation of a facial expression 12 | 13 | struct FacialExpression 14 | { 15 | enum Eyes: Int { 16 | case Open 17 | case Closed 18 | case Squinting 19 | } 20 | 21 | enum EyeBrows: Int { 22 | case Relaxed 23 | case Normal 24 | case Furrowed 25 | 26 | func moreRelaxedBrow() -> EyeBrows { 27 | return EyeBrows(rawValue: rawValue - 1) ?? .Relaxed 28 | } 29 | func moreFurrowedBrow() -> EyeBrows { 30 | return EyeBrows(rawValue: rawValue + 1) ?? .Furrowed 31 | } 32 | } 33 | 34 | enum Mouth: Int { 35 | case Frown 36 | case Smirk 37 | case Neutral 38 | case Grin 39 | case Smile 40 | 41 | func sadderMouth() -> Mouth { 42 | return Mouth(rawValue: rawValue - 1) ?? .Frown 43 | } 44 | func happierMouth() -> Mouth { 45 | return Mouth(rawValue: rawValue + 1) ?? .Smile 46 | } 47 | } 48 | 49 | var eyes: Eyes 50 | var eyeBrows: EyeBrows 51 | var mouth: Mouth 52 | } 53 | -------------------------------------------------------------------------------- /democode/FaceIt-L6/FaceIt/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Pollster 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CloudKit 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | let settings = UIUserNotificationSettings(forTypes: [.Alert,.Badge,.Sound], categories: nil) 20 | application.registerUserNotificationSettings(settings) 21 | application.registerForRemoteNotifications() 22 | return true 23 | } 24 | 25 | func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { 26 | let ckqn = CKQueryNotification(fromRemoteNotificationDictionary: userInfo as! [String:NSObject]) 27 | let notification = NSNotification( 28 | name: CloudKitNotifications.NotificationReceived, 29 | object: self, 30 | userInfo: [CloudKitNotifications.NotificationKey:ckqn] 31 | ) 32 | NSNotificationCenter.defaultCenter().postNotification(notification) 33 | } 34 | 35 | func applicationWillResignActive(application: UIApplication) { 36 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 37 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 38 | } 39 | 40 | func applicationDidEnterBackground(application: UIApplication) { 41 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 43 | } 44 | 45 | func applicationWillEnterForeground(application: UIApplication) { 46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 47 | } 48 | 49 | func applicationDidBecomeActive(application: UIApplication) { 50 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 51 | } 52 | 53 | func applicationWillTerminate(application: UIApplication) { 54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/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 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/CloudKitExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudKitExtensions.swift 3 | // Pollster 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import CloudKit 10 | 11 | // these are read-only 12 | // one could make read-write versions of them just as easily 13 | 14 | extension CKRecord { 15 | var question: String { 16 | return self[Cloud.Attribute.Question] as? String ?? "" 17 | } 18 | var answers: [String] { 19 | return self[Cloud.Attribute.Answers] as? [String] ?? [] 20 | } 21 | } 22 | 23 | // Constants 24 | 25 | struct CloudKitNotifications { 26 | static let NotificationReceived = "iCloudRemoteNotificationReceived" 27 | static let NotificationKey = "Notification" 28 | } 29 | 30 | struct Cloud { 31 | struct Entity { 32 | static let QandA = "QandA" 33 | static let Response = "Response" 34 | } 35 | struct Attribute { 36 | static let Question = "question" 37 | static let Answers = "answers" 38 | static let ChosenAnswer = "chosenAnswer" 39 | static let QandA = "qanda" 40 | } 41 | } 42 | 43 | // probably in a real application 44 | // you'd have an Entity in the database for users 45 | // and so you wouldn't use this way of determining whether 46 | // the record was authored by the currently-logged-in iCloud user 47 | 48 | extension CKRecord { 49 | var wasCreatedByThisUser: Bool { 50 | // is this really the right way to do this? 51 | // seems like this Bool property should be built in to CKRecord 52 | return (creatorUserRecordID == nil) || (creatorUserRecordID?.recordName == "__defaultOwner__") 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/CloudQandATableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudQandATableViewController.swift 3 | // Pollster 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CloudKit 11 | 12 | class CloudQandATableViewController: QandATableViewController 13 | { 14 | // MARK: Model 15 | 16 | var ckQandARecord: CKRecord { 17 | get { 18 | if _ckQandARecord == nil { 19 | _ckQandARecord = CKRecord(recordType: Cloud.Entity.QandA) 20 | } 21 | return _ckQandARecord! 22 | } 23 | set { 24 | _ckQandARecord = newValue 25 | } 26 | } 27 | 28 | // MARK: UITextViewDelegate 29 | 30 | override func textViewDidEndEditing(textView: UITextView) { 31 | super.textViewDidEndEditing(textView) 32 | iCloudUpdate() 33 | } 34 | 35 | // MARK: Private Implementation 36 | 37 | private var _ckQandARecord: CKRecord? { 38 | didSet { 39 | let question = ckQandARecord[Cloud.Attribute.Question] as? String ?? "" 40 | let answers = ckQandARecord[Cloud.Attribute.Answers] as? [String] ?? [] 41 | qanda = QandA(question: question, answers: answers) 42 | 43 | asking = ckQandARecord.wasCreatedByThisUser 44 | } 45 | } 46 | 47 | private let database = CKContainer.defaultContainer().publicCloudDatabase 48 | 49 | @objc private func iCloudUpdate() { 50 | if !qanda.question.isEmpty && !qanda.answers.isEmpty { 51 | ckQandARecord[Cloud.Attribute.Question] = qanda.question 52 | ckQandARecord[Cloud.Attribute.Answers] = qanda.answers 53 | iCloudSaveRecord(ckQandARecord) 54 | } 55 | } 56 | 57 | private func iCloudSaveRecord(recordToSave: CKRecord) { 58 | database.saveRecord(recordToSave) { (savedRecord, error) in 59 | if error?.code == CKErrorCode.ServerRecordChanged.rawValue { 60 | // optimistic locking failed, ignore 61 | } else if error != nil { 62 | self.retryAfterError(error, withSelector: #selector(self.iCloudUpdate)) 63 | } 64 | } 65 | } 66 | 67 | private func retryAfterError(error: NSError?, withSelector selector: Selector) { 68 | if let retryInterval = error?.userInfo[CKErrorRetryAfterKey] as? NSTimeInterval { 69 | dispatch_async(dispatch_get_main_queue()) { 70 | NSTimer.scheduledTimerWithTimeInterval( 71 | retryInterval, 72 | target: self, selector: selector, 73 | userInfo: nil, repeats: false 74 | ) 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/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 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/Pollster.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.$(CFBundleIdentifier) 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudKit 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /democode/Pollster-L16/Pollster/QandAAccessoryTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QandAAccessoryDoneTableViewController.swift 3 | // Pollster 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // Adds accessoryValues for the cells 12 | 13 | class QandAAccessoryTableViewController: QandATableViewController 14 | { 15 | // MARK: Public API 16 | 17 | // key is content found in a cell 18 | // value is what to put in the accessory label for that cell 19 | // note: if two cells have the same content, they'll both get the same accessory value 20 | // (which may or may not be what you want, but there it is) 21 | 22 | var accessoryValues = [String:CustomStringConvertible]() { 23 | didSet { 24 | for content in data?[Section.Answers] ?? [] { 25 | accessoryLabelForContent(content)?.text = "\(accessoryValues[content] ?? "")" 26 | } 27 | } 28 | } 29 | 30 | // MARK: - Private Implementation 31 | 32 | private func accessoryLabelForContent(content: String) -> UILabel? { 33 | for cell in tableView.visibleCells { 34 | for subview in cell.contentView.subviews { 35 | if let textView = subview as? UITextView where textView.text == content { 36 | for subview in textView.subviews { 37 | if let label = subview as? UILabel { 38 | return label 39 | } 40 | } 41 | } 42 | } 43 | } 44 | return nil 45 | } 46 | 47 | override func createTextViewForIndexPath(indexPath: NSIndexPath?) -> UITextView { 48 | let textView = super.createTextViewForIndexPath(indexPath) 49 | createAccessoryLabel(inTextView: textView) 50 | return textView 51 | } 52 | 53 | private func createAccessoryLabel(inTextView textView: UITextView) { 54 | let label = UILabel() 55 | label.textAlignment = .Right 56 | label.text = "100" 57 | label.sizeToFit() 58 | let width = label.bounds.size.width 59 | label.frame = CGRect(x: textView.bounds.maxX - width, y: 0, width: width, height: textView.bounds.size.height) 60 | label.text = "" 61 | label.autoresizingMask = [.FlexibleHeight,.FlexibleLeftMargin] 62 | textView.addSubview(label) 63 | } 64 | 65 | // MARK: UITableViewDataSource 66 | 67 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 68 | let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) 69 | if asking && indexPath.section == Section.Answers { 70 | if let answerInRow = data?[indexPath.section][indexPath.row] { 71 | accessoryLabelForContent(answerInRow)?.text = "\(accessoryValues[answerInRow] ?? "")" 72 | } 73 | } 74 | return cell 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /democode/README.md: -------------------------------------------------------------------------------- 1 | ### Demo Code 2 | This is the demo code as entered per lecture. 3 | 4 | Project | Xcode Project 5 | ------------- | ------------- 6 | 1. | [Lecture 4: Drawing and Views](FaceIt-L4) 7 | 2. | [Lecture 5: Gestures](FaceIt-L5) 8 | 3. | [Lecture 6: Multiple MVCs](FaceIt-L6) 9 | 4. | [Lecture 7: Delegation & Scroll View](Cassini-L7) 10 | 5. | [Lecture 8: Multithreading](Cassini-L8) 11 | 6. | [Lecture 9: Table View](Smashtag-L9) 12 | 7. | [Lecture 11: Core Data](Smashtag-L11) 13 | 8. | [Lecture 13: NSTimer & UIView Animation](FaceIt-L13) 14 | 9. | [Lecture 14: Animation](DropIt-L14) 15 | 10. | [Lecture 16: CloudKit](Pollster-L16) 16 | 11. | [Lectures 17 & 18: MapKit and Segues](Trax-L18) 17 | 18 | ## Support or Contact 19 | Visit [ddApps.co](http://ddapps.co) to see more. -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/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 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/CoreDataTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataTableViewController.swift 3 | // 4 | // Created by CS193p Instructor. 5 | // Copyright © 2015-16 Stanford University. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | import CoreData 10 | 11 | class CoreDataTableViewController: UITableViewController, NSFetchedResultsControllerDelegate 12 | { 13 | var fetchedResultsController: NSFetchedResultsController? { 14 | didSet { 15 | do { 16 | if let frc = fetchedResultsController { 17 | frc.delegate = self 18 | try frc.performFetch() 19 | } 20 | tableView.reloadData() 21 | } catch let error { 22 | print("NSFetchedResultsController.performFetch() failed: \(error)") 23 | } 24 | } 25 | } 26 | 27 | // MARK: UITableViewDataSource 28 | 29 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 30 | return fetchedResultsController?.sections?.count ?? 1 31 | } 32 | 33 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 34 | if let sections = fetchedResultsController?.sections where sections.count > 0 { 35 | return sections[section].numberOfObjects 36 | } else { 37 | return 0 38 | } 39 | } 40 | 41 | override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 42 | if let sections = fetchedResultsController?.sections where sections.count > 0 { 43 | return sections[section].name 44 | } else { 45 | return nil 46 | } 47 | } 48 | 49 | override func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? { 50 | return fetchedResultsController?.sectionIndexTitles 51 | } 52 | 53 | override func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int { 54 | return fetchedResultsController?.sectionForSectionIndexTitle(title, atIndex: index) ?? 0 55 | } 56 | 57 | // MARK: NSFetchedResultsControllerDelegate 58 | 59 | func controllerWillChangeContent(controller: NSFetchedResultsController) { 60 | tableView.beginUpdates() 61 | } 62 | 63 | func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { 64 | switch type { 65 | case .Insert: tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) 66 | case .Delete: tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) 67 | default: break 68 | } 69 | } 70 | 71 | func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { 72 | switch type { 73 | case .Insert: 74 | tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 75 | case .Delete: 76 | tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 77 | case .Update: 78 | tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 79 | case .Move: 80 | tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 81 | tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 82 | } 83 | } 84 | 85 | func controllerDidChangeContent(controller: NSFetchedResultsController) { 86 | tableView.endUpdates() 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/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 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/Model.xcdatamodeld/Model.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/Tweet+CoreDataProperties.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tweet+CoreDataProperties.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | // Choose "Create NSManagedObject Subclass…" from the Core Data editor menu 9 | // to delete and recreate this implementation file for your updated model. 10 | // 11 | 12 | import Foundation 13 | import CoreData 14 | 15 | extension Tweet { 16 | 17 | @NSManaged var text: String? 18 | @NSManaged var unique: String? 19 | @NSManaged var posted: NSDate? 20 | @NSManaged var tweeter: TwitterUser? 21 | 22 | } 23 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/Tweet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tweet.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | import Twitter 12 | 13 | class Tweet: NSManagedObject 14 | { 15 | // a class method which 16 | // returns a Tweet from the database if Twitter.Tweet has already been put in 17 | // or returns a newly-added-to-the-database Tweet if not 18 | 19 | class func tweetWithTwitterInfo(twitterInfo: Twitter.Tweet, inManagedObjectContext context: NSManagedObjectContext) -> Tweet? 20 | { 21 | let request = NSFetchRequest(entityName: "Tweet") 22 | request.predicate = NSPredicate(format: "unique = %@", twitterInfo.id) 23 | 24 | if let tweet = (try? context.executeFetchRequest(request))?.first as? Tweet { 25 | // found this tweet in the database, return it ... 26 | return tweet 27 | } else if let tweet = NSEntityDescription.insertNewObjectForEntityForName("Tweet", inManagedObjectContext: context) as? Tweet { 28 | // created a new tweet in the database 29 | // load it up with information from the Twitter.Tweet ... 30 | tweet.unique = twitterInfo.id 31 | tweet.text = twitterInfo.text 32 | tweet.posted = twitterInfo.created 33 | tweet.tweeter = TwitterUser.twitterUserWithTwitterInfo(twitterInfo.user, inManagedObjectContext: context) 34 | return tweet 35 | } 36 | 37 | return nil 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/TweetTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TweetTableViewCell.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Twitter 11 | 12 | class TweetTableViewCell: UITableViewCell 13 | { 14 | @IBOutlet weak var tweetScreenNameLabel: UILabel! 15 | @IBOutlet weak var tweetTextLabel: UILabel! 16 | @IBOutlet weak var tweetProfileImageView: UIImageView! 17 | @IBOutlet weak var tweetCreatedLabel: UILabel! 18 | 19 | var tweet: Twitter.Tweet? { 20 | didSet { 21 | updateUI() 22 | } 23 | } 24 | 25 | private func updateUI() 26 | { 27 | // reset any existing tweet information 28 | tweetTextLabel?.attributedText = nil 29 | tweetScreenNameLabel?.text = nil 30 | tweetProfileImageView?.image = nil 31 | tweetCreatedLabel?.text = nil 32 | 33 | // load new information from our tweet (if any) 34 | if let tweet = self.tweet 35 | { 36 | tweetTextLabel?.text = tweet.text 37 | if tweetTextLabel?.text != nil { 38 | for _ in tweet.media { 39 | tweetTextLabel.text! += " 📷" 40 | } 41 | } 42 | 43 | tweetScreenNameLabel?.text = "\(tweet.user)" // tweet.user.description 44 | 45 | if let profileImageURL = tweet.user.profileImageURL { 46 | if let imageData = NSData(contentsOfURL: profileImageURL) { // blocks main thread! 47 | tweetProfileImageView?.image = UIImage(data: imageData) 48 | } 49 | } 50 | 51 | let formatter = NSDateFormatter() 52 | if NSDate().timeIntervalSinceDate(tweet.created) > 24*60*60 { 53 | formatter.dateStyle = NSDateFormatterStyle.ShortStyle 54 | } else { 55 | formatter.timeStyle = NSDateFormatterStyle.ShortStyle 56 | } 57 | tweetCreatedLabel?.text = formatter.stringFromDate(tweet.created) 58 | } 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/TweetersTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TweetersTableViewController.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | // uses CoreDataTableViewController as its superclass 13 | // so all we need to do is set the fetchedResultsController var 14 | // and implement tableView(cellForRowAtIndexPath:) 15 | 16 | class TweetersTableViewController: CoreDataTableViewController 17 | { 18 | var mention: String? { didSet { updateUI() } } 19 | var managedObjectContext: NSManagedObjectContext? { didSet { updateUI() } } 20 | 21 | private func updateUI() { 22 | if let context = managedObjectContext where mention?.characters.count > 0 { 23 | let request = NSFetchRequest(entityName: "TwitterUser") 24 | request.predicate = NSPredicate(format: "any tweets.text contains[c] %@ and !screenName beginswith[c] %@", mention!, "darkside") 25 | request.sortDescriptors = [NSSortDescriptor( 26 | key: "screenName", 27 | ascending: true, 28 | selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)) 29 | )] 30 | fetchedResultsController = NSFetchedResultsController( 31 | fetchRequest: request, 32 | managedObjectContext: context, 33 | sectionNameKeyPath: nil, 34 | cacheName: nil 35 | ) 36 | } else { 37 | fetchedResultsController = nil 38 | } 39 | } 40 | 41 | // this is the only UITableViewDataSource method we have to implement 42 | // if we use a CoreDataTableViewController 43 | // the most important call is fetchedResultsController?.objectAtIndexPath(indexPath) 44 | // (that's how we get the object that is in this row so we can load the cell up) 45 | 46 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 47 | let cell = tableView.dequeueReusableCellWithIdentifier("TwitterUserCell", forIndexPath: indexPath) 48 | 49 | if let twitterUser = fetchedResultsController?.objectAtIndexPath(indexPath) as? TwitterUser { 50 | var screenName: String? 51 | twitterUser.managedObjectContext?.performBlockAndWait { 52 | // it's easy to forget to do this on the proper queue 53 | screenName = twitterUser.screenName 54 | // we're not assuming the context is a main queue context 55 | // so we'll grab the screenName and return to the main queue 56 | // to do the cell.textLabel?.text setting 57 | } 58 | cell.textLabel?.text = screenName 59 | if let count = tweetCountWithMentionByTwitterUser(twitterUser) { 60 | cell.detailTextLabel?.text = (count == 1) ? "1 tweet" : "\(count) tweets" 61 | } else { 62 | cell.detailTextLabel?.text = "" 63 | } 64 | } 65 | 66 | return cell 67 | } 68 | 69 | // private func which figures out how many tweets 70 | // were tweeted by the given user that contain our mention 71 | 72 | private func tweetCountWithMentionByTwitterUser(user: TwitterUser) -> Int? 73 | { 74 | var count: Int? 75 | user.managedObjectContext?.performBlockAndWait { 76 | let request = NSFetchRequest(entityName: "Tweet") 77 | request.predicate = NSPredicate(format: "text contains[c] %@ and tweeter = %@", self.mention!, user) 78 | count = user.managedObjectContext?.countForFetchRequest(request, error: nil) 79 | } 80 | return count 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/TwitterUser+CoreDataProperties.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TwitterUser+CoreDataProperties.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | // Choose "Create NSManagedObject Subclass…" from the Core Data editor menu 9 | // to delete and recreate this implementation file for your updated model. 10 | // 11 | 12 | import Foundation 13 | import CoreData 14 | 15 | extension TwitterUser { 16 | 17 | @NSManaged var screenName: String? 18 | @NSManaged var name: String? 19 | @NSManaged var tweets: NSSet? 20 | 21 | } 22 | -------------------------------------------------------------------------------- /democode/Smashtag-L11/Smashtag/TwitterUser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TwitterUser.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreData 11 | import Twitter 12 | 13 | class TwitterUser: NSManagedObject 14 | { 15 | // a class method which 16 | // returns a TwitterUser from the database if Twitter.User has already been put in 17 | // or returns a newly-added-to-the-database TwitterUser if not 18 | 19 | class func twitterUserWithTwitterInfo(twitterInfo: Twitter.User, inManagedObjectContext context: NSManagedObjectContext) -> TwitterUser? 20 | { 21 | let request = NSFetchRequest(entityName: "TwitterUser") 22 | request.predicate = NSPredicate(format: "screenName = %@", twitterInfo.screenName) 23 | if let twitterUser = (try? context.executeFetchRequest(request))?.first as? TwitterUser { 24 | return twitterUser 25 | } else if let twitterUser = NSEntityDescription.insertNewObjectForEntityForName("TwitterUser", inManagedObjectContext: context) as? TwitterUser { 26 | twitterUser.screenName = twitterInfo.screenName 27 | twitterUser.name = twitterInfo.name 28 | return twitterUser 29 | } 30 | return nil 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/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 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/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 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/TweetTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TweetTableViewCell.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Twitter 11 | 12 | class TweetTableViewCell: UITableViewCell 13 | { 14 | @IBOutlet weak var tweetScreenNameLabel: UILabel! 15 | @IBOutlet weak var tweetTextLabel: UILabel! 16 | @IBOutlet weak var tweetProfileImageView: UIImageView! 17 | @IBOutlet weak var tweetCreatedLabel: UILabel! 18 | 19 | var tweet: Twitter.Tweet? { 20 | didSet { 21 | updateUI() 22 | } 23 | } 24 | 25 | private func updateUI() 26 | { 27 | // reset any existing tweet information 28 | tweetTextLabel?.attributedText = nil 29 | tweetScreenNameLabel?.text = nil 30 | tweetProfileImageView?.image = nil 31 | tweetCreatedLabel?.text = nil 32 | 33 | // load new information from our tweet (if any) 34 | if let tweet = self.tweet 35 | { 36 | tweetTextLabel?.text = tweet.text 37 | if tweetTextLabel?.text != nil { 38 | for _ in tweet.media { 39 | tweetTextLabel.text! += " 📷" 40 | } 41 | } 42 | 43 | tweetScreenNameLabel?.text = "\(tweet.user)" // tweet.user.description 44 | 45 | if let profileImageURL = tweet.user.profileImageURL { 46 | if let imageData = NSData(contentsOfURL: profileImageURL) { // blocks main thread! 47 | tweetProfileImageView?.image = UIImage(data: imageData) 48 | } 49 | } 50 | 51 | let formatter = NSDateFormatter() 52 | if NSDate().timeIntervalSinceDate(tweet.created) > 24*60*60 { 53 | formatter.dateStyle = NSDateFormatterStyle.ShortStyle 54 | } else { 55 | formatter.timeStyle = NSDateFormatterStyle.ShortStyle 56 | } 57 | tweetCreatedLabel?.text = formatter.stringFromDate(tweet.created) 58 | } 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Smashtag/Smashtag/TweetTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TweetTableViewController.swift 3 | // Smashtag 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Twitter 11 | 12 | class TweetTableViewController: UITableViewController, UITextFieldDelegate 13 | { 14 | // MARK: Model 15 | 16 | var tweets = [Array]() { 17 | didSet { 18 | tableView.reloadData() 19 | } 20 | } 21 | 22 | var searchText: String? { 23 | didSet { 24 | tweets.removeAll() 25 | lastTwitterRequest = nil 26 | searchForTweets() 27 | title = searchText 28 | } 29 | } 30 | 31 | // MARK: Fetching Tweets 32 | 33 | private var twitterRequest: Twitter.Request? { 34 | if lastTwitterRequest == nil { 35 | if let query = searchText where !query.isEmpty { 36 | return Twitter.Request(search: query + " -filter:retweets", count: 100) 37 | } 38 | } 39 | return lastTwitterRequest?.requestForNewer 40 | } 41 | 42 | private var lastTwitterRequest: Twitter.Request? 43 | 44 | private func searchForTweets() 45 | { 46 | if let request = twitterRequest { 47 | lastTwitterRequest = request 48 | request.fetchTweets { [weak weakSelf = self] newTweets in 49 | dispatch_async(dispatch_get_main_queue()) { 50 | if request == weakSelf?.lastTwitterRequest { 51 | if !newTweets.isEmpty { 52 | weakSelf?.tweets.insert(newTweets, atIndex: 0) 53 | } 54 | } 55 | weakSelf?.refreshControl?.endRefreshing() 56 | } 57 | } 58 | } else { 59 | self.refreshControl?.endRefreshing() 60 | } 61 | } 62 | 63 | @IBAction func refresh(sender: UIRefreshControl) { 64 | searchForTweets() 65 | } 66 | 67 | // MARK: UITableViewDataSource 68 | 69 | override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 70 | return "\(tweets.count - section)" 71 | } 72 | 73 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 74 | return tweets.count 75 | } 76 | 77 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 78 | return tweets[section].count 79 | } 80 | 81 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 82 | let cell = tableView.dequeueReusableCellWithIdentifier(Storyboard.TweetCellIdentifier, forIndexPath: indexPath) 83 | 84 | let tweet = tweets[indexPath.section][indexPath.row] 85 | if let tweetCell = cell as? TweetTableViewCell { 86 | tweetCell.tweet = tweet 87 | } 88 | 89 | return cell 90 | } 91 | 92 | // MARK: Constants 93 | 94 | private struct Storyboard { 95 | static let TweetCellIdentifier = "Tweet" 96 | } 97 | 98 | // MARK: Outlets 99 | 100 | @IBOutlet weak var searchTextField: UITextField! { 101 | didSet { 102 | searchTextField.delegate = self 103 | searchTextField.text = searchText 104 | } 105 | } 106 | 107 | // MARK: UITextFieldDelegate 108 | 109 | func textFieldShouldReturn(textField: UITextField) -> Bool { 110 | textField.resignFirstResponder() 111 | searchText = textField.text 112 | return true 113 | } 114 | 115 | // MARK: View Controller Lifecycle 116 | 117 | override func viewDidLoad() { 118 | super.viewDidLoad() 119 | tableView.estimatedRowHeight = tableView.rowHeight 120 | tableView.rowHeight = UITableViewAutomaticDimension 121 | } 122 | 123 | /* 124 | // MARK: - Navigation 125 | 126 | // In a storyboard-based application, you will often want to do a little preparation before navigation 127 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 128 | // Get the new view controller using segue.destinationViewController. 129 | // Pass the selected object to the new view controller. 130 | } 131 | */ 132 | } 133 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Twitter/Twitter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Twitter/Twitter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en_US 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Twitter/Twitter/MediaItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaItem.swift 3 | // Twitter 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2015 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // holds the network url and aspectRatio of an image attached to a Tweet 12 | // created automatically when a Tweet object is created 13 | 14 | public class MediaItem: NSObject 15 | { 16 | public let url: NSURL 17 | public let aspectRatio: Double 18 | 19 | public override var description: String { return "\(url.absoluteString) (aspect ratio = \(aspectRatio))" } 20 | 21 | // MARK: - Internal Implementation 22 | 23 | init?(data: NSDictionary?) { 24 | guard 25 | let height = data?.valueForKeyPath(TwitterKey.Height) as? Double where height > 0, 26 | let width = data?.valueForKeyPath(TwitterKey.Width) as? Double where width > 0, 27 | let urlString = data?.valueForKeyPath(TwitterKey.MediaURL) as? String, 28 | let url = NSURL(string: urlString) 29 | else { 30 | return nil 31 | } 32 | self.url = url 33 | self.aspectRatio = width/height 34 | } 35 | 36 | struct TwitterKey { 37 | static let MediaURL = "media_url_https" 38 | static let Width = "sizes.small.w" 39 | static let Height = "sizes.small.h" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Twitter/Twitter/Twitter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Twitter.h 3 | // Twitter 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2015 Stanford University. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Twitter. 12 | FOUNDATION_EXPORT double TwitterVersionNumber; 13 | 14 | //! Project version string for Twitter. 15 | FOUNDATION_EXPORT const unsigned char TwitterVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | -------------------------------------------------------------------------------- /democode/Smashtag-L9/Twitter/Twitter/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // Twitter 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright (c) 2015 Stanford University. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // container to hold data about a Twitter user 12 | 13 | public class User: NSObject 14 | { 15 | public let screenName: String 16 | public let name: String 17 | public let id: String 18 | public let verified: Bool 19 | public let profileImageURL: NSURL? 20 | 21 | public override var description: String { return "@\(screenName) (\(name))\(verified ? " ✅" : "")" } 22 | 23 | // MARK: - Internal Implementation 24 | 25 | init?(data: NSDictionary?) { 26 | guard 27 | let screenName = data?.valueForKeyPath(TwitterKey.ScreenName) as? String, 28 | let name = data?.valueForKeyPath(TwitterKey.Name) as? String, 29 | let id = data?.valueForKeyPath(TwitterKey.ID) as? String 30 | else { 31 | return nil 32 | } 33 | 34 | self.screenName = screenName 35 | self.name = name 36 | self.id = id 37 | 38 | self.verified = data?.valueForKeyPath(TwitterKey.Verified)?.boolValue ?? false 39 | let urlString = data?.valueForKeyPath(TwitterKey.ProfileImageURL) as? String ?? "" 40 | self.profileImageURL = (urlString.characters.count > 0) ? NSURL(string: urlString) : nil 41 | } 42 | 43 | var asPropertyList: AnyObject { 44 | return [ 45 | TwitterKey.Name:name, 46 | TwitterKey.ScreenName:screenName, 47 | TwitterKey.ID:id, 48 | TwitterKey.Verified:verified ? "YES" : "NO", 49 | TwitterKey.ProfileImageURL:profileImageURL?.absoluteString ?? "" 50 | ] 51 | } 52 | 53 | struct TwitterKey { 54 | static let Name = "name" 55 | static let ScreenName = "screen_name" 56 | static let ID = "id_str" 57 | static let Verified = "verified" 58 | static let ProfileImageURL = "profile_image_url" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Trax 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/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 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/EditWaypointViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EditWaypointViewController.swift 3 | // Trax 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class EditWaypointViewController: UIViewController, UITextFieldDelegate 12 | { 13 | // MARK: Public API 14 | 15 | var waypointToEdit: EditableWaypoint? { didSet { updateUI() } } 16 | 17 | // MARK: View Controller Lifecycle 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | updateUI() 22 | nameTextField.becomeFirstResponder() 23 | } 24 | 25 | override func viewDidAppear(animated: Bool) { 26 | super.viewDidAppear(animated) 27 | listenToTextFields() 28 | } 29 | 30 | override func viewWillDisappear(animated: Bool) { 31 | super.viewWillDisappear(animated) 32 | stopListeningToTextFields() 33 | } 34 | 35 | override func viewWillLayoutSubviews() { 36 | super.viewWillLayoutSubviews() 37 | preferredContentSize = view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) 38 | } 39 | 40 | // MARK: Private Implementation 41 | 42 | @IBOutlet weak var nameTextField: UITextField! { didSet { nameTextField.delegate = self } } 43 | @IBOutlet weak var infoTextField: UITextField! { didSet { infoTextField.delegate = self } } 44 | 45 | private func updateUI() { 46 | nameTextField?.text = waypointToEdit?.name 47 | infoTextField?.text = waypointToEdit?.info 48 | } 49 | 50 | private var ntfObserver: NSObjectProtocol? 51 | private var itfObserver: NSObjectProtocol? 52 | 53 | private func listenToTextFields() 54 | { 55 | let center = NSNotificationCenter.defaultCenter() 56 | let queue = NSOperationQueue.mainQueue() 57 | 58 | ntfObserver = center.addObserverForName( 59 | UITextFieldTextDidChangeNotification, 60 | object: nameTextField, 61 | queue: queue) 62 | { notification in 63 | if let waypoint = self.waypointToEdit { 64 | waypoint.name = self.nameTextField.text 65 | } 66 | } 67 | itfObserver = center.addObserverForName( 68 | UITextFieldTextDidChangeNotification, 69 | object: infoTextField, 70 | queue: queue) 71 | { notification in 72 | if let waypoint = self.waypointToEdit { 73 | waypoint.info = self.infoTextField.text 74 | } 75 | } 76 | } 77 | 78 | private func stopListeningToTextFields() { 79 | if let observer = ntfObserver { 80 | NSNotificationCenter.defaultCenter().removeObserver(observer) 81 | } 82 | if let observer = itfObserver { 83 | NSNotificationCenter.defaultCenter().removeObserver(observer) 84 | } 85 | } 86 | 87 | // MARK: UITextFieldDelegate 88 | 89 | func textFieldShouldReturn(textField: UITextField) -> Bool { 90 | textField.resignFirstResponder() 91 | return true 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/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 | NSAppTransportSecurity 40 | 41 | NSAllowsArbitraryLoads 42 | 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /democode/Trax-L18/Trax/MKGPX.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MKGPX.swift 3 | // Trax 4 | // 5 | // Created by CS193p Instructor. 6 | // Copyright © 2016 Stanford University. All rights reserved. 7 | // 8 | // Enhancements to GPX.Waypoint to support MKMapView 9 | 10 | import MapKit 11 | 12 | // EditableWaypoints are draggable 13 | // so their coordinate needs to be settable 14 | 15 | class EditableWaypoint : GPX.Waypoint 16 | { 17 | override var coordinate: CLLocationCoordinate2D { 18 | get { 19 | return super.coordinate 20 | } 21 | set { 22 | latitude = newValue.latitude 23 | longitude = newValue.longitude 24 | } 25 | } 26 | } 27 | 28 | extension GPX.Waypoint : MKAnnotation 29 | { 30 | var coordinate: CLLocationCoordinate2D { 31 | return CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 32 | } 33 | 34 | var title: String? { return name } 35 | 36 | var subtitle: String? { return info } 37 | 38 | var thumbnailURL: NSURL? { 39 | return getImageURLofType("thumbnail") 40 | } 41 | 42 | var imageURL: NSURL? { 43 | return getImageURLofType("large") 44 | } 45 | 46 | // look in the hyperlink information from the GPX file 47 | // try to find a url with a given type 48 | 49 | private func getImageURLofType(type: String?) -> NSURL? { 50 | for link in links { 51 | if link.type == type { 52 | return link.url 53 | } 54 | } 55 | return nil 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /problemsets/Programming_Project_1_Calculator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_1_Calculator.pdf -------------------------------------------------------------------------------- /problemsets/Programming_Project_2_Calculator_Brain.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_2_Calculator_Brain.pdf -------------------------------------------------------------------------------- /problemsets/Programming_Project_3_Graphic_Calculator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_3_Graphic_Calculator.pdf -------------------------------------------------------------------------------- /problemsets/Programming_Project_4_Smashtag_Mentions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_4_Smashtag_Mentions.pdf -------------------------------------------------------------------------------- /problemsets/Programming_Project_5_Smashtag_Ment.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_5_Smashtag_Ment.pdf -------------------------------------------------------------------------------- /problemsets/Programming_Project_6_Animation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/Programming_Project_6_Animation.pdf -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/AppIcon.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/AppIcon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/AppIcon.xcf -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-40@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-60@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-72.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-72@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-76.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-76@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-83.5@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small-50.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon-Small@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/Icon@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/iTunesArtwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/iTunesArtwork.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/AppIcon/IconSet/iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/AppIcon/IconSet/iTunesArtwork@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator00.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator00.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator01.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator02.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator03.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator04.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator05.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator06.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator06.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/Art/Screenshot/Calculator07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Art/Screenshot/Calculator07.gif -------------------------------------------------------------------------------- /problemsets/assignment-1/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | ## Post an Issue 4 | 5 | If you discover a bug or error, please [add an issue](https://github.com/duliodenis/cs193p-Spring-2016/issues) here on GitHub. Feature requests are welcome. However, I am a one-man band, so pull requests are preferred. 6 | 7 | 8 | ## Create a Pull Request 9 | 10 | Fork the project, create a branch, commit your changes, and then create a pull request. Please submit your pull request to the **develop** branch of this repository. 11 | 12 | The **master** branch is for production-ready content and should not contain incomplete features. Development occurs on the **develop** branch. Once your pull request is accepted, it will be merged into **master**. 13 | 14 | 15 | ## Licensing 16 | Vending Machine is licensed under [the MIT License](LICENSE). 17 | 18 | ## Support or Contact 19 | Visit [ddApps.co](http://ddapps.co) to see more. -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Calculator 4 | // 5 | // Created by Dulio Denis on 5/1/16. 6 | // Copyright © 2016 Dulio Denis. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-Small.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-Small@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "83.5x83.5", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-83.5@2x.png", 79 | "scale" : "2x" 80 | } 81 | ], 82 | "info" : { 83 | "version" : 1, 84 | "author" : "xcode" 85 | } 86 | } -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/problemsets/assignment-1/Calculator/Calculator/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/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 | -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/CalculatorBrain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CalculatorBrain.swift 3 | // Calculator 4 | // 5 | // Created by Dulio Denis on 5/2/16. 6 | // Copyright © 2016 Dulio Denis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CalculatorBrain { 12 | 13 | private var accumulator = 0.0 14 | private var memory = 0.0 15 | 16 | func setOperand(operand: Double) { 17 | accumulator = operand 18 | } 19 | 20 | private var operations: Dictionary = [ 21 | "π" : Operation.Constant(M_PI), 22 | "e" : Operation.Constant(M_E), 23 | "±" : Operation.UnaryOperation({ -$0 }), 24 | "√" : Operation.UnaryOperation(sqrt), 25 | "x^2" : Operation.UnaryOperation({ pow($0, 2.0) }), 26 | "cos" : Operation.UnaryOperation(cos), 27 | "sin" : Operation.UnaryOperation(sin), 28 | "tan" : Operation.UnaryOperation(tan), 29 | "×" : Operation.BinaryOperation({ $0 * $1 }), 30 | "÷" : Operation.BinaryOperation({ $0 / $1 }), 31 | "+" : Operation.BinaryOperation({ $0 + $1 }), 32 | "-" : Operation.BinaryOperation({ $0 - $1 }), 33 | "=" : Operation.Equals 34 | ] 35 | 36 | private enum Operation { 37 | case Constant(Double) 38 | case UnaryOperation((Double) -> Double) 39 | case BinaryOperation((Double, Double) -> Double) 40 | case Equals 41 | } 42 | 43 | func performOperation(symbol: String) { 44 | if let operation = operations[symbol] { 45 | switch operation { 46 | case .Constant(let value): 47 | accumulator = value 48 | case .UnaryOperation(let function): 49 | accumulator = function(accumulator) 50 | case .BinaryOperation(let function): 51 | executePendingBinaryOperation() 52 | pending = PendingBinaryOperationInfo(binaryFunction: function, firstOperand: accumulator) 53 | case .Equals: 54 | executePendingBinaryOperation() 55 | } 56 | } 57 | } 58 | 59 | private func executePendingBinaryOperation() { 60 | if pending != nil { 61 | accumulator = pending!.binaryFunction(pending!.firstOperand, accumulator) 62 | pending = nil 63 | } 64 | } 65 | 66 | private var pending: PendingBinaryOperationInfo? 67 | 68 | private struct PendingBinaryOperationInfo { 69 | var binaryFunction: (Double, Double) -> Double 70 | var firstOperand: Double 71 | } 72 | 73 | var result: Double { 74 | get { 75 | return accumulator 76 | } 77 | } 78 | 79 | func clear() { 80 | accumulator = 0.0 81 | } 82 | } -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/RoundedButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedButton.swift 3 | // Calculator 4 | // 5 | // Created by Dulio Denis on 5/7/16. 6 | // Copyright © 2016 Dulio Denis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class RoundedButton: UIButton { 12 | 13 | override func awakeFromNib() { 14 | layer.cornerRadius = 5.0 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /problemsets/assignment-1/Calculator/Calculator/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Calculator 4 | // 5 | // Created by Dulio Denis on 5/1/16. 6 | // Copyright © 2016 Dulio Denis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet private weak var display: UILabel! 14 | @IBOutlet private weak var calculationTape: UILabel! 15 | 16 | private var userIsInTheMiddleOfTyping = false 17 | private var decimalUsed = false 18 | 19 | @IBAction private func touchDigit(sender: UIButton) { 20 | let digit = sender.currentTitle! 21 | 22 | if userIsInTheMiddleOfTyping { 23 | 24 | if digit == "." && decimalUsed == true { 25 | return 26 | } else if digit == "." && decimalUsed == false { 27 | decimalUsed = true 28 | } 29 | 30 | let textCurrentlyInDisplay = display.text! 31 | display.text = textCurrentlyInDisplay + digit 32 | } else { 33 | display.text = digit 34 | } 35 | 36 | userIsInTheMiddleOfTyping = true 37 | } 38 | 39 | // computed property is calculated when getting and setting 40 | private var displayValue: Double { 41 | get { 42 | return Double(display.text!)! 43 | } 44 | 45 | set { 46 | display.text = String(newValue) 47 | } 48 | } 49 | 50 | private var brain = CalculatorBrain() 51 | 52 | @IBAction private func performOperation(sender: UIButton) { 53 | if userIsInTheMiddleOfTyping { 54 | brain.setOperand(displayValue) 55 | userIsInTheMiddleOfTyping = false 56 | } 57 | 58 | if let mathematicalSymbol = sender.currentTitle { 59 | brain.performOperation(mathematicalSymbol) 60 | } 61 | 62 | displayValue = brain.result 63 | } 64 | 65 | @IBAction func clear(sender: AnyObject) { 66 | userIsInTheMiddleOfTyping = false 67 | decimalUsed = false 68 | brain.clear() 69 | displayValue = brain.result 70 | display.text = "0" 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /problemsets/assignment-1/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Dulio Denis 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 | -------------------------------------------------------------------------------- /problemsets/assignment-1/README.md: -------------------------------------------------------------------------------- 1 | # CS193p - Assignment 1: Calculator 2 | 3 | An iOS 9 / Swift 2 Calculator App that recreates the demonstration given in lecture and then make some small enhancements. 4 | 5 | ![](Art/Screenshot/Calculator07.gif?raw=true) 6 | 7 | ## Contributing 8 | 9 | See [CONTRIBUTING.md](CONTRIBUTING.md). 10 | 11 | ## Licensing 12 | Calculator is licensed under [the MIT License](LICENSE). 13 | 14 | ## Support or Contact 15 | Visit [ddApps.co](http://ddapps.co) to see more. -------------------------------------------------------------------------------- /reading/Reading_1_Intro_to_Swift.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/reading/Reading_1_Intro_to_Swift.pdf -------------------------------------------------------------------------------- /reading/Reading_2_More_Swift.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/reading/Reading_2_More_Swift.pdf -------------------------------------------------------------------------------- /reading/Reading_3_The_Rest_of_Swift.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/reading/Reading_3_The_Rest_of_Swift.pdf -------------------------------------------------------------------------------- /slides/Lecture-1-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-1-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-10-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-10-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-11-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-11-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-12-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-12-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-13-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-13-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-14-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-14-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-15-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-15-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-16-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-16-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-17-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-17-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-18-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-18-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-2-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-2-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-3-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-3-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-4-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-4-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-5-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-5-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-6-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-6-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-7-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-7-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-8-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-8-Slides.pdf -------------------------------------------------------------------------------- /slides/Lecture-9-Slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/cs193p-Spring-2016/6f095651b4c27a13c558f7afe0c23920531ef313/slides/Lecture-9-Slides.pdf --------------------------------------------------------------------------------