├── .gitignore ├── .gitmodules ├── BasicSwift.playground ├── Contents.swift ├── Documentation │ ├── playground.css │ └── section-1.html ├── Sources │ └── SupportCode.swift ├── contents.xcplayground ├── playground.xcworkspace │ └── contents.xcworkspacedata └── timeline.xctimeline ├── FileIO.playground ├── Contents.swift ├── Resources │ └── BundledFile.txt ├── Sources │ └── SupportCode.swift ├── contents.xcplayground └── playground.xcworkspace │ └── contents.xcworkspacedata ├── JSON.playground ├── Contents.swift ├── Resources │ └── test.json ├── Sources │ └── SupportCode.swift ├── contents.xcplayground └── timeline.xctimeline ├── Networking.playground ├── Contents.swift ├── Resources │ └── JSON.playground │ │ ├── Contents.swift │ │ ├── Resources │ │ └── test.json │ │ ├── Sources │ │ └── SupportCode.swift │ │ ├── contents.xcplayground │ │ └── timeline.xctimeline ├── Sources │ └── SupportCode.swift └── contents.xcplayground ├── Playgrounds.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── Playgrounds.xccheckout └── xcuserdata │ └── daniel.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ ├── WorkspaceSettings.xcsettings │ └── xcschemes │ └── xcschememanagement.plist └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "SwiftyJSON"] 2 | path = SwiftyJSON 3 | url = https://github.com/SwiftyJSON/SwiftyJSON.git 4 | [submodule "Alamofire"] 5 | path = Alamofire 6 | url = https://github.com/Alamofire/Alamofire.git 7 | [submodule "Just"] 8 | path = Just 9 | url = https://github.com/JustHTTP/Just.git 10 | -------------------------------------------------------------------------------- /BasicSwift.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | 3 | # Intro to Swift for App Development 4 | 5 | Swift is a full featured language with lots of nice capabilities, but it's not necessary to know everything about it to start writing some basic apps for the Mac Desktop. 6 | 7 | The goal of this document is to walk through the basics of the language and showcase the things that you'll need to know to start writing apps. 8 | 9 | ## Output 10 | 11 | As is traditional, we start by writing to STDOUT. In GUI apps this is useful for light debugging. 12 | 13 | */ 14 | 15 | println("Hello World!") 16 | 17 | 18 | /*: 19 | 20 | ## Data 21 | 22 | There are two ways to store it: constants and variables. Constants can be set once and are immutable (you can't change them). Variables can be changed as much as you want. Use constants whenever possible, as the compiler can optimize them more. 23 | 24 | */ 25 | 26 | let answer = 42 27 | var donuts = "Yes" 28 | 29 | /*: 30 | 31 | ## Types 32 | 33 | Swift is a staticly typed language, meaning you need to declare a type for your data. However most of the time Swift can infer the type based on what you assign to the variable. 34 | 35 | In the examples above, the type of the first object is an Int and the second is a String. 36 | 37 | In some situations you need to explicitly set the type, for example if you are not providing an initial value. That is done with the following syntax. 38 | 39 | */ 40 | 41 | var x:Int 42 | var y:String 43 | 44 | /*: 45 | 46 | ## Collections 47 | 48 | Printing the values of a constant or variable is easy. No need to concat strings together. 49 | 50 | */ 51 | 52 | println("Answer to the Ultimate Question of Life, the Universe, and Everything is ... \(answer)") 53 | println("Would you like donuts? \(donuts), please") 54 | 55 | /*: 56 | 57 | Lists can be used to store collection of the same type of items. You can bend this rule a bit by using Any or AnyObject, but you should only do that when you need to. It's better to be specific. [See docs for more](https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html). 58 | 59 | */ 60 | 61 | var myList = [1,2,3,4,5,6,7,8] 62 | var myMixedList:[Any] = ["1", 2, ["a", "b", "c"], 3] 63 | 64 | /*: 65 | 66 | A dictionary or map can be used to store key/value pairs. It has the same restriction as lists, the types must be the same unless you make use of Any / AnyObject. 67 | 68 | */ 69 | 70 | var myDict = ["name": "Frank", "age": "43", "weight": "106"] 71 | var myMixedDict:[String:Any] = ["name": "Frank", "age": 43, "weight": 106] 72 | 73 | /*: 74 | 75 | Printing values from a list works like you'd expect. Printing values from a dictionary requires an intermediate variable. 76 | 77 | */ 78 | 79 | println("Some value = \(myList[2])") 80 | 81 | var age = myDict["age"] 82 | println("Some value = \(age)") 83 | 84 | /*: 85 | 86 | ## Control Flow 87 | 88 | Swift offers several looping and conditional statements that allow you to easily control the flow of your code. Not going to cover all of them here. This doc just aims to show how you'd accomplish some common tasks. For a complete reference, [see the docs](https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID120). 89 | 90 | ### Loops 91 | 92 | There's two options for looping through the elements of a list. The first option is `for..in` and the second is the traditional C style for loop. 93 | 94 | */ 95 | 96 | for v in myList { 97 | println(v) 98 | } 99 | 100 | for (i, v) in enumerate(myList) { 101 | println("\(i).) \(v)") 102 | } 103 | 104 | for var i = 1; i <= myList.count; ++i { 105 | println("\(i).) \(myList[i-1])") 106 | } 107 | 108 | /*: 109 | 110 | Looping through a dictionary can be done easily with a `for..in` loop. While possible with a traditional C style loop, it's not nearly as elegant. 111 | 112 | */ 113 | 114 | for (k, v) in myDict { 115 | println("\(k) == \(v)") 116 | } 117 | 118 | /*: 119 | 120 | Iterating over some code a certain number of times is also straightforward. You can do it with a C style loop or with `for..in` and a sequence. 121 | 122 | */ 123 | 124 | for var i = 0; i < 10; i++ { 125 | print("\(i) ") 126 | } 127 | 128 | for i in 0...9 { 129 | print("\(i) ") 130 | } 131 | 132 | for i in 0..<10 { 133 | print("\(i) ") 134 | } 135 | 136 | /*: 137 | 138 | ### Conditionals 139 | 140 | Conditionals are similar to other languages. Swift also supports a switch statement, if that's something you'd like to use. 141 | 142 | */ 143 | 144 | if answer != 42 { 145 | println("WRONG!!") 146 | } else { 147 | println("RIGHT!!") 148 | } 149 | 150 | /*: 151 | 152 | The conditional in an if statement must be a boolean. You cannot do `if found { ... }`. There's no implicit comparison to 0 or nil. It's just an error. This leads us to optionals. 153 | 154 | ### Optionals 155 | 156 | Defining an optional. The ? after means it may have a value or may be nil. Check out what happens when you change `maybeAValue` to nil. 157 | 158 | */ 159 | 160 | let maybeAValue:String? = "George Washington" 161 | 162 | 163 | /*: 164 | 165 | Some common things to do with an optional: 166 | 167 | - check if it's nil 168 | - print it 169 | - get the value (done with the trailing `!`) 170 | 171 | */ 172 | 173 | println("is nil? \(maybeAValue == nil)") 174 | println("contents of value: \(maybeAValue)") 175 | println("get the value: \(maybeAValue!)") 176 | 177 | /*: 178 | 179 | You can also use the `if..let` syntax to make working with them easier. The example below roughly reads "if maybeAValue has a value then set name to its value and run this block of code". If it's nil, just skip the whole block. 180 | 181 | */ 182 | 183 | if let name = maybeAValue { 184 | println("Yay! We have a name: \(name)") 185 | } 186 | 187 | /*: 188 | 189 | It's roughly the same as checking it against nil and using the exclamation mark to unwrap the actual value. 190 | 191 | */ 192 | 193 | if maybeAValue != nil { 194 | println("Yay! We have a name: \(maybeAValue!)") 195 | } 196 | 197 | /*: 198 | 199 | ## Functions & Closures 200 | 201 | We also need to know how to define functions and the similar closure. These will be useful as we build apps because we can use them to define and attach behaviors to our GUI. i.e. make it do stuff. 202 | 203 | ### Functions 204 | 205 | This is how you define a function. Each function has a name, which is how you refer to it later. It can be given zero or more parameters and it can return zero or more values. This is not all, there's lots more you can do with functions like named parameters, default values, etc.. [See the docs](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID158) for more on that. 206 | 207 | */ 208 | 209 | func greet(name: String, greeting: String) -> String { 210 | return "\(greeting) \(name)" 211 | } 212 | 213 | /*: 214 | 215 | Calling functions works like you'd expect if you programmed in other languages. You call the name and pass in the arguments. 216 | 217 | */ 218 | 219 | greet("Dan", "Hello") 220 | 221 | /*: 222 | 223 | You can also pass functions around as objects. This includes assigning them to variables and constants, passing them into functions and returning them from functions. When passing into or out of a function, any functions that match the signature can be intermixed freely. 224 | 225 | */ 226 | 227 | var greet_other: (String, String) -> String = greet 228 | greet_other("Dan", "Bye") 229 | 230 | func reverse_greeting(name: String, greeting: String) -> String { 231 | return "\(name) \(greeting)" 232 | } 233 | 234 | reverse_greeting("Dan", "Hello") 235 | 236 | greet_other = reverse_greeting 237 | greet_other("Dan", "Bye") 238 | 239 | /*: 240 | 241 | ### Closures 242 | 243 | Closures are similar to functions, but don't have a name and offer some syntax simplifications when passing them into functions. 244 | 245 | Here we do a comparison of a factorial function and closure. Both do the same thing, there is no difference other than the minor change in syntax. 246 | 247 | */ 248 | 249 | func fact(i:Int) -> Int { 250 | return (i == 0) ? 1 : (i * fact(i - 1)) 251 | } 252 | fact(5) 253 | fact(8) 254 | 255 | let factorial: (Int) -> Int 256 | factorial = { i -> Int in 257 | return (i == 0) ? 1 : (i * factorial(i - 1)) 258 | } 259 | factorial(5) 260 | factorial(8) 261 | 262 | /*: 263 | 264 | Where closures are helpful is when passing them into functions. The examples below show the difference between passing a function or a closure. 265 | 266 | **Function** 267 | 268 | */ 269 | 270 | func double(i:Int) -> Int { 271 | return i * i 272 | } 273 | [1,2,3,4,5,6].map(double) 274 | 275 | //: **Closure** 276 | 277 | [1,2,3,4,5,6].map { i -> Int in 278 | i * i 279 | } 280 | 281 | /*: 282 | 283 | That's about it. At this point, you should have a good handle on the basics that are necessary to start writing apps in Swift. 284 | 285 | Feel free to play around with the demos here more or try out [Apple's Swift Tour Playground](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1). 286 | */ 287 | -------------------------------------------------------------------------------- /BasicSwift.playground/Documentation/playground.css: -------------------------------------------------------------------------------- 1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,figure,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td { 2 | /* background: transparent; */ 3 | border: 0; 4 | font-size: 100%; 5 | margin: 0; 6 | outline: 0; 7 | padding: 0; 8 | vertical-align: baseline 9 | } 10 | body.jazz { 11 | background-color: rgba(255,255,255,0.65); 12 | color: rgba(0,0,0,1); 13 | font-family: Helvetica,Arial,sans-serif; 14 | font-size: 62.5%; 15 | margin-left: 15px; 16 | } 17 | .jazz a[name] { 18 | display: block; 19 | padding-top: 85px; 20 | margin: -95px 0 0 21 | } 22 | .jazz .content-wrapper { 23 | /* background-color: rgba(255,255,255,1); */ 24 | margin: 0 auto; 25 | } 26 | .jazz .chapter { 27 | /* background-color: rgba(255,255,255,1); */ 28 | border: 1px solid rgba(238,238,238,1); 29 | box-shadow: 0 0 1px rgba(0,0,0,.07); 30 | display: block; 31 | margin-left: 246px; 32 | min-height: calc(100% - 173px); 33 | min-height: -moz-calc(100% - 173px); 34 | min-height: -webkit-calc(100% - 173px); 35 | min-height: -o-calc(100% - 173px); 36 | position: absolute; 37 | overflow: auto; 38 | padding-bottom: 100px; 39 | top: 70px; 40 | -webkit-overflow-scrolling: touch; 41 | } 42 | .jazz #mini_toc { 43 | /* background-color: rgba(255,255,255,1); */ 44 | background-image: url(../Images/plus_2x.png); 45 | background-position: 90% 11px; 46 | background-repeat: no-repeat; 47 | background-size: 12px 12px; 48 | border: 1px solid rgba(238,238,238,1); 49 | box-shadow: 0 0 1px rgba(0,0,0,.07); 50 | margin-left: 505px; 51 | padding: 10px 10px 0 15px; 52 | position: fixed; 53 | top: 85px; 54 | width: 190px; 55 | z-index: 1; 56 | overflow: auto; 57 | height: 25px; 58 | max-height: 500px; 59 | -webkit-transition: height .3s ease,-webkit-transform .3s ease; 60 | -moz-transition: height .3s ease,-moz-transform .3s ease; 61 | -o-transition: height .3s ease,-o-transform .3s ease; 62 | -ms-transition: height .3s ease,-ms-transform .3s ease; 63 | transition: height .3s ease,transform .3s ease 64 | } 65 | .jazz #mini_toc.slide-out { 66 | -webkit-transform: translateY(-85px); 67 | -moz-transform: translateY(-85px); 68 | -o-transform: translateY(-85px); 69 | -ms-transform: translateY(-85px); 70 | transform: translateY(-85px) 71 | } 72 | .jazz #mini_toc.open { 73 | background-image: url(../Images/minus_2x.png); 74 | z-index: 2 75 | } 76 | .jazz #mini_toc #mini_toc_button { 77 | cursor: pointer; 78 | width: 195px 79 | } 80 | 81 | .jazz .section { 82 | padding: 20px 25px 20px 35px 83 | } 84 | .jazz .section .section { 85 | margin: 30px 0 0; 86 | padding: 0 87 | } 88 | .jazz .clear { 89 | } 90 | .jazz .two-columns { 91 | clear: both; 92 | display: table; 93 | margin: 60px auto; 94 | vertical-align: middle; 95 | width: 85% 96 | } 97 | .jazz .left-column,.jazz .right-column { 98 | display: table-cell; 99 | height: 100%; 100 | vertical-align: middle 101 | } 102 | .jazz .left-column { 103 | padding-right: 10px 104 | } 105 | .jazz .right-column { 106 | padding-left: 10px 107 | } 108 | .jazz .right-column.left-align { 109 | width: 100% 110 | } 111 | .jazz .right-column.left-align .para { 112 | color: rgba(128,128,128,1); 113 | font-size: 1.6em 114 | } 115 | .jazz .two-columns .inline-graphic { 116 | margin: 0 auto; 117 | text-align: center 118 | } 119 | .jazz .two-columns .para { 120 | clear: both; 121 | font-size: 1.4em 122 | } 123 | .jazz #ios_header { 124 | /* background-color: rgba(65,65,65,1); */ 125 | box-shadow: 0 1px 1px rgba(0,0,0,.07); 126 | color: rgba(255,255,255,1); 127 | height: 25px; 128 | letter-spacing: .05em; 129 | position: fixed; 130 | top: 0; 131 | width: 100%; 132 | z-index: 4 133 | } 134 | .jazz .header-text { 135 | font-size: 1.1em; 136 | margin: 0 auto; 137 | padding-top: 6px; 138 | vertical-align: middle; 139 | float: left 140 | } 141 | .jazz .header-text a { 142 | color: rgba(255,255,255,1); 143 | text-decoration: none 144 | } 145 | .jazz #apple_logo { 146 | padding-right: 8px; 147 | vertical-align: -2px 148 | } 149 | .jazz #wwdr { 150 | float: right; 151 | padding-top: 4px; 152 | font-size: 1.1em; 153 | vertical-align: middle; 154 | margin: 0 auto 155 | } 156 | .jazz #wwdr a { 157 | color: rgba(255,255,255,1); 158 | text-decoration: none 159 | } 160 | .jazz #valence { 161 | /* background-color: rgba(242,242,242,1); */ 162 | display: block; 163 | height: 60px; 164 | padding-top: 10px; 165 | position: fixed; 166 | top: 0; 167 | width: 100%; 168 | z-index: 3 169 | } 170 | .jazz #hierarchial_navigation { 171 | float: left; 172 | font-size: 1.4em; 173 | margin-top: 29px; 174 | vertical-align: middle 175 | } 176 | .jazz #carat { 177 | margin: 0 10px 178 | } 179 | .jazz #design_resources_link { 180 | color: rgba(0,136,204,1); 181 | text-decoration: none 182 | } 183 | .jazz #book_title { 184 | color: rgba(0,0,0,1); 185 | font-size: 1em 186 | } 187 | .jazz .download-text { 188 | color: rgba(0,136,204,1); 189 | float: right; 190 | font-size: 1.1em; 191 | margin-right: 20px; 192 | margin-top: 32px; 193 | text-decoration: none 194 | } 195 | .jazz input[type=search] { 196 | background-size: 14px 14px; 197 | background-image: url(../Images/magnify_2x.png); 198 | background-position: 3% 50%; 199 | background-repeat: no-repeat; 200 | border: 1px solid rgba(238,238,238,1); 201 | box-shadow: 0 0 1px rgba(0,0,0,.07); 202 | -webkit-appearance: none; 203 | float: right; 204 | font-family: Helvetica,Arial,sans-serif; 205 | font-size: 1.1em; 206 | height: 30px; 207 | margin-right: -2px; 208 | margin-top: 23px; 209 | padding-left: 18px; 210 | vertical-align: middle; 211 | width: 177px 212 | } 213 | .jazz #shortstack { 214 | display: none 215 | } 216 | .jazz .para { 217 | color: rgba(65,65,65,1); 218 | font-size: 1.4em; 219 | line-height: 145%; 220 | margin-bottom: 5px; 221 | 222 | } 223 | .jazz .chapter-name { 224 | color: rgba(0,0,0,1); 225 | display: block; 226 | font-family: Helvetica; 227 | font-size: 2.8em; 228 | font-weight: 100; 229 | margin-bottom: 0; 230 | padding: 15px 25px; 231 | width: 63% 232 | } 233 | .jazz #mini_toc p { 234 | font-size: 1.4em 235 | } 236 | .jazz #mini_toc .list-bullet a { 237 | color: rgba(0,136,204,1); 238 | list-style-type: none; 239 | list-style-position: outside; 240 | margin-left: 0; 241 | padding-left: 0; 242 | text-decoration: none 243 | } 244 | .jazz #mini_toc ul.list-bullet { 245 | list-style-type: none; 246 | margin-bottom: 0; 247 | margin-left: 0; 248 | margin-top: 15px; 249 | overflow: hidden; 250 | padding-left: 0; 251 | width: 167px; 252 | display: none 253 | } 254 | .jazz #mini_toc.open ul.list-bullet { 255 | display: block 256 | } 257 | .jazz #mini_toc ul.list-bullet li.item { 258 | padding-left: 0; 259 | display: block 260 | } 261 | .jazz #mini_toc ul.list-bullet li.item:before { 262 | content: none 263 | } 264 | .jazz #mini_toc ul.list-bullet li.item .para { 265 | color: rgba(0,136,204,1); 266 | font-size: 1.4em; 267 | line-height: 135%; 268 | padding-bottom: 22px; 269 | text-decoration: none 270 | } 271 | .jazz .chapter a { 272 | color: rgba(0,136,204,1); 273 | text-decoration: none 274 | } 275 | .jazz h3.section-name:before { 276 | display: block; 277 | content: " "; 278 | margin-top: -85px; 279 | height: 85px; 280 | visibility: hidden 281 | } 282 | .jazz .section-name { 283 | color: rgba(128,128,128,1); 284 | display: block; 285 | font-family: Helvetica; 286 | font-size: 2.2em; 287 | font-weight: 100; 288 | margin-bottom: 15px; 289 | margin-top: 20px; 290 | } 291 | .jazz .section .section .section-name { 292 | color: rgba(0,0,0,1); 293 | font-size: 1.8em; 294 | letter-spacing: 0; 295 | padding-top: 20px 296 | } 297 | .jazz .section .section .section .section-name { 298 | font-size: 1.6em; 299 | padding-top: 0 300 | } 301 | .jazz .title-three { 302 | color: rgba(0,0,0,1); 303 | font-size: 2em; 304 | font-weight: 400; 305 | margin-bottom: 10px 306 | } 307 | .jazz .inline-head { 308 | } 309 | .jazz .code-voice { 310 | color: rgba(128,128,128,1); 311 | font-family: Menlo,monospace; 312 | font-size: .9em; 313 | word-wrap: break-word 314 | } 315 | .jazz .copyright { 316 | clear: both; 317 | color: rgba(160,160,160,1); 318 | float: none; 319 | margin: 70px 25px 10px 0 320 | } 321 | .jazz .link { 322 | color: rgba(0,136,204,1); 323 | text-decoration: none 324 | } 325 | .jazz .u-book { 326 | } 327 | .jazz .pediaLink { 328 | } 329 | .jazz .x-name-no-link { 330 | } 331 | .jazz .u-api { 332 | } 333 | .jazz ul.list-bullet { 334 | list-style: none; 335 | margin-bottom: 12px; 336 | margin-left: 24px; 337 | padding-left: 0 338 | } 339 | .jazz ul.list-bullet li.item { 340 | list-style-type: none; 341 | list-style-image: none; 342 | padding-left: 1.3em; 343 | position: relative 344 | } 345 | .jazz .aside ul.list-bullet li.item { 346 | padding-left: 1.1em 347 | } 348 | .jazz ul.list-bullet li.item:before { 349 | color: rgba(65,65,65,1); 350 | content: "\02022"; 351 | font-size: 1.5em; 352 | left: 0; 353 | padding-top: 2px; 354 | position: absolute 355 | } 356 | .jazz .aside ul.list-bullet li.item:before { 357 | font-size: 1.2em; 358 | margin-top: -2px 359 | } 360 | .jazz .list-number,.jazz .list-simple,.jazz .list-check { 361 | margin-bottom: 12px; 362 | margin-left: 20px; 363 | padding-left: 20px 364 | } 365 | .jazz .list-number { 366 | color: rgba(65,65,65,1); 367 | font-size: 1.4em 368 | } 369 | .jazz .aside .list-number { 370 | font-size: 1em 371 | } 372 | .jazz ol.list-number li.item ol.list-number { 373 | font-size: 1em 374 | } 375 | .jazz .list-number .item p { 376 | font-size: 1em 377 | } 378 | .jazz .list-simple { 379 | list-style-type: none 380 | } 381 | .jazz .list-check { 382 | list-style: url(../Images/check.png) outside none 383 | } 384 | .jazz .item p { 385 | margin: 0; 386 | padding-bottom: 6px 387 | } 388 | .jazz .book-parts { 389 | /* background-color: rgba(249,249,249,1); */ 390 | border: 1px solid rgba(238,238,238,1); 391 | bottom: 0; 392 | box-shadow: 0 0 1px rgba(0,0,0,.07); 393 | display: block; 394 | overflow: auto; 395 | -webkit-overflow-scrolling: touch; 396 | position: fixed; 397 | top: 70px; 398 | width: 230px 399 | } 400 | .jazz .nav-parts { 401 | color: rgba(128,128,128,1); 402 | font-weight: 100; 403 | line-height: 140%; 404 | list-style-type: none; 405 | margin: 0; 406 | -webkit-padding-start: 0 407 | } 408 | .jazz .part-name { 409 | border-bottom: 1px solid rgba(238,238,238,1); 410 | font-family: Helvetica; 411 | font-size: 1.6em; 412 | line-height: 150%; 413 | list-style-type: none; 414 | margin: 0; 415 | padding: 15px 30px 15px 20px; 416 | cursor: pointer 417 | } 418 | .jazz .nav-chapters { 419 | font-weight: 400; 420 | line-height: 110%; 421 | list-style-position: outside; 422 | list-style-type: none; 423 | margin: 0; 424 | padding: 0; 425 | height: 0; 426 | overflow: hidden; 427 | -webkit-transition: height .3s ease-in-out; 428 | -moz-transition: height .3s ease-in-out; 429 | -o-transition: height .3s ease-in-out; 430 | -ms-transition: height .3s ease-in-out; 431 | transition: height .3s ease-in-out 432 | } 433 | .jazz .nav-chapter { 434 | font-size: .8em; 435 | list-style-position: outside; 436 | list-style-type: none; 437 | margin: 0; 438 | padding: 0 0 8px 439 | } 440 | .jazz .nav-chapters .nav-chapter { 441 | margin-left: 0 442 | } 443 | .jazz .nav-chapter .nav-chapter-active { 444 | color: rgba(0,0,0,1); 445 | font-weight: 700; 446 | text-decoration: none 447 | } 448 | .jazz .book-parts a { 449 | color: rgba(128,128,128,1); 450 | display: block; 451 | margin-left: 15px; 452 | text-decoration: none 453 | } 454 | .jazz .aside-title { 455 | color: rgba(128,128,128,1); 456 | font-size: .6em; 457 | letter-spacing: 2px; 458 | margin-bottom: 8px; 459 | text-transform: uppercase 460 | } 461 | .jazz .tip,.jazz .warning,.jazz .important,.jazz .note { 462 | background-color: rgba(249,249,249,1); 463 | border-left: 5px solid rgba(238,238,238,1); 464 | color: rgba(0,0,0,1); 465 | font-size: 1.2em; 466 | margin: 25px 45px 35px 35px; 467 | padding: 15px 15px 7px; 468 | 469 | } 470 | .jazz .note .para,.jazz .important .para,.jazz .tip .para,.jazz .warning .para { 471 | font-size: 1em; 472 | margin-bottom: 8px 473 | } 474 | .jazz .note { 475 | border-left: 5px solid rgba(238,238,238,1) 476 | } 477 | .jazz .important { 478 | border-left: 5px solid rgba(128,128,128,1) 479 | } 480 | .jazz .tip { 481 | border-left: 5px solid rgba(238,238,238,1) 482 | } 483 | .jazz .warning { 484 | border-left: 5px solid rgba(247,235,97,1) 485 | } 486 | .jazz .rec-container { 487 | margin: 40px auto; 488 | text-align: center; 489 | width: 95% 490 | } 491 | .jazz .rec-container .blurb { 492 | text-align: center 493 | } 494 | .jazz .rec-container .blurb .para:nth-child(1) { 495 | color: rgba(128,128,128,1); 496 | font-size: 2em; 497 | font-weight: 100; 498 | line-height: 120%; 499 | margin: 0 auto 20px; 500 | width: 460px 501 | } 502 | .jazz .rec-container .blurb .para { 503 | margin-bottom: 20px 504 | } 505 | .jazz .rec-container .left-container,.jazz .rec-container .right-container { 506 | display: table-cell; 507 | margin-top: 20px; 508 | width: 325px 509 | } 510 | .jazz .rec-container .left-container { 511 | padding-right: 10px 512 | } 513 | .jazz .rec-container .right-container { 514 | padding-left: 10px 515 | } 516 | .jazz .rec-container .container-label { 517 | font-size: 1.5em; 518 | margin-bottom: 10px 519 | } 520 | .jazz .rec-container .do { 521 | color: rgba(17,183,40,1) 522 | } 523 | .jazz .rec-container .do-not { 524 | color: rgba(208,50,54,1) 525 | } 526 | .jazz .rec-container .recommended { 527 | color: rgba(40,103,206,1) 528 | } 529 | .jazz .rec-container .not-recommended { 530 | color: rgba(255,133,0,1) 531 | } 532 | .jazz .rec-container .inline-graphic { 533 | margin: 10px auto; 534 | max-width: 100% 535 | } 536 | .jazz .code-listing { 537 | background-clip: padding-box; 538 | margin: 20px 0; 539 | text-align: left 540 | } 541 | .jazz .item .code-listing { 542 | padding: 0; 543 | margin: 0 0 15px 544 | } 545 | .jazz .code-listing .caption { 546 | caption-side: top; 547 | display: block; 548 | font-size: 1.1em; 549 | text-align: left; 550 | margin-bottom: 16px 551 | } 552 | .jazz>.content-wrapper>.chapter>.section>.list-number>.item>.code-listing { 553 | padding-top: 0; 554 | padding-bottom: 5px; 555 | margin-top: 0; 556 | margin-bottom: 0 557 | } 558 | .jazz .code-sample { 559 | /* background-color: rgba(249,249,249,1); */ 560 | display: block; 561 | font-size: 1.4em; 562 | margin-left: 20px 563 | } 564 | .jazz ol .code-sample { 565 | font-size: 1em 566 | } 567 | .jazz .code-lines { 568 | /* background-color: rgba(255,255,255,1); */ 569 | counter-reset: li; 570 | line-height: 1.6em; 571 | list-style: none; 572 | margin: 0 0 0 20px; 573 | padding: 0 574 | } 575 | .jazz pre { 576 | white-space: pre-wrap 577 | } 578 | .jazz .code-lines li:before { 579 | color: rgba(128,128,128,1); 580 | content: counter(li); 581 | counter-increment: li; 582 | font-family: Menlo,monospace; 583 | margin-right: 10px; 584 | -webkit-user-select: none 585 | } 586 | .jazz .code-lines li { 587 | padding-left: 10px; 588 | text-indent: -24px; 589 | white-space: pre 590 | } 591 | .jazz .code-lines li:nth-child(n+10) { 592 | text-indent: -28px 593 | } 594 | .jazz .code-lines li:nth-child(n+10):before { 595 | margin-right: 6px 596 | } 597 | .jazz #next_previous { 598 | bottom: 0; 599 | color: rgba(0,136,204,1); 600 | margin: 0 25px; 601 | position: absolute; 602 | width: 684px 603 | } 604 | .jazz .next-link a,.jazz .previous-link a { 605 | background-size: 6px 12px; 606 | background-repeat: no-repeat; 607 | font-size: 1.4em; 608 | margin-bottom: 50px; 609 | margin-top: 50px; 610 | width: 45% 611 | } 612 | .jazz .next-link a { 613 | background-image: url(../Images/right_arrow_2x.png); 614 | background-position: 100% 50%; 615 | float: right; 616 | padding-right: 16px; 617 | text-align: right 618 | } 619 | .jazz .previous-link a { 620 | background-image: url(../Images/left_arrow_2x.png); 621 | background-position: 0 50%; 622 | float: left; 623 | padding-left: 16px; 624 | text-align: left 625 | } 626 | .jazz #footer { 627 | bottom: 0; 628 | position: fixed; 629 | width: 100% 630 | } 631 | .jazz #leave_feedback { 632 | display: none 633 | } 634 | .jazz #footer #leave_feedback { 635 | /* background-color: rgba(160,160,160,1); */ 636 | box-shadow: 0 0 1px rgba(0,0,0,.07); 637 | color: rgba(255,255,255,1); 638 | font-size: 1.1em; 639 | margin-left: 912px; 640 | padding: 5px 10px; 641 | position: absolute; 642 | text-align: center; 643 | right: auto; 644 | z-index: 3; 645 | display: block 646 | } 647 | .jazz #modal { 648 | font-family: Helvetica,Arial,sans-serif; 649 | -webkit-border-radius: 0; 650 | width: 600px 651 | } 652 | .jazz #modal #feedback h2 { 653 | font-size: 1.5em; 654 | font-weight: 100; 655 | margin-bottom: 10px 656 | } 657 | .jazz #modal #feedback #star_group,.jazz #modal #feedback #improve { 658 | top: 0 659 | } 660 | .jazz #modal #feedback #star_group label,.jazz #modal #feedback .right-leaf,.jazz #modal #feedback .checkboxes label { 661 | color: rgba(0,0,0,1) 662 | } 663 | .jazz #modal #feedback #star_group label { 664 | width: 200px 665 | } 666 | .jazz #modal #feedback .right-leaf { 667 | width: 297px 668 | } 669 | .jazz #modal #feedback #comment,.jazz #modal #feedback #email { 670 | border: 1px solid rgba(128,128,128,1); 671 | font-family: Helvetica,Arial,sans-serif 672 | } 673 | .jazz #modal #feedback #comment { 674 | margin: 26px 0 12px 675 | } 676 | .jazz #modal #feedback #email { 677 | height: 13px 678 | } 679 | .jazz #modal #feedback #submit { 680 | /* background-color: rgba(160,160,160,1); */ 681 | background-image: none; 682 | color: rgba(255,255,255,1); 683 | font-family: Helvetica,Arial,sans-serif; 684 | height: 27px; 685 | margin: 0 0 0 6px; 686 | -webkit-border-radius: 0 687 | } 688 | .jazz #modal #feedback #legal { 689 | margin-top: 22px 690 | } 691 | .jazz .caption { 692 | caption-side: top; 693 | display: block; 694 | font-size: 1.1em; 695 | text-align: left; 696 | margin-bottom: 8px 697 | } 698 | .jazz .figure { 699 | margin: 40px auto; 700 | text-align: center 701 | } 702 | .jazz .inline-graphic { 703 | margin: 20px auto; 704 | text-align: center; 705 | display: block 706 | } 707 | .jazz tr td .para .inline-graphic { 708 | margin: 10px 0 709 | } 710 | .jazz .list-bullet .item .para .inline-graphic,.jazz .list-number .item .para .inline-graphic { 711 | margin: 0 4px; 712 | display: inline; 713 | vertical-align: middle 714 | } 715 | .jazz .tableholder { 716 | } 717 | .jazz .tablecaption { 718 | caption-side: top; 719 | font-size: 1.1em; 720 | text-align: left; 721 | margin-bottom: 8px 722 | } 723 | .jazz ol .tablecaption { 724 | font-size: .78em 725 | } 726 | .jazz .caption-number { 727 | padding-right: .4em 728 | } 729 | .jazz .graybox { 730 | border: 1px solid rgba(238,238,238,1); 731 | border-collapse: collapse; 732 | border-spacing: 0; 733 | empty-cells: hide; 734 | margin: 20px 0 36px; 735 | text-align: left; 736 | width: 100% 737 | } 738 | .jazz .graybox p { 739 | margin: 0 740 | } 741 | .jazz .TableHeading_TableRow_TableCell { 742 | padding: 5px 10px; 743 | border-left: 1px solid rgba(238,238,238,1); 744 | /* background-color: rgba(249,249,249,1); */ 745 | font-weight: 400; 746 | white-space: normal 747 | } 748 | .jazz td { 749 | border: 1px solid rgba(238,238,238,1); 750 | padding: 5px 25px 5px 10px; 751 | margin: 0; 752 | vertical-align: middle; 753 | max-width: 260px 754 | } 755 | .jazz .row-heading { 756 | /* background-color: rgba(249,249,249,1) */ 757 | } 758 | .video-container { 759 | position: relative 760 | } 761 | .video-container video { 762 | outline: 0; 763 | -webkit-transition: -webkit-filter .3s ease; 764 | -moz-transition: -moz-filter .3s ease; 765 | -o-transition: -o-filter .3s ease; 766 | cursor: pointer 767 | } 768 | .playButtonOverlay { 769 | opacity: 1; 770 | display: block; 771 | -webkit-transition: opacity .3s ease; 772 | position: absolute; 773 | background: url(../Images/playbutton.svg) no-repeat; 774 | background-size: cover; 775 | left: 312px; 776 | width: 60px; 777 | height: 60px; 778 | pointer-events: none; 779 | top: 40% 780 | } 781 | .playButtonOverlay.hide { 782 | opacity: 0 783 | } 784 | .jazz #big_button.active { 785 | position: fixed; 786 | top: 0; 787 | bottom: 0; 788 | left: 0; 789 | right: 0; 790 | z-index: 1; 791 | /* background-color: transparent */ 792 | } 793 | #conceptual_flow_with_tasks #carat { 794 | margin: 0 10px 795 | } 796 | #conceptual_flow_with_tasks #design_resources_link { 797 | color: rgba(0,136,204,1); 798 | text-decoration: none 799 | } 800 | #conceptual_flow_with_tasks .list-check { 801 | list-style: url(../Images/check.png) outside none 802 | } 803 | #conceptual_flow_with_tasks .nav-part-active { 804 | /* background-color: rgba(255,255,255,1); */ 805 | color: rgba(0,0,0,1); 806 | cursor: default 807 | } 808 | #conceptual_flow_with_tasks .nav-chapters { 809 | font-weight: 400; 810 | line-height: 110%; 811 | list-style-position: outside; 812 | list-style-type: none; 813 | margin: 0; 814 | padding: 0; 815 | height: 0; 816 | overflow: hidden; 817 | -webkit-transition: height .3s ease-in-out; 818 | -moz-transition: height .3s ease-in-out; 819 | -o-transition: height .3s ease-in-out; 820 | -ms-transition: height .3s ease-in-out; 821 | transition: height .3s ease-in-out 822 | } 823 | #conceptual_flow_with_tasks .nav-part-active .nav-chapters { 824 | margin: 15px 0 0 825 | } 826 | #conceptual_flow_with_tasks .nav-chapter { 827 | font-size: .8em; 828 | list-style-position: outside; 829 | list-style-type: none; 830 | margin: 0; 831 | padding: 0 0 8px 832 | } 833 | #conceptual_flow_with_tasks .nav-chapters .nav-chapter { 834 | margin-left: 0 835 | } 836 | #conceptual_flow_with_tasks .nav-chapter .nav-chapter-active { 837 | color: rgba(0,0,0,1); 838 | font-weight: 700; 839 | text-decoration: none 840 | } 841 | #conceptual_flow_with_tasks .book-parts a { 842 | color: rgba(128,128,128,1); 843 | display: block; 844 | margin-left: 15px; 845 | text-decoration: none 846 | } 847 | #conceptual_flow_with_tasks .rec-container { 848 | margin: 40px auto; 849 | text-align: center; 850 | width: 95% 851 | } 852 | #conceptual_flow_with_tasks .rec-container .blurb { 853 | text-align: center 854 | } 855 | #conceptual_flow_with_tasks .rec-container .blurb .para:nth-child(1) { 856 | color: rgba(128,128,128,1); 857 | font-size: 2em; 858 | font-weight: 100; 859 | line-height: 120%; 860 | margin: 0 auto 20px; 861 | width: 460px 862 | } 863 | #conceptual_flow_with_tasks .rec-container .blurb .para { 864 | margin-bottom: 20px 865 | } 866 | #conceptual_flow_with_tasks .rec-container .left-container,#conceptual_flow_with_tasks .rec-container .right-container { 867 | display: table-cell; 868 | margin-top: 20px; 869 | width: 325px 870 | } 871 | #conceptual_flow_with_tasks .rec-container .left-container { 872 | padding-right: 10px 873 | } 874 | #conceptual_flow_with_tasks .rec-container .right-container { 875 | padding-left: 10px 876 | } 877 | #conceptual_flow_with_tasks .rec-container .container-label { 878 | font-size: 1.5em; 879 | margin-bottom: 10px 880 | } 881 | #conceptual_flow_with_tasks .rec-container .do { 882 | color: rgba(17,183,40,1) 883 | } 884 | #conceptual_flow_with_tasks .rec-container .do-not { 885 | color: rgba(208,50,54,1) 886 | } 887 | #conceptual_flow_with_tasks .rec-container .recommended { 888 | color: rgba(40,103,206,1) 889 | } 890 | #conceptual_flow_with_tasks .rec-container .not-recommended { 891 | color: rgba(255,133,0,1) 892 | } 893 | #conceptual_flow_with_tasks .rec-container .inline-graphic { 894 | margin: 10px auto; 895 | max-width: 100% 896 | } 897 | #roadmap.jazz .nav-chapters { 898 | font-weight: 400; 899 | line-height: 110%; 900 | list-style-position: outside; 901 | list-style-type: none; 902 | margin: 0; 903 | padding: 8px 0 0; 904 | height: 100%; 905 | width: 200px 906 | } 907 | #roadmap .nav-part-active { 908 | /* background-color: rgba(255,255,255,1); */ 909 | color: rgba(0,0,0,1); 910 | cursor: default 911 | } 912 | #roadmap.jazz .conceptual-with-tasks:before { 913 | border: 2px solid rgba(128,128,128,1); 914 | border-radius: 50%; 915 | content: ""; 916 | display: block; 917 | float: left; 918 | height: 10px; 919 | margin: 2px 8px 0 0; 920 | width: 10px 921 | } 922 | #roadmap.jazz .tutorial:before { 923 | border: 2px solid rgba(128,128,128,1); 924 | content: ""; 925 | display: block; 926 | float: left; 927 | height: 10px; 928 | margin: 2px 8px 0 0; 929 | width: 10px 930 | } 931 | #roadmap.jazz .nav-visited-chapter.conceptual-with-tasks:before { 932 | /* background-color: rgba(128,128,128,1) */ 933 | } 934 | #roadmap.jazz .nav-visited-chapter.tutorial:before { 935 | /* background-color: rgba(128,128,128,1) */ 936 | } 937 | #roadmap.jazz .nav-current-chapter.conceptual-with-tasks:before { 938 | /* background-color: rgba(0,0,0,1); */ 939 | border-color: rgba(0,0,0,1) 940 | } 941 | #roadmap.jazz .nav-current-chapter.tutorial:before { 942 | /* background-color: rgba(0,0,0,1); */ 943 | border-color: rgba(0,0,0,1) 944 | } 945 | .jazz .book-parts a { 946 | margin-left: 24px 947 | } 948 | #roadmap .nav-chapters li:first-child .pipe { 949 | height: 9px; 950 | top: auto 951 | } 952 | #roadmap .nav-chapters .pipe { 953 | /* background-color: gray; */ 954 | height: 9px; 955 | padding-top: 2px; 956 | position: absolute; 957 | right: auto; 958 | bottom: auto; 959 | left: 26px; 960 | width: 2px; 961 | margin-top: -1px 962 | } 963 | #roadmap .nav-chapters li:last-child .pipe { 964 | height: 0; 965 | display: none 966 | } 967 | #roadmap.jazz .part-name { 968 | cursor: default 969 | } 970 | /*! Copyright © 2012 Apple Inc. All rights reserved. */#release_notes .chapter-name { 971 | width: auto 972 | } 973 | #release_notes .nav-part-active { 974 | /* background-color: rgba(255,255,255,1); */ 975 | color: rgba(0,0,0,1); 976 | cursor: default 977 | } 978 | #release_notes #contents { 979 | width: 980px; 980 | margin-left: 0 981 | } 982 | #release_notes .section { 983 | width: 734px; 984 | margin: 0 auto 985 | } 986 | #release_notes #mini_toc { 987 | left: 434px 988 | } 989 | /*! Copyright © 2010 Apple Inc. All rights reserved. */@media only print {.jazz #valence { 990 | display: none 991 | } 992 | .jazz #ios_header { 993 | display: none 994 | } 995 | .jazz #footer #leave_feedback { 996 | display: none 997 | } 998 | .jazz #mini_toc { 999 | display: none 1000 | } 1001 | .jazz .chapter { 1002 | position: relative; 1003 | margin: 0 auto; 1004 | top: 0; 1005 | border: 0; 1006 | box-shadow: none; 1007 | padding-bottom: 0 1008 | } 1009 | .jazz .book-parts { 1010 | display: none 1011 | } 1012 | body.jazz,.jazz .content-wrapper { 1013 | /* background-color: rgba(255,255,255,1) */ 1014 | } 1015 | .jazz a[name] { 1016 | margin: auto; 1017 | padding-top: 0; 1018 | display: static 1019 | } 1020 | .jazz .next-link a { 1021 | display: none 1022 | } 1023 | .jazz .previous-link a { 1024 | display: none 1025 | } 1026 | .jazz .rec-container .left-container { 1027 | padding-right: 0; 1028 | float: left 1029 | } 1030 | .jazz .rec-container .right-container { 1031 | float: right; 1032 | padding-left: 0 1033 | } 1034 | .jazz .rec-container .left-container,.jazz .rec-container .right-container { 1035 | display: static; 1036 | width: auto 1037 | } 1038 | .jazz .para { 1039 | clear: both 1040 | } 1041 | .jazz .copyright { 1042 | margin: auto 1043 | } 1044 | 1045 | } 1046 | @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:portrait) {body.jazz { 1047 | font-size: 75% 1048 | } 1049 | .jazz .content-wrapper { 1050 | width: 100% 1051 | } 1052 | .jazz #ios_header .content-wrapper { 1053 | /* background-color: rgba(242,242,242,1); */ 1054 | margin: 0 auto; 1055 | width: 96% 1056 | } 1057 | .jazz #valence .content-wrapper { 1058 | /* background-color: rgba(242,242,242,1); */ 1059 | margin: 0 auto; 1060 | width: 96% 1061 | } 1062 | .jazz #ios_header { 1063 | height: 30px; 1064 | letter-spacing: 0; 1065 | margin-bottom: 0; 1066 | position: fixed; 1067 | top: 0; 1068 | width: 100%; 1069 | z-index: 3 1070 | } 1071 | .jazz #valence { 1072 | height: 70px; 1073 | top: 30px; 1074 | position: fixed; 1075 | width: 100%; 1076 | z-index: 2 1077 | } 1078 | .jazz #hierarchial_navigation { 1079 | margin-top: 2px 1080 | } 1081 | .jazz .download-text { 1082 | background-image: url(../Images/download_2x.png); 1083 | background-size: 30px 30px; 1084 | background-position: 0; 1085 | color: transparent; 1086 | height: 30px; 1087 | margin: 0; 1088 | width: 30px; 1089 | overflow: hidden 1090 | } 1091 | .jazz #search { 1092 | background-image: url(../Images/search_2x.png); 1093 | background-size: 30px 30px; 1094 | background-position: 0; 1095 | float: right; 1096 | height: 30px; 1097 | margin: 0 0 0 10px; 1098 | padding: 0; 1099 | width: 30px 1100 | } 1101 | .jazz #search.enabled { 1102 | } 1103 | .jazz input[type=search] { 1104 | display: none 1105 | } 1106 | .jazz input[type=search].enabled { 1107 | background-image: none; 1108 | display: block; 1109 | height: 30px; 1110 | margin-top: 34px; 1111 | padding-left: 8px; 1112 | -webkit-border-radius: 0; 1113 | width: 248px 1114 | } 1115 | .jazz #shortstack { 1116 | display: block; 1117 | float: none; 1118 | height: 30px; 1119 | margin-left: -12px; 1120 | margin-top: 18px; 1121 | padding: 13px 10px; 1122 | position: absolute; 1123 | width: 30px 1124 | } 1125 | .jazz .chapter { 1126 | bottom: 0; 1127 | left: 0; 1128 | margin-left: 0; 1129 | padding-bottom: 0; 1130 | position: relative; 1131 | right: 0; 1132 | top: 110px; 1133 | z-index: -2 1134 | } 1135 | .jazz .part-name { 1136 | padding: 20px 20px 20px 25px 1137 | } 1138 | .jazz .book-parts { 1139 | box-shadow: 0 0 1px rgba(0,0,0,.07); 1140 | display: none; 1141 | top: 110px; 1142 | position: fixed; 1143 | left: 0; 1144 | -webkit-overflow-scrolling: touch; 1145 | width: 295px; 1146 | z-index: -1 1147 | } 1148 | .jazz .nav-parts { 1149 | overflow: auto 1150 | } 1151 | .jazz .book-parts.open { 1152 | box-shadow: 7px 0 5px rgba(0,0,0,.05); 1153 | display: block; 1154 | z-index: 5 1155 | } 1156 | .jazz #big_button { 1157 | } 1158 | .jazz #big_button.active { 1159 | position: fixed; 1160 | top: 0; 1161 | bottom: 0; 1162 | left: 0; 1163 | right: 0; 1164 | z-index: 4; 1165 | /* background-color: transparent */ 1166 | } 1167 | .jazz .nav-chapter { 1168 | padding: 0 0 16px 1169 | } 1170 | .jazz #mini_toc { 1171 | background-position: 90% 14px; 1172 | margin-top: 2px; 1173 | padding: 10px 10px 5px 15px; 1174 | width: 220px; 1175 | top: 125px 1176 | } 1177 | .jazz #mini_toc ul.list-bullet { 1178 | margin-top: 15px; 1179 | padding-bottom: 0; 1180 | width: 200px 1181 | } 1182 | .jazz .section { 1183 | padding: 20px 13px 1184 | } 1185 | .jazz .chapter { 1186 | margin: 0 auto; 1187 | width: 100%; 1188 | z-index: 0; 1189 | overflow: visible 1190 | } 1191 | .jazz .chapter-name { 1192 | padding: 15px 20px 15px 13px 1193 | } 1194 | .jazz .figure img { 1195 | max-width: 600px 1196 | } 1197 | .jazz .two-columns .inline-graphic { 1198 | max-width: 100% 1199 | } 1200 | .jazz .intro ul.list-bullet { 1201 | width: 100% 1202 | } 1203 | .jazz .intro ul.list-bullet li.item { 1204 | width: 40%; 1205 | padding-right: 80px 1206 | } 1207 | .jazz #next_previous { 1208 | margin: 0 13px; 1209 | position: static; 1210 | width: 95% 1211 | } 1212 | .jazz .copyright { 1213 | margin: 70px 13px 15px 0; 1214 | position: relative; 1215 | bottom: 0 1216 | } 1217 | .jazz #footer { 1218 | position: relative 1219 | } 1220 | .jazz #footer #leave_feedback { 1221 | height: 17px; 1222 | right: 0; 1223 | position: fixed 1224 | } 1225 | .jazz #modal #feedback #comment { 1226 | -webkit-border-radius: 0; 1227 | height: 111px; 1228 | margin: 16px 0 12px 1229 | } 1230 | .jazz #feedback .asterisk#a1.ipad,.asterisk#modal_a1.ipad { 1231 | left: 257px 1232 | } 1233 | .jazz #feedback .asterisk#a2.ipad,.asterisk#modal_a2.ipad { 1234 | top: 178px 1235 | } 1236 | .jazz .fineprint.invalid,#modal_feedback .fineprint.invalid { 1237 | bottom: 53px 1238 | } 1239 | .jazz #modal #feedback #email { 1240 | -webkit-border-radius: 0 1241 | } 1242 | .jazz #modal #feedback input[type=button] { 1243 | /* background-color: rgba(160,160,160,1); */ 1244 | background-image: none; 1245 | color: rgba(255,255,255,1); 1246 | font-family: Helvetica,Arial,sans-serif; 1247 | margin: 10px 0 0; 1248 | -webkit-border-radius: 0; 1249 | -webkit-appearance: none; 1250 | -moz-appearance: none; 1251 | appearance: none 1252 | } 1253 | 1254 | } 1255 | @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) {body.jazz { 1256 | } 1257 | .jazz .content-wrapper { 1258 | /* background-color: rgba(242,242,242,1); */ 1259 | margin: 0 auto; 1260 | width: 96% 1261 | } 1262 | .jazz #ios_header { 1263 | letter-spacing: 0 1264 | } 1265 | .jazz #valence { 1266 | top: 25px; 1267 | height: 35px 1268 | } 1269 | .jazz #hierarchial_navigation { 1270 | margin-top: 4px 1271 | } 1272 | .jazz .download-text { 1273 | margin-top: 6px 1274 | } 1275 | .jazz input[type=search] { 1276 | margin-right: 0; 1277 | margin-top: 0; 1278 | padding-left: 25px; 1279 | -webkit-border-radius: 0 1280 | } 1281 | .jazz .book-parts { 1282 | -webkit-overflow-scrolling: touch 1283 | } 1284 | .jazz .part-name { 1285 | padding: 15px 20px 1286 | } 1287 | .jazz .chapter { 1288 | bottom: 0; 1289 | left: 246px; 1290 | margin-left: 20px; 1291 | padding-bottom: 0; 1292 | overflow: visible 1293 | } 1294 | .jazz .section { 1295 | background: rgba(255,255,255,1) 1296 | } 1297 | .jazz #next_previous { 1298 | position: static; 1299 | background: rgba(255,255,255,1); 1300 | margin: 0; 1301 | padding: 0 25px 1302 | } 1303 | .jazz #dpf_leave_feedback { 1304 | height: 16px; 1305 | margin-left: 797px 1306 | } 1307 | .jazz .two-columns .inline-graphic { 1308 | max-width: 100% 1309 | } 1310 | .jazz #footer { 1311 | position: relative 1312 | } 1313 | .jazz .copyright { 1314 | margin: 0; 1315 | position: relative; 1316 | bottom: 8px 1317 | } 1318 | .jazz #footer #leave_feedback { 1319 | position: fixed 1320 | } 1321 | .jazz #modal #feedback #comment { 1322 | -webkit-border-radius: 0; 1323 | height: 106px 1324 | } 1325 | .jazz #feedback .asterisk#a1.ipad,.asterisk#modal_a1.ipad { 1326 | left: 257px 1327 | } 1328 | .jazz .fineprint.invalid,#modal_feedback .fineprint.invalid { 1329 | bottom: 48px 1330 | } 1331 | .jazz #modal #feedback #email { 1332 | -webkit-border-radius: 0 1333 | } 1334 | .jazz #modal #feedback input[type=button] { 1335 | /* background-color: rgba(160,160,160,1); */ 1336 | background-image: none; 1337 | color: rgba(255,255,255,1); 1338 | font-family: Helvetica,Arial,sans-serif; 1339 | margin: 10px 0 0; 1340 | -webkit-border-radius: 0; 1341 | -webkit-appearance: none; 1342 | -moz-appearance: none; 1343 | appearance: none 1344 | } 1345 | 1346 | } 1347 | @media only screen and (min-device-width:320px) and (max-device-width:480px) and (orientation:portrait) {html { 1348 | -webkit-text-size-adjust: none 1349 | } 1350 | body.jazz { 1351 | /* background-color: rgba(255,255,255,1); */ 1352 | font-size: 70%; 1353 | overflow-x: hidden 1354 | } 1355 | .jazz #ios_header { 1356 | display: block; 1357 | height: 30px; 1358 | position: static; 1359 | top: 0; 1360 | z-index: 3 1361 | } 1362 | .jazz #ios_header .content-wrapper { 1363 | /* background-color: rgba(242,242,242,1); */ 1364 | margin: 0 auto; 1365 | width: 96% 1366 | } 1367 | .jazz .header-text { 1368 | letter-spacing: 0; 1369 | padding-top: 8px 1370 | } 1371 | .jazz #wwdr { 1372 | padding-top: 8px 1373 | } 1374 | .jazz #valence { 1375 | display: block; 1376 | height: 91px; 1377 | left: 0; 1378 | position: relative; 1379 | top: 0; 1380 | width: 100%; 1381 | z-index: 2 1382 | } 1383 | .jazz #valence .content-wrapper { 1384 | /* background-color: rgba(242,242,242,1); */ 1385 | margin: 0 auto; 1386 | width: 96% 1387 | } 1388 | .jazz #hierarchial_navigation { 1389 | font-size: 1.4em; 1390 | margin-bottom: 0; 1391 | margin-top: 0; 1392 | padding-left: 10%; 1393 | padding-right: 10%; 1394 | text-align: center 1395 | } 1396 | .jazz #search { 1397 | background-image: url(../Images/search_2x.png); 1398 | background-position: 50% 50%; 1399 | background-repeat: no-repeat; 1400 | background-size: 32px 32px; 1401 | float: right; 1402 | height: 44px; 1403 | margin: 0 80px 0 0; 1404 | padding: 0; 1405 | width: 44px 1406 | } 1407 | .jazz input[type=search] { 1408 | display: none 1409 | } 1410 | .jazz input[type=search].enabled { 1411 | background-image: none; 1412 | display: block; 1413 | font-size: 1.4em; 1414 | height: 40px; 1415 | margin-right: -75px; 1416 | margin-top: 64px; 1417 | outline: 13px solid rgba(160,160,160,1); 1418 | padding-left: 8px; 1419 | -webkit-border-radius: 0; 1420 | width: 297px 1421 | } 1422 | .jazz .download-text { 1423 | background-image: url(../Images/download_2x.png); 1424 | background-position: 50% 50%; 1425 | background-repeat: no-repeat; 1426 | background-size: 32px 32px; 1427 | color: transparent; 1428 | height: 44px; 1429 | margin: 0 10px 0 0; 1430 | width: 44px 1431 | } 1432 | .jazz #shortstack { 1433 | float: none; 1434 | display: block; 1435 | height: 32px; 1436 | margin-left: 75px; 1437 | margin-top: 42px; 1438 | padding: 6px; 1439 | position: absolute; 1440 | width: 32px 1441 | } 1442 | .jazz .book-parts { 1443 | border: 0; 1444 | box-shadow: 0 0 0; 1445 | clear: both; 1446 | margin: 61px 0 0 -20px; 1447 | -webkit-overflow-scrolling: auto; 1448 | z-index: -1 1449 | } 1450 | .jazz .book-parts.open { 1451 | display: block; 1452 | margin-left: 0; 1453 | -webkit-overflow-scrolling: touch; 1454 | width: 100%; 1455 | z-index: 2 1456 | } 1457 | .jazz .part-name { 1458 | padding-left: 30px 1459 | } 1460 | .jazz .nav-part-active { 1461 | padding-bottom: 0 1462 | } 1463 | .jazz .nav-chapters { 1464 | line-height: 180% 1465 | } 1466 | .jazz .nav-chapter { 1467 | line-height: 140%; 1468 | padding-bottom: 22px; 1469 | padding-left: 5px 1470 | } 1471 | .jazz .content-wrapper { 1472 | /* background-color: rgba(255,255,255,1); */ 1473 | width: 100% 1474 | } 1475 | .jazz .chapter { 1476 | border: 0; 1477 | box-shadow: none; 1478 | left: 0; 1479 | margin: 0 auto; 1480 | padding-bottom: 50px; 1481 | padding-top: 6px; 1482 | position: relative; 1483 | right: 0; 1484 | top: 0; 1485 | -webkit-overflow-scrolling: touch; 1486 | width: 96% 1487 | } 1488 | .jazz .frozen { 1489 | position: fixed; 1490 | z-index: -10 1491 | } 1492 | .jazz .chapter-name { 1493 | margin-top: 0; 1494 | padding: 10px 15px 10px 5px; 1495 | width: 100% 1496 | } 1497 | .jazz #mini_toc { 1498 | background-position-y: 14px; 1499 | margin: 10px 0 10px 5px; 1500 | padding: 10px 10px 5px; 1501 | position: static; 1502 | width: 246px 1503 | } 1504 | .jazz #mini_toc #mini_toc_button { 1505 | width: 246px 1506 | } 1507 | .jazz .section { 1508 | padding: 10px 5px 20px 1509 | } 1510 | .jazz .section-name { 1511 | margin-top: 0 1512 | } 1513 | .jazz .figure img { 1514 | max-width: 275px 1515 | } 1516 | .jazz .list-bullet { 1517 | margin-left: 18px; 1518 | padding-left: 15px 1519 | } 1520 | .jazz .intro ul.list-bullet { 1521 | margin-top: 10px 1522 | } 1523 | .jazz .intro ul.list-bullet li.item { 1524 | float: none; 1525 | padding: 5px 0; 1526 | width: 100% 1527 | } 1528 | .jazz ul.list-bullet li.item:before { 1529 | padding-top: 1px 1530 | } 1531 | .jazz .intro ul.list-bullet li.item .para { 1532 | line-height: 200% 1533 | } 1534 | .jazz .two-columns { 1535 | display: block; 1536 | margin: 80px auto 1537 | } 1538 | .jazz .two-columns .inline-graphic { 1539 | max-width: 100% 1540 | } 1541 | .jazz .left-column { 1542 | display: block 1543 | } 1544 | .jazz .right-column { 1545 | display: block; 1546 | padding-left: 0 1547 | } 1548 | .jazz .two-columns img { 1549 | padding-bottom: 10px 1550 | } 1551 | .jazz .two-columns .para { 1552 | font-size: 1.2em 1553 | } 1554 | .jazz .rec-container .blurb .para:nth-child(1) { 1555 | width: 95% 1556 | } 1557 | .jazz .rec-container .left-container { 1558 | display: block; 1559 | width: 100% 1560 | } 1561 | .jazz .rec-container .right-container { 1562 | display: block; 1563 | margin-top: 10px; 1564 | width: 100% 1565 | } 1566 | .jazz #next_previous { 1567 | margin: 0 10px; 1568 | position: static; 1569 | width: 95% 1570 | } 1571 | .jazz .previous-link { 1572 | display: table-cell; 1573 | height: 60px; 1574 | margin-bottom: 30px; 1575 | width: 40% 1576 | } 1577 | .jazz .next-link { 1578 | display: table-cell; 1579 | height: 60px; 1580 | margin-bottom: 30px; 1581 | width: 40% 1582 | } 1583 | .jazz .next-link a,.jazz .previous-link a { 1584 | display: table-cell; 1585 | vertical-align: middle; 1586 | width: 90% 1587 | } 1588 | .jazz #next_previous .copyright a { 1589 | display: inline; 1590 | vertical-align: baseline 1591 | } 1592 | .jazz .copyright { 1593 | margin: 0; 1594 | text-align: center 1595 | } 1596 | .jazz #footer { 1597 | /* background-color: rgba(255,255,255,1); */ 1598 | padding-bottom: 20px; 1599 | position: relative 1600 | } 1601 | .jazz #footer #leave_feedback { 1602 | margin: 0 auto; 1603 | height: 15px; 1604 | position: static; 1605 | width: 60px 1606 | } 1607 | .jazz #modal { 1608 | margin-bottom: 7px; 1609 | overflow: scroll!important; 1610 | padding: 0; 1611 | -webkit-overflow-scrolling: touch; 1612 | width: 300px 1613 | } 1614 | .jazz #modal #closebox { 1615 | left: 266px; 1616 | top: 5px 1617 | } 1618 | .jazz .activated { 1619 | height: 700px; 1620 | margin-bottom: 0 1621 | } 1622 | .jazz #feedback { 1623 | padding: 10px; 1624 | width: 280px 1625 | } 1626 | .jazz #modal #sending { 1627 | width: 300px 1628 | } 1629 | .jazz #modal #feedback h2 { 1630 | font-size: 1.1em; 1631 | margin-bottom: 5px; 1632 | margin-top: 0; 1633 | padding-top: 0 1634 | } 1635 | .jazz #modal #feedback .left-leaf { 1636 | float: none; 1637 | margin-bottom: 15px; 1638 | width: 250px 1639 | } 1640 | .jazz #modal #feedback .right-leaf { 1641 | float: none; 1642 | width: 250px 1643 | } 1644 | .jazz #modal #feedback #comment { 1645 | -webkit-border-radius: 0; 1646 | height: 90px; 1647 | width: 266px 1648 | } 1649 | .jazz #feedback .asterisk#a1 { 1650 | left: 185px; 1651 | top: 5px 1652 | } 1653 | .jazz #feedback .asterisk#a2 { 1654 | top: 270px; 1655 | left: 279px 1656 | } 1657 | .jazz #modal #feedback #email { 1658 | -webkit-border-radius: 0; 1659 | width: 266px 1660 | } 1661 | .jazz #modal #feedback .fineprint { 1662 | bottom: 0; 1663 | position: relative; 1664 | width: 200px 1665 | } 1666 | .jazz #modal #feedback input[type=button] { 1667 | /* background-color: rgba(160,160,160,1); */ 1668 | background-image: none; 1669 | color: rgba(255,255,255,1); 1670 | font-family: Helvetica,Arial,sans-serif; 1671 | left: 0; 1672 | margin: 10px 0 0; 1673 | -webkit-border-radius: 0; 1674 | -webkit-appearance: none; 1675 | -moz-appearance: none; 1676 | appearance: none 1677 | } 1678 | .jazz #modal #feedback #submit { 1679 | margin: 10px 0 0 1680 | } 1681 | 1682 | } 1683 | @media only screen and (min-device-width:320px) and (max-device-width:568px) and (orientation:landscape) {html { 1684 | -webkit-text-size-adjust: none 1685 | } 1686 | body.jazz { 1687 | /* background-color: rgba(255,255,255,1); */ 1688 | font-size: 70%; 1689 | overflow-x: hidden 1690 | } 1691 | .jazz #ios_header { 1692 | display: block; 1693 | height: 30px; 1694 | position: static; 1695 | top: 0; 1696 | z-index: 3 1697 | } 1698 | .jazz #ios_header .content-wrapper { 1699 | /* background-color: rgba(242,242,242,1); */ 1700 | margin: 0 auto; 1701 | width: 96% 1702 | } 1703 | .jazz .header-text { 1704 | letter-spacing: 0; 1705 | padding-top: 8px 1706 | } 1707 | .jazz #wwdr { 1708 | padding-top: 8px 1709 | } 1710 | .jazz #valence { 1711 | display: block; 1712 | height: 82px; 1713 | left: 0; 1714 | position: relative; 1715 | top: 0; 1716 | width: 100%; 1717 | z-index: 2 1718 | } 1719 | .jazz #valence .content-wrapper { 1720 | /* background-color: rgba(242,242,242,1); */ 1721 | margin: 0 auto; 1722 | width: 96% 1723 | } 1724 | .jazz #hierarchial_navigation { 1725 | float: none; 1726 | font-size: 1.4em; 1727 | margin: 0 auto; 1728 | padding-top: 0; 1729 | text-align: center; 1730 | width: 90% 1731 | } 1732 | .jazz #search { 1733 | background-image: url(../Images/search_2x.png); 1734 | background-position: 50% 50%; 1735 | background-repeat: no-repeat; 1736 | background-size: 32px 32px; 1737 | float: right; 1738 | height: 44px; 1739 | margin: 4px 199px 0 0; 1740 | padding: 0; 1741 | width: 44px 1742 | } 1743 | .jazz input[type=search] { 1744 | display: none 1745 | } 1746 | .jazz input[type=search].enabled { 1747 | background-image: none; 1748 | display: block; 1749 | font-size: 1.4em; 1750 | height: 40px; 1751 | margin-right: -200px; 1752 | margin-top: 60px; 1753 | outline: 13px solid rgba(128,128,128,1); 1754 | padding-left: 8px; 1755 | -webkit-border-radius: 0; 1756 | width: 545px 1757 | } 1758 | .jazz .download-text { 1759 | background-image: url(../Images/download_2x.png); 1760 | background-position: 50% 50%; 1761 | background-repeat: no-repeat; 1762 | background-size: 32px 32px; 1763 | color: transparent; 1764 | height: 44px; 1765 | margin: 4px 10px 0 0; 1766 | width: 44px 1767 | } 1768 | .jazz #shortstack { 1769 | float: none; 1770 | display: block; 1771 | height: 32px; 1772 | margin-left: 192px; 1773 | margin-top: 5px; 1774 | padding: 6px; 1775 | position: absolute; 1776 | width: 32px 1777 | } 1778 | .jazz .book-parts { 1779 | clear: both; 1780 | display: none; 1781 | margin: 51px 0 0 -20px; 1782 | -webkit-overflow-scrolling: touch; 1783 | z-index: 1 1784 | } 1785 | .jazz .book-parts.open { 1786 | display: block; 1787 | width: 60%; 1788 | z-index: 2 1789 | } 1790 | .jazz .part-name { 1791 | padding-left: 30px 1792 | } 1793 | .jazz .nav-part-active { 1794 | padding-bottom: 0 1795 | } 1796 | .jazz .nav-chapters { 1797 | line-height: 180% 1798 | } 1799 | .jazz .nav-chapter { 1800 | line-height: 140%; 1801 | padding-bottom: 22px; 1802 | padding-left: 5px 1803 | } 1804 | .jazz .content-wrapper { 1805 | /* background-color: rgba(255,255,255,1); */ 1806 | width: 100% 1807 | } 1808 | .jazz .chapter { 1809 | border: 0; 1810 | box-shadow: none; 1811 | left: 0; 1812 | margin: 0 auto; 1813 | padding-bottom: 50px; 1814 | padding-top: 6px; 1815 | position: relative; 1816 | right: 0; 1817 | top: 0; 1818 | -webkit-overflow-scrolling: touch; 1819 | width: 96% 1820 | } 1821 | .jazz .frozen { 1822 | padding-top: 112px; 1823 | position: fixed; 1824 | z-index: -10 1825 | } 1826 | .jazz .chapter-name { 1827 | padding: 10px 15px 10px 5px; 1828 | width: 100% 1829 | } 1830 | .jazz #mini_toc { 1831 | background-position-y: 14px; 1832 | margin: 10px 0 10px 5px; 1833 | padding: 10px 10px 5px; 1834 | position: static; 1835 | width: 246px 1836 | } 1837 | .jazz #mini_toc #mini_toc_button { 1838 | width: 246px 1839 | } 1840 | .jazz .section { 1841 | padding: 10px 5px 20px 1842 | } 1843 | .jazz .figure img { 1844 | max-width: 275px 1845 | } 1846 | .jazz .list-bullet { 1847 | margin-left: 18px; 1848 | padding-left: 15px 1849 | } 1850 | .jazz .intro ul.list-bullet { 1851 | margin-top: 10px 1852 | } 1853 | .jazz .intro ul.list-bullet li.item { 1854 | float: none; 1855 | padding: 5px 0; 1856 | width: 100% 1857 | } 1858 | .jazz ul.list-bullet li.item:before { 1859 | padding-top: 1px 1860 | } 1861 | .jazz .intro ul.list-bullet li.item .para { 1862 | line-height: 200% 1863 | } 1864 | .jazz .two-columns { 1865 | display: block; 1866 | margin: 80px auto 1867 | } 1868 | .jazz .left-column { 1869 | display: block 1870 | } 1871 | .jazz .right-column { 1872 | display: block; 1873 | padding-left: 0 1874 | } 1875 | .jazz .two-columns img { 1876 | padding-bottom: 10px 1877 | } 1878 | .jazz .two-columns .inline-graphic { 1879 | max-width: 100% 1880 | } 1881 | .jazz .two-columns .para { 1882 | font-size: 1.2em 1883 | } 1884 | .jazz .rec-container .blurb .para:nth-child(1) { 1885 | width: 95% 1886 | } 1887 | .jazz .rec-container .left-container { 1888 | display: block; 1889 | width: 100% 1890 | } 1891 | .jazz .rec-container .right-container { 1892 | display: block; 1893 | margin-top: 10px; 1894 | width: 100% 1895 | } 1896 | .jazz #next_previous { 1897 | margin: 0 10px; 1898 | position: static; 1899 | width: 95% 1900 | } 1901 | .jazz .previous-link { 1902 | display: table-cell; 1903 | height: 60px; 1904 | margin-bottom: 30px; 1905 | width: 40% 1906 | } 1907 | .jazz .next-link { 1908 | display: table-cell; 1909 | height: 60px; 1910 | margin-bottom: 30px; 1911 | width: 40% 1912 | } 1913 | .jazz .next-link a,.jazz .previous-link a { 1914 | display: table-cell; 1915 | vertical-align: middle; 1916 | width: 90% 1917 | } 1918 | .jazz #next_previous .copyright a { 1919 | display: inline; 1920 | vertical-align: baseline 1921 | } 1922 | .jazz .copyright { 1923 | margin: 0; 1924 | text-align: center 1925 | } 1926 | .jazz #footer { 1927 | /* background-color: rgba(255,255,255,1); */ 1928 | padding-bottom: 20px; 1929 | position: relative 1930 | } 1931 | .jazz #footer #leave_feedback { 1932 | margin: 0 auto; 1933 | height: 15px; 1934 | position: static; 1935 | width: 100px 1936 | } 1937 | .jazz #modal { 1938 | margin-bottom: 7px; 1939 | overflow: scroll!important; 1940 | padding: 0; 1941 | -webkit-overflow-scrolling: touch; 1942 | width: 300px 1943 | } 1944 | .jazz #modal #closebox { 1945 | left: 266px; 1946 | top: 5px 1947 | } 1948 | .jazz .activated { 1949 | height: 700px; 1950 | margin-bottom: 0 1951 | } 1952 | .jazz #feedback { 1953 | padding: 10px; 1954 | width: 280px 1955 | } 1956 | .jazz #modal #sending { 1957 | width: 300px 1958 | } 1959 | .jazz #modal #feedback h2 { 1960 | font-size: 1.1em; 1961 | margin-bottom: 5px; 1962 | margin-top: 0; 1963 | padding-top: 0 1964 | } 1965 | .jazz #modal #feedback .left-leaf { 1966 | float: none; 1967 | margin-bottom: 15px; 1968 | width: 250px 1969 | } 1970 | .jazz #modal #feedback .right-leaf { 1971 | float: none; 1972 | width: 250px 1973 | } 1974 | .jazz #modal #feedback #comment { 1975 | -webkit-border-radius: 0; 1976 | height: 90px; 1977 | width: 266px 1978 | } 1979 | .jazz #feedback .asterisk#a1 { 1980 | left: 185px; 1981 | top: 5px 1982 | } 1983 | .jazz #feedback .asterisk#a2 { 1984 | top: 270px; 1985 | left: 279px 1986 | } 1987 | .jazz #modal #feedback #email { 1988 | -webkit-border-radius: 0; 1989 | width: 266px 1990 | } 1991 | .jazz #modal #feedback .fineprint { 1992 | bottom: 0; 1993 | position: relative; 1994 | width: 200px 1995 | } 1996 | .jazz #modal #feedback input[type=button] { 1997 | /* background-color: rgba(160,160,160,1); */ 1998 | background-image: none; 1999 | color: rgba(255,255,255,1); 2000 | font-family: Helvetica,Arial,sans-serif; 2001 | left: 0; 2002 | margin: 10px 0 0; 2003 | -webkit-border-radius: 0; 2004 | -webkit-appearance: none; 2005 | -moz-appearance: none; 2006 | appearance: none 2007 | } 2008 | .jazz #modal #feedback #submit { 2009 | margin: 10px 0 0 2010 | } 2011 | 2012 | } 2013 | .svg-container { 2014 | position: relative 2015 | } 2016 | .svg-play-button { 2017 | background: url(../Images/playbutton.svg) no-repeat; 2018 | background-position: 0 0; 2019 | background-size: cover; 2020 | width: 32px; 2021 | height: 32px; 2022 | position: absolute; 2023 | top: 90px; 2024 | left: 90px; 2025 | pointer-events: none; 2026 | opacity: 1; 2027 | -webkit-transition: opacity .3s ease 2028 | } 2029 | .svg-play-button.faded { 2030 | opacity: 0 2031 | } 2032 | .p { 2033 | color: rgba(0,0,0,1) 2034 | } 2035 | .c { 2036 | color: rgba(0,116,0,1); 2037 | font-style: italic 2038 | } 2039 | .err { 2040 | } 2041 | .k { 2042 | color: rgba(170,13,145,1) 2043 | } 2044 | .o { 2045 | color: #666 2046 | } 2047 | .cm { 2048 | color: rgba(0,116,0,1); 2049 | font-style: italic 2050 | } 2051 | .cp { 2052 | color: rgba(100,56,32,1) 2053 | } 2054 | .c1 { 2055 | color: rgba(0,116,0,1); 2056 | font-style: italic 2057 | } 2058 | .cs { 2059 | color: rgba(0,116,0,1); 2060 | font-style: italic 2061 | } 2062 | .gd { 2063 | color: #A00000 2064 | } 2065 | .ge { 2066 | font-style: italic 2067 | } 2068 | .gr { 2069 | color: #F00 2070 | } 2071 | .gh { 2072 | color: navy; 2073 | font-weight: 700 2074 | } 2075 | .gi { 2076 | color: #00A000 2077 | } 2078 | .go { 2079 | color: gray 2080 | } 2081 | .gp { 2082 | color: navy; 2083 | font-weight: 700 2084 | } 2085 | .gs { 2086 | font-weight: 700 2087 | } 2088 | .gu { 2089 | color: purple; 2090 | font-weight: 700 2091 | } 2092 | .gt { 2093 | color: #0040D0 2094 | } 2095 | .kc { 2096 | color: rgba(170,13,145,1) 2097 | } 2098 | .kd { 2099 | color: rgba(170,13,145,1) 2100 | } 2101 | .kp { 2102 | color: rgba(170,13,145,1) 2103 | } 2104 | .kr { 2105 | color: rgba(170,13,145,1) 2106 | } 2107 | .kt { 2108 | color: rgba(170,13,145,1) 2109 | } 2110 | .m { 2111 | color: rgba(28,0,207,1) 2112 | } 2113 | .s { 2114 | color: rgba(196,26,22,1) 2115 | } 2116 | .n { 2117 | color: rgba(46,13,110,1) 2118 | } 2119 | .na { 2120 | color: rgba(131,48,30,1) 2121 | } 2122 | .nb { 2123 | color: rgba(170,13,145,1) 2124 | } 2125 | .nc { 2126 | color: rgba(63,110,116,1) 2127 | } 2128 | .no { 2129 | color: rgba(38,71,75,1) 2130 | } 2131 | .nd { 2132 | color: #A2F 2133 | } 2134 | .ni { 2135 | color: #999; 2136 | font-weight: 700 2137 | } 2138 | .ne { 2139 | color: #D2413A; 2140 | font-weight: 700 2141 | } 2142 | .nf { 2143 | color: rgba(0,0,0,1) 2144 | } 2145 | .nl { 2146 | color: rgba(46,13,110,1) 2147 | } 2148 | .nn { 2149 | color: #00F; 2150 | font-weight: 700 2151 | } 2152 | .nt { 2153 | color: green; 2154 | font-weight: 700 2155 | } 2156 | .nv { 2157 | color: #19177C 2158 | } 2159 | .ow { 2160 | color: #A2F; 2161 | font-weight: 700 2162 | } 2163 | .w { 2164 | color: #bbb 2165 | } 2166 | .mf { 2167 | color: rgba(28,0,207,1) 2168 | } 2169 | .mh { 2170 | color: rgba(28,0,207,1) 2171 | } 2172 | .mi { 2173 | color: rgba(28,0,207,1) 2174 | } 2175 | .mo { 2176 | color: rgba(28,0,207,1) 2177 | } 2178 | .sb { 2179 | color: rgba(196,26,22,1) 2180 | } 2181 | .sc { 2182 | color: rgba(196,26,22,1) 2183 | } 2184 | .sd { 2185 | color: rgba(196,26,22,1) 2186 | } 2187 | .s2 { 2188 | color: rgba(196,26,22,1) 2189 | } 2190 | .se { 2191 | color: rgba(196,26,22,1) 2192 | } 2193 | .sh { 2194 | color: rgba(196,26,22,1) 2195 | } 2196 | .si { 2197 | color: rgba(196,26,22,1) 2198 | } 2199 | .sx { 2200 | color: rgba(196,26,22,1) 2201 | } 2202 | .sr { 2203 | color: rgba(196,26,22,1) 2204 | } 2205 | .s1 { 2206 | color: rgba(196,26,22,1) 2207 | } 2208 | .ss { 2209 | color: rgba(196,26,22,1) 2210 | } 2211 | .bp { 2212 | color: green 2213 | } 2214 | .vc { 2215 | color: rgba(63,110,116,1) 2216 | } 2217 | .vg { 2218 | color: #19177C 2219 | } 2220 | .vi { 2221 | color: #19177C 2222 | } 2223 | .il { 2224 | color: rgba(28,0,207,1) 2225 | } 2226 | -------------------------------------------------------------------------------- /BasicSwift.playground/Documentation/section-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | section-1.html 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 |

Basic Swift

18 |

Swift is a full featured language, but it's not necessary to know everything about it to start writing apps. This doc walks through the language basics that are useful when writing apps.

19 | 20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /BasicSwift.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to BasicSwift.playground. 3 | // 4 | -------------------------------------------------------------------------------- /BasicSwift.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /BasicSwift.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BasicSwift.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /FileIO.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | 3 | # File IO with Swift 4 | 5 | At the moment, there's no Swift specific File API. You simply use the existing Foundation APIs for File IO. That means we start by importing it. 6 | 7 | */ 8 | 9 | import Foundation 10 | 11 | /*: 12 | 13 | ## File API 14 | 15 | The traditional file API is built around [NSFileManager](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/occ/cl/NSFileManager), and as you might expect it allows you to examine and interact with the file system. 16 | 17 | The first step is to get a file manager and there are two ways to do that. 18 | 19 | 1. Obtain the default file manager. 20 | 2. Create a new and unique file manager. 21 | 22 | You should generally use the default file manager, except if you're planning to attach a delegate to it. [Delegates](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSFileManagerDelegate_Protocol/index.html#//apple_ref/occ/intf/NSFileManagerDelegate) are used to receive notifications when operations (copy, move, delete or linking) occur on a file or directory. The delegate allows you to inject additional logic and control if a particular file is processed or skipped. 23 | 24 | Here's how to get the default NSFileManager. 25 | 26 | */ 27 | 28 | NSFileManager.defaultManager() 29 | 30 | //: Note, you can call this as many times as you want. It will always return the same object. 31 | 32 | NSFileManager.defaultManager() 33 | 34 | //: To create a unique object, just use the `init` method. It takes no parameters. 35 | 36 | NSFileManager() 37 | 38 | /*: 39 | 40 | ## Handling Paths 41 | 42 | Before you can work with files, you need to understand how to construct, handle and manipulate file paths. There's two ways to do this, either as strings or as URLs. Both are similar, but each has it's advantages and disadvangages. 43 | 44 | For more on those, see the docs ([NSString](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/index.html#//apple_ref/doc/uid/20000154-SW38), [NSURL](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/index.html#//apple_ref/doc/uid/20000301-SW25). 45 | 46 | ### Strings 47 | 48 | Appending to or deleting path components or extensions. 49 | 50 | */ 51 | 52 | "/tmp".stringByAppendingPathComponent("junk") 53 | "/tmp/file".stringByAppendingPathExtension("txt") 54 | 55 | "/tmp/junk".stringByDeletingPathExtension 56 | "/tmp/file.txt".stringByDeletingPathExtension 57 | 58 | //: Obtain the current working directory 59 | 60 | NSFileManager.defaultManager().currentDirectoryPath 61 | 62 | //: Evaluate things like `~`, `.` and `..` in a path 63 | 64 | "~/".stringByExpandingTildeInPath 65 | "~".stringByStandardizingPath 66 | "/tmp/junk/path/../../".stringByStandardizingPath 67 | 68 | /*: 69 | 70 | ### URLs 71 | 72 | Appending to or deleting path components or extensions. 73 | 74 | */ 75 | 76 | NSURL(fileURLWithPath: "/tmp")?.URLByAppendingPathComponent("junk") 77 | NSURL(fileURLWithPath: "/tmp", isDirectory: true)?.URLByAppendingPathComponent("junk", isDirectory: true) 78 | NSURL(fileURLWithPath: "/tmp/file")?.URLByAppendingPathExtension("txt") 79 | 80 | NSURL(fileURLWithPath: "/tmp/junk/", isDirectory: true)?.URLByDeletingLastPathComponent 81 | NSURL(fileURLWithPath: "/tmp/junk")?.URLByDeletingLastPathComponent 82 | NSURL(fileURLWithPath: "/tmp/file.txt")?.URLByDeletingPathExtension 83 | 84 | //: Obtain the current working directory 85 | 86 | NSURL(fileURLWithPath: NSFileManager.defaultManager().currentDirectoryPath) 87 | 88 | //: Obtain a URL relative to a path 89 | 90 | NSURL(string: "../../", relativeToURL: NSURL(fileURLWithPath: "/tmp/junk/path/")) 91 | 92 | /*: 93 | 94 | ### Special Paths 95 | 96 | There are a handful of "special" paths, you might want to access. These are things like the "Desktop", the user's directory, the application directory, etc. Here's how you would get the paths for those. 97 | 98 | ... as a list of strings 99 | 100 | */ 101 | 102 | NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) 103 | 104 | //: ... as a list of urls 105 | 106 | NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.ApplicationDirectory, inDomains: NSSearchPathDomainMask.LocalDomainMask) 107 | 108 | //: ... as a single url 109 | 110 | NSFileManager.defaultManager().URLForDirectory(NSSearchPathDirectory.DesktopDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: nil, create: false, error: nil) 111 | 112 | /*: 113 | 114 | ## Inspecting Files 115 | 116 | In many cases you might want to inspect a file or folder, perhaps to confirm if it exists or if it has the proper permissions. The NSFileManager allows you to do all this. 117 | 118 | Note: The NSFileManager docs suggest that you not use these methods because they are succeptable to race conditions, instead the suggestion is to just try an action and be prepared to gracefully handle an error. 119 | 120 | */ 121 | 122 | let curPath = NSFileManager.defaultManager().currentDirectoryPath 123 | 124 | //: Check if a file or directory exists at the path 125 | 126 | NSFileManager.defaultManager().fileExistsAtPath(curPath) 127 | 128 | //: Check if exists and if a directory 129 | 130 | var isDir: ObjCBool = false 131 | NSFileManager.defaultManager().fileExistsAtPath(curPath, isDirectory: &isDir) 132 | if isDir { 133 | "YES!" 134 | } 135 | 136 | //: Check if it's read / write / executable / deletable 137 | 138 | NSFileManager.defaultManager().isReadableFileAtPath(curPath) 139 | NSFileManager.defaultManager().isWritableFileAtPath(curPath) 140 | NSFileManager.defaultManager().isExecutableFileAtPath(curPath) 141 | NSFileManager.defaultManager().isDeletableFileAtPath(curPath) 142 | 143 | /*: 144 | 145 | ## Directory Listings & Walking the Directory Tree 146 | 147 | It's often useful to be able to list the contents of a directory or even recursively walk a directory tree. This can be done with the NSFileManager and either a string path or an NSURL. 148 | 149 | In the examples below, we'll use NSURL. It's slightly more verbose, but offers more functionality. 150 | 151 | ### List the contents of a Directory 152 | 153 | */ 154 | 155 | var error:NSError? 156 | 157 | //: Get the URL pointing to the `/Applications` directory 158 | 159 | let appsUrl:NSURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.ApplicationDirectory, inDomains: NSSearchPathDomainMask.LocalDomainMask)[0] as! NSURL 160 | 161 | //: List the files (returns an array of NSURLs) in that directory 162 | 163 | let filesInDir = NSFileManager.defaultManager().contentsOfDirectoryAtURL(appsUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles, error: &error) 164 | 165 | /*: 166 | 167 | ### Recursively walk a directory tree 168 | 169 | To get started, we get a URL or string path to our target directory. In this case, it's the user's document's directory. 170 | 171 | */ 172 | 173 | let docsUrl = NSFileManager.defaultManager().URLForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: nil, create: false, error: nil)! 174 | 175 | /*: 176 | 177 | The next step is to configure the NSDirectoryEnumerator. This takes a few arguments. 178 | 179 | - the URL or path from which to start 180 | - an array of keys to cache. `nil` gives you the default. `[]` gives you none. [Common file system keys](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/index.html#//apple_ref/doc/constant_group/Common_File_System_Resource_Keys) 181 | - Options mask to control behavior of enumerator. [NSDirectoryEnumerationOptions](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/c/tdef/NSDirectoryEnumerationOptions) 182 | - Optional error handler `(NSURL, NSError) -> Bool` that's called when there's a problem. The handler can return true / false to control continue or stop. 183 | 184 | In this example we don't cache any keys, we skip hidden files and the error handler just logs a message and continues. 185 | 186 | */ 187 | 188 | let fsEnumerator = NSFileManager.defaultManager().enumeratorAtURL(docsUrl, includingPropertiesForKeys: [], options: NSDirectoryEnumerationOptions.SkipsHiddenFiles) 189 | { (url:NSURL!, err:NSError!) -> Bool in 190 | if let e = err { 191 | "Error \(e)" 192 | } 193 | return true 194 | } 195 | 196 | //: Last, we run the NSDirectoryEnumerator. 197 | 198 | for url in fsEnumerator! { 199 | "url -> \(url)" 200 | } 201 | 202 | /*: 203 | 204 | ## Basic File Ops 205 | 206 | Copy, move and delete operations are straigtforward. You use the NSFileManager object to perform the operation. 207 | 208 | It's also possible to use an NSFileManagerDelegate with the copy, move and delete operations. This gives you an easy way to add logic and control what is or is not deleted. An example of this would be deleting all the files with an extension of *pdf*. 209 | 210 | */ 211 | 212 | let origFile = curPath.stringByAppendingPathComponent("origfile.txt") 213 | let copyFile = curPath.stringByAppendingPathComponent("copyfile.txt") 214 | let moveFile = curPath.stringByAppendingPathComponent("movefile.txt") 215 | let data = "Hello World!".dataUsingEncoding(NSUTF8StringEncoding) 216 | 217 | //: ### Create a file 218 | 219 | NSFileManager.defaultManager().createFileAtPath(origFile, contents: data, attributes: nil) 220 | 221 | //: ### Copy that file 222 | 223 | var err:NSError? 224 | 225 | if NSFileManager.defaultManager().copyItemAtPath(origFile, toPath: copyFile, error: &err) { 226 | "File Copied!" 227 | } else { 228 | "Error \(err)" 229 | } 230 | 231 | //: ### Move the original file 232 | 233 | if NSFileManager.defaultManager().moveItemAtPath(origFile, toPath: moveFile, error: &err) { 234 | "File Moved!" 235 | } else { 236 | "Error \(err)" 237 | } 238 | 239 | //: ### Delete the copied file 240 | 241 | if NSFileManager.defaultManager().removeItemAtPath(copyFile, error: &err) { 242 | "File \(copyFile) removed!" 243 | } else { 244 | "Error \(err)" 245 | } 246 | 247 | //: ### Delete the moved file 248 | 249 | if NSFileManager.defaultManager().removeItemAtPath(moveFile, error: &err) { 250 | "File \(moveFile) removed!" 251 | } else { 252 | "Error \(err)" 253 | } 254 | 255 | /*: 256 | 257 | ## Temp Files and Directories 258 | 259 | Creating temporary files and directories can helpful in your apps. For example, if you need a short term place to stash something on disk. 260 | 261 | On your Mac, there's two places you can use for temporary files. The first is the traditional "/tmp" directory. The second is the user's cache directory. The main difference between the two is that the "/tmp" directory is periodically cleared out. 262 | 263 | ### Locate the "/tmp" directory 264 | 265 | */ 266 | 267 | NSTemporaryDirectory() 268 | 269 | //: ### Locate the cache directory 270 | 271 | NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] 272 | 273 | /*: 274 | 275 | ### Create a temporary file 276 | 277 | There's no Swift or Cocoa API call to make a temporary file. Instead you just use the C function `mkstemp`. Doing that from Swift is easy enough, but requires a few steps. 278 | 279 | First, you need to create the path. We're going to do this by combining the temp directory and a template string. In the template string, all `X` characters are replaced by a unique alphanumeric combination. See `mkstemp` [man page](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/mkstemp.3.html) for more on how it works. 280 | 281 | Also, note how we call `fileSystemRepresentation()` to get an array of encoded characters from the string. We need this to interact properly with the C `mkstemp` function. 282 | 283 | */ 284 | 285 | var tmpFilePathTemplate = NSTemporaryDirectory().stringByAppendingPathComponent("prefix.XXXXXX.suffix").fileSystemRepresentation() 286 | 287 | //: Second, call `mkstemp` with our file name. It returns a file descriptor number, we'll need that in the next step. 288 | 289 | var fileDesc = mkstemp(&tmpFilePathTemplate) 290 | 291 | /*: 292 | 293 | The third step is to check for errors with `mkstemp`. If it fails, it'll return `-1`. More details on the error can be found by inspecting the global `errno`. 294 | 295 | */ 296 | 297 | if fileDesc == -1 { 298 | "Fail :( [\(errno)] -> \(strerror(errno))" 299 | // normally, you'd handle this better 300 | } 301 | 302 | //: The fourth step is to take the file descriptor, which is a number and use it to get a handle to the file. That can then be used to interact with the file. 303 | 304 | var tmpFile = NSFileHandle(fileDescriptor: fileDesc, closeOnDealloc: false) 305 | 306 | // do some stuff 307 | 308 | tmpFile.closeFile() 309 | 310 | //: When we're done with the temp file, we need to delete it. The easiest way to do that is with NSFileManager's `removeitemAtPath` method. 311 | 312 | let tmpFilePath = NSFileManager.defaultManager().stringWithFileSystemRepresentation(tmpFilePathTemplate, length: tmpFilePathTemplate.count) 313 | 314 | NSFileManager.defaultManager().removeItemAtPath(tmpFilePath, error: &err) 315 | 316 | 317 | /*: 318 | 319 | ### Create a temporary directory 320 | 321 | This works much like creating a temporary file. You just use the C `mkdtemp` method instead. here's an example. 322 | 323 | */ 324 | 325 | var tempDirPathTemplate = NSTemporaryDirectory().stringByAppendingPathComponent("dir-prefix.XXXXXX.suffix").fileSystemRepresentation() 326 | 327 | mkdtemp(&tempDirPathTemplate) 328 | 329 | let tmpDirPath = NSFileManager.defaultManager().stringWithFileSystemRepresentation(tempDirPathTemplate, length: tempDirPathTemplate.count) 330 | 331 | NSFileManager.defaultManager().removeItemAtPath(tmpDirPath, error: &err) 332 | 333 | /*: 334 | 335 | ## Accessing Resources from an App Bundle 336 | 337 | To access resources that you bundle with your app, things like images, config, etc..; you simply need to use the `NSBundle.mainBundle().pathForResource(..)` method. This returns the full path to the bundled resource. 338 | 339 | In this example, we grabs the "BundledFile.txt" file that is packaged with the playground, read the entire thing and convert it to a string. 340 | 341 | More docs on this [here](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/index.html#//apple_ref/doc/uid/20000214-SW13). 342 | 343 | */ 344 | 345 | if let resourcePath = NSBundle.mainBundle().pathForResource("BundledFile", ofType: "txt") { 346 | NSString(data: NSData(contentsOfFile: resourcePath)!, encoding: NSUTF8StringEncoding) 347 | } 348 | 349 | -------------------------------------------------------------------------------- /FileIO.playground/Resources/BundledFile.txt: -------------------------------------------------------------------------------- 1 | This is some bundled text! -------------------------------------------------------------------------------- /FileIO.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to FileIO.playground. 3 | // 4 | -------------------------------------------------------------------------------- /FileIO.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /FileIO.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JSON.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import SwiftyJSON 2 | 3 | /*: 4 | 5 | ## JSON 6 | 7 | This playground shows a couple approaches for using JSON from Swift. The first is the built-in support and the second is a friendlier library called SwiftyJSON. 8 | 9 | */ 10 | 11 | //: Load a small bit of data to use below 12 | let small_json_data = "{\"a\": 100, \"b\": 200}".dataUsingEncoding(NSUTF8StringEncoding)! 13 | 14 | //: Load a larger amount of data to use below 15 | let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") 16 | let big_json_data = NSData(contentsOfFile: path!) 17 | 18 | /*: 19 | 20 | ### Reading w/Built-in Support 21 | 22 | Here we use Swift's build-in JSON support to parse the small JSON blob. As you can see it's pretty simple, you just have to handle the optionals correctly. 23 | 24 | */ 25 | 26 | var error: NSError? 27 | let small_json_obj: AnyObject? = NSJSONSerialization.JSONObjectWithData(small_json_data, options: nil, error: &error) 28 | 29 | if error != nil { 30 | "Error: \(error)" 31 | } 32 | 33 | if let small_json_dict = small_json_obj as? Dictionary { 34 | let a = small_json_dict["a"]! 35 | let b = small_json_dict["b"]! 36 | "a: \(a) b: \(b)" 37 | } else { 38 | "Couldn't convert to Dictionary" 39 | } 40 | 41 | /*: 42 | 43 | ### Reading w/SwiftyJSON 44 | 45 | Here's the same example, but using SwiftyJSON. The code is easier to read and less verbose. 46 | 47 | */ 48 | 49 | let small_json = JSON(data: small_json_data) 50 | let a = small_json["a"].intValue 51 | let b = small_json["b"].int 52 | "a: \(a) b: \(b)" 53 | 54 | /*: 55 | 56 | ### More Complicated Example of Reading 57 | 58 | This example parses a more complicated JSON object. The `test.json` file is in the `Resources` directory of this playground, if you'd like to see the raw JSON. 59 | 60 | #### Built-in Support 61 | 62 | I'm not showing how you'd do this with the built-in support as it's a lot of code and messy. There's nothing wrong with the built-in support, using it just requires more verbose code. 63 | 64 | #### SwiftyJSON 65 | 66 | Here's how you'd parse it with SwiftyJSON. As you can see, it's not much more compliated than the short example above. 67 | 68 | */ 69 | 70 | // parse json 71 | let json_in = JSON(data: big_json_data!) 72 | 73 | "We've read in \(json_in.count) items" 74 | 75 | // test.json is a big list, grab the first item 76 | let item1 = json_in[0] 77 | 78 | // print some of the keys 79 | for (key,val) in item1 { 80 | if key == "tags" { 81 | for (_: String, v: JSON) in val { 82 | v 83 | } 84 | } else if key == "friends" { 85 | for (i: String, friend: JSON) in val { 86 | let id = friend["id"] 87 | let name = friend["name"] 88 | " \(id) -> \(name)" 89 | } 90 | 91 | } else { 92 | "\(key): \(val)" 93 | } 94 | } 95 | 96 | 97 | /*: 98 | 99 | ### Converting to JSON 100 | 101 | The other side of the coin is writing data into the JSON format. Below are two examples on doing this. 102 | 103 | Regardless of the way you do it note the limitations that are documented on the NSJSONSerialization object. Essentially it works with simple types that easily correspond to JSON. 104 | 105 | */ 106 | 107 | let obj_to_dump = ["name":"Jack", "age": 25, "list":["a","b","c",["what":"this"]]] 108 | 109 | 110 | //: #### Built-in Support 111 | 112 | let apl_json_out = NSJSONSerialization.dataWithJSONObject(obj_to_dump, options: NSJSONWritingOptions.PrettyPrinted, error: &error) 113 | if error == nil { 114 | "Raw Data: \(apl_json_out)" 115 | let json_str = NSString(data: apl_json_out!, encoding: NSUTF8StringEncoding) 116 | "String: \(json_str)" 117 | } else { 118 | "Error: \(error)" 119 | } 120 | 121 | /*: 122 | 123 | #### SwiftyJSON 124 | 125 | Note how again, SwiftyJSON API is more concise. 126 | 127 | */ 128 | 129 | let sj_json_out = JSON(obj_to_dump) 130 | "Raw Data: \(sj_json_out.rawData()!)" 131 | "String: \(sj_json_out.rawString()!)" 132 | -------------------------------------------------------------------------------- /JSON.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to JSON.playground. 3 | // 4 | -------------------------------------------------------------------------------- /JSON.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /JSON.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Networking.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | 3 | # HTTP Networking 4 | 5 | There's a good chance your app will need to interact with the world. What better way to do that than through HTTP. 6 | 7 | There's a couple ways you can do this, we'll explore two. First we'll look at the built-in support and then we'll look at third party libraries. We'll cover two examples here, the first is Alamofire and the second is Just, which are both popular open source libraries. 8 | 9 | ## Setup 10 | 11 | Before we get started, we need to import some modules. The first is the XCPlayground. This allows us to tell the Playground that it should keep running, by default it will run and terminate. Since networking requests are generally performed asynchronously, we need the playground to keep running. 12 | 13 | */ 14 | 15 | import XCPlayground 16 | XCPSetExecutionShouldContinueIndefinitely() 17 | 18 | /*: 19 | 20 | We also import Foundation, which provides core Mac APIs, Alamofire which is an open source HTTP networking library and SwiftyJSON which is a JSON parsing library (see JSON playground for more details on that). 21 | 22 | */ 23 | 24 | import Foundation 25 | import Alamofire 26 | import SwiftyJSON 27 | import Just 28 | 29 | /*: 30 | 31 | ## Examples 32 | 33 | All of the examples below send requests to [httpbin.org](http://httpbin.org), which simply echo's the request data back as JSON. We then parse it, using SwiftyJSON and confirm the response. 34 | 35 | We'll cover the following common scenarios. 36 | 37 | 1. Simple GET request 38 | 2. Basic AUTH request 39 | 3. POST request w/Data 40 | 41 | The first section will cover them with the built-in support, the second will use Alamofire and the third will use Just. 42 | 43 | The following is some basic data used by all the tests. 44 | 45 | */ 46 | 47 | let ex1_url = "http://httpbin.org/get" 48 | let ex2_url = "http://httpbin.org/basic-auth/auser/apass" 49 | let ex3_url = "http://httpbin.org/post" 50 | 51 | let params:[String: AnyObject] = [ 52 | "foo": [1,2,3], 53 | "bar": [ 54 | "baz": "qux" 55 | ] 56 | ] 57 | 58 | /*: 59 | 60 | ### Built-in Support 61 | 62 | For basic tasks, it's easy enough to use the built-in support. There's more boiler plate code though, so as you start to do more complicated things the amount of code you need to write will go up quite a bit. The examples here are pretty simple, but you'll see the difference in volume and complexity of code. 63 | 64 | **Ex 1: Simple GET Request** 65 | 66 | */ 67 | 68 | var task = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: ex1_url)!) { 69 | (data, response, err) -> Void in 70 | if err == nil { 71 | (response as! NSHTTPURLResponse).statusCode 72 | let json = JSON(data: data) 73 | json["origin"].string 74 | json["url"].string 75 | } else { 76 | err 77 | } 78 | } 79 | task.resume() 80 | 81 | /*: 82 | 83 | **Ex 2: Basic AUTH request** 84 | 85 | */ 86 | 87 | let loginData = "auser:apass".dataUsingEncoding(NSUTF8StringEncoding) 88 | let loginEncoded = loginData?.base64EncodedStringWithOptions(nil) 89 | let loginString = "Basic \(loginEncoded!)" 90 | 91 | // fails, no auth 92 | task = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: ex2_url)!) { 93 | (data, response, err) -> Void in 94 | if err == nil { 95 | (response as! NSHTTPURLResponse).statusCode 96 | } else { 97 | err 98 | } 99 | } 100 | task.resume() 101 | 102 | // let's send auth, much better! 103 | var request = NSMutableURLRequest(URL: NSURL(string: ex2_url)!) 104 | request.setValue(loginString, forHTTPHeaderField: "Authorization") 105 | 106 | task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 107 | (data, response, err) in 108 | if err == nil { 109 | (response as! NSHTTPURLResponse).statusCode 110 | JSON(data: data!)["user"].stringValue 111 | } else { 112 | err 113 | } 114 | } 115 | task.resume() 116 | 117 | /*: 118 | 119 | **Ex 3: POST request w/Data** 120 | 121 | */ 122 | 123 | request = NSMutableURLRequest(URL: NSURL(string: ex3_url)!) 124 | request.HTTPMethod = "POST" 125 | request.HTTPBody = JSON(params).rawString()!.dataUsingEncoding(NSUTF8StringEncoding) 126 | request.setValue("application/json", forHTTPHeaderField: "Content-Type") 127 | 128 | task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 129 | (data, response, err) in 130 | if err == nil { 131 | (response as! NSHTTPURLResponse).statusCode 132 | let json = JSON(data: data!) 133 | json["json"]["bar"]["baz"].stringValue 134 | } else { 135 | err 136 | } 137 | } 138 | task.resume() 139 | 140 | 141 | /*: 142 | 143 | ## Alamofire - Elegant Networking in Swift 144 | 145 | Alamofire is a third party library which makes sending HTTP requests in Swift easier. Here's three examples of using Alamofire. 146 | 147 | **Ex 1: Simple GET Request** 148 | 149 | */ 150 | 151 | Alamofire.request(.GET, "http://httpbin.org/get").responseJSON { 152 | (req, resp, data, err) in 153 | if err == nil { 154 | resp?.statusCode 155 | let json = JSON(data!) 156 | json["origin"].stringValue 157 | json["url"].stringValue 158 | } else { 159 | err 160 | } 161 | } 162 | 163 | /*: 164 | 165 | **Ex 2: Basic AUTH request** 166 | 167 | */ 168 | 169 | // fails, no auth 170 | Alamofire.request(.GET, "http://httpbin.org/basic-auth/auser/apass").responseJSON { 171 | (req, resp, data, err) in 172 | if err == nil { 173 | resp?.statusCode 174 | } else { 175 | err 176 | } 177 | } 178 | 179 | // let's send auth, much better! 180 | Alamofire.request(.GET, "http://httpbin.org/basic-auth/auser/apass") 181 | .authenticate(user: "auser", password: "apass") 182 | .responseJSON { 183 | (req, resp, data, err) in 184 | if err == nil { 185 | let status = resp?.statusCode 186 | JSON(data!)["user"].stringValue 187 | } else { 188 | println("Fail: \(err)") 189 | } 190 | } 191 | 192 | /*: 193 | 194 | **Ex 3: POST request w/Data** 195 | 196 | */ 197 | 198 | Alamofire.request(.POST, "http://httpbin.org/post", parameters: params, encoding: .JSON) 199 | .responseJSON { 200 | (req, resp, data, err) in 201 | if err == nil { 202 | resp?.statusCode 203 | let json = JSON(data!) 204 | json["json"]["bar"]["baz"].stringValue 205 | } 206 | } 207 | 208 | /*: 209 | 210 | ## Just: Swift HTTP for Humans 211 | 212 | Just is another third party HTTP library. The syntax is different, but the goal is the same; make HTTP easier in Swift. 213 | 214 | **Ex 1: Simple GET Request** 215 | 216 | */ 217 | 218 | Just.get("http://httpbin.org/get") { (r) in 219 | if r.ok { 220 | r.ok 221 | r.statusCode 222 | let json = JSON(data: r.content!) 223 | json["origin"].stringValue 224 | json["url"].stringValue 225 | } 226 | } 227 | 228 | /*: 229 | 230 | **Ex 2: Basic AUTH request** 231 | 232 | */ 233 | 234 | // fails, no auth 235 | Just.get("http://httpbin.org/basic-auth/auser/apass") { (r) in 236 | if !r.ok { 237 | r.ok 238 | r.statusCode 239 | } 240 | } 241 | 242 | // let's send auth, much better! 243 | Just.get("http://httpbin.org/basic-auth/auser/apass", auth: ("auser", "apass"), asyncCompletionHandler: { (r) in 244 | if r.ok { 245 | r.ok 246 | r.statusCode 247 | JSON(data: r.content!)["user"].stringValue 248 | } 249 | }) 250 | 251 | /*: 252 | 253 | **Ex 3: POST request w/Data** 254 | 255 | */ 256 | 257 | Just.post("http://httpbin.org/post", json: params) { (r) in 258 | if r.ok { 259 | r.ok 260 | r.statusCode 261 | let json = JSON(data: r.content!) 262 | json["json"]["bar"]["baz"].stringValue 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /Networking.playground/Resources/JSON.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftyJSON 3 | 4 | // 5 | // JSON INPUT 6 | // 7 | 8 | // load test.json 9 | let path = NSBundle.mainBundle().pathForResource("test", ofType: "json") 10 | 11 | // parse json 12 | let json_in = JSON(data: NSData(contentsOfFile: path!)!) 13 | 14 | println("We've read in \(json_in.count) items") 15 | 16 | // test.json is a big list, grab the first item 17 | let item1 = json_in[0] 18 | 19 | // print some of the keys 20 | for (key,val) in item1 { 21 | if key == "tags" { 22 | for (_: String, v: JSON) in val { 23 | println(v) 24 | } 25 | } else if key == "friends" { 26 | for (i: String, friend: JSON) in val { 27 | let id = friend["id"] 28 | let name = friend["name"] 29 | println(" \(id) -> \(name)") 30 | } 31 | 32 | } else { 33 | println("\(key): \(val)") 34 | } 35 | } 36 | 37 | 38 | // 39 | // JSON OUTPUT 40 | // 41 | 42 | let obj = ["name":"Jack", "age": 25, "list":["a","b","c",["what":"this"]]] 43 | let json_out = JSON(obj) 44 | println("Out: \(json_out.rawString())") -------------------------------------------------------------------------------- /Networking.playground/Resources/JSON.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to JSON.playground. 3 | // 4 | -------------------------------------------------------------------------------- /Networking.playground/Resources/JSON.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Networking.playground/Resources/JSON.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Networking.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to Networking.playground. 3 | // 4 | -------------------------------------------------------------------------------- /Networking.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Playgrounds.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 19 | 21 | 22 | 24 | 25 | 27 | 28 | 30 | 31 | 34 | 36 | 37 | 38 | 41 | 43 | 44 | 47 | 49 | 50 | 51 | 53 | 54 | 56 | 57 | 60 | 63 | 65 | 66 | 67 | 70 | 72 | 73 | 74 | 77 | 79 | 80 | 82 | 83 | 85 | 86 | 87 | 88 | 90 | 91 | 93 | 94 | 95 | 97 | 98 | 100 | 101 | 103 | 104 | 107 | 109 | 110 | 112 | 113 | 115 | 116 | 117 | 120 | 122 | 123 | 125 | 126 | 128 | 129 | 131 | 132 | 134 | 135 | 137 | 138 | 140 | 141 | 143 | 144 | 146 | 147 | 149 | 150 | 151 | 152 | 155 | 157 | 158 | 160 | 161 | 164 | 166 | 167 | 168 | 171 | 173 | 174 | 176 | 177 | 178 | 181 | 184 | 186 | 187 | 189 | 190 | 191 | 194 | 196 | 197 | 199 | 200 | 201 | 203 | 204 | 205 | 207 | 208 | 211 | 213 | 214 | 216 | 217 | 220 | 222 | 223 | 224 | 227 | 229 | 230 | 231 | 233 | 234 | 235 | 237 | 238 | 240 | 241 | 243 | 244 | 245 | 248 | 251 | 253 | 254 | 255 | 258 | 260 | 261 | 264 | 266 | 267 | 269 | 270 | 271 | 274 | 277 | 279 | 280 | 281 | 284 | 286 | 287 | 289 | 290 | 291 | 292 | 294 | 295 | 297 | 298 | 300 | 301 | 302 | 304 | 305 | 307 | 308 | 310 | 311 | 314 | 316 | 317 | 319 | 320 | 322 | 323 | 325 | 326 | 327 | 329 | 330 | 332 | 333 | 335 | 336 | 339 | 341 | 342 | 344 | 345 | 347 | 348 | 350 | 351 | 353 | 354 | 356 | 357 | 359 | 360 | 362 | 363 | 365 | 366 | 368 | 369 | 371 | 372 | 374 | 375 | 377 | 378 | 380 | 381 | 383 | 384 | 386 | 387 | 388 | 389 | 390 | -------------------------------------------------------------------------------- /Playgrounds.xcworkspace/xcshareddata/Playgrounds.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 82E9FBC2-8A6E-4CD9-814D-29B6BE74A681 9 | IDESourceControlProjectName 10 | Playgrounds 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 67620B5EFA902936DF04070AF595B76AB0333747 14 | https://github.com/Alamofire/Alamofire.git 15 | B1A093F9666B6981C8C317B04F27511B9663A5BE 16 | https://github.com/dmikusa/swift_playgrounds.git 17 | BC949C044609264A7DE78DBBB5DCDDF5E033DADA 18 | https://github.com/JustHTTP/Just.git 19 | C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3 20 | https://github.com/SwiftyJSON/SwiftyJSON.git 21 | 22 | IDESourceControlProjectPath 23 | Playgrounds.xcworkspace 24 | IDESourceControlProjectRelativeInstallPathDictionary 25 | 26 | 67620B5EFA902936DF04070AF595B76AB0333747 27 | ../Alamofire/ 28 | B1A093F9666B6981C8C317B04F27511B9663A5BE 29 | .. 30 | BC949C044609264A7DE78DBBB5DCDDF5E033DADA 31 | ../Just/ 32 | C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3 33 | ../SwiftyJSON/ 34 | 35 | IDESourceControlProjectURL 36 | https://github.com/dmikusa/swift_playgrounds.git 37 | IDESourceControlProjectVersion 38 | 111 39 | IDESourceControlProjectWCCIdentifier 40 | B1A093F9666B6981C8C317B04F27511B9663A5BE 41 | IDESourceControlProjectWCConfigurations 42 | 43 | 44 | IDESourceControlRepositoryExtensionIdentifierKey 45 | public.vcs.git 46 | IDESourceControlWCCIdentifierKey 47 | 67620B5EFA902936DF04070AF595B76AB0333747 48 | IDESourceControlWCCName 49 | Alamofire 50 | 51 | 52 | IDESourceControlRepositoryExtensionIdentifierKey 53 | public.vcs.git 54 | IDESourceControlWCCIdentifierKey 55 | BC949C044609264A7DE78DBBB5DCDDF5E033DADA 56 | IDESourceControlWCCName 57 | Just 58 | 59 | 60 | IDESourceControlRepositoryExtensionIdentifierKey 61 | public.vcs.git 62 | IDESourceControlWCCIdentifierKey 63 | B1A093F9666B6981C8C317B04F27511B9663A5BE 64 | IDESourceControlWCCName 65 | Playgrounds 66 | 67 | 68 | IDESourceControlRepositoryExtensionIdentifierKey 69 | public.vcs.git 70 | IDESourceControlWCCIdentifierKey 71 | C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3 72 | IDESourceControlWCCName 73 | SwiftyJSON 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Playgrounds.xcworkspace/xcuserdata/daniel.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmikusa/swift_playgrounds/4cbd46426f5426b11dc532d719ea24d29cf0c44e/Playgrounds.xcworkspace/xcuserdata/daniel.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Playgrounds.xcworkspace/xcuserdata/daniel.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildIntermediatesPath 8 | Build/Intermediates 9 | CustomBuildLocationType 10 | RelativeToDerivedData 11 | CustomBuildProductsPath 12 | Build/Products 13 | DerivedDataLocationStyle 14 | Default 15 | IssueFilterStyle 16 | ShowActiveSchemeOnly 17 | LiveSourceIssuesEnabled 18 | 19 | SharedBuildFolderName 20 | Build 21 | SnapshotAutomaticallyBeforeSignificantChanges 22 | 23 | SnapshotLocationStyle 24 | Default 25 | 26 | 27 | -------------------------------------------------------------------------------- /Playgrounds.xcworkspace/xcuserdata/daniel.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift Playgrounds 2 | 3 | This is a collection of Swift playgrounds that I included in my presentation at the [2015 MacAdmins Conference at Penn State University](http://macadmins.psu.edu/). 4 | 5 | It includes playgrounds that show basic Swift, JSON parsing, sending HTTP requests and doing basic file IO. 6 | 7 | ## Usage 8 | 9 | 1. Clone the repo. `git clone --recursive https://github.com/dmikusa/swift_playgrounds.git` 10 | 2. Open the workspace in XCode. Wait for it to index everything. 11 | 3. In the Schema selector, pick SwiftyJSON -> My Mac. Go to the Project menu and pick Build. Repeat for Just-OSX -> My Mac and Alamofire OSX -> My Mac. This will build the frameworks used by the projects. 12 | 4. Select a playground or go to Editor -> Execute Playground to refresh it. 13 | 14 | Note: You only need to perform the first three steps once. After that, you can edit the playgrounds as much as you want. 15 | --------------------------------------------------------------------------------