변수
- let, var
- Int, Double, Bool, String, Array, Dictionary
Converting 은 명시적으로!
let width = 94
String(width)
문자열 안에 변수값
"\(width + height)"
연산 후, 문자열로 변환
여러줄에 걸쳐 문자열 정의할 때
let g = """
I said "I have"
"""
큰따옴표 3개
배열
var arr = ["a", "b", "c"]
var arr2 = [String]() // 빈 배열
var arr3 = [] // 빈 배열
arr.append("d") // 요소 추가
딕셔너리
var dict = [
"key1" : "value1",
"key2" : "value2",
]
dict["key2"] = "newValue"
var dict2 = [String:String]() // 빈 딕셔너리
Optional variables
값이 있거나 nil 이거나…
var str: String? = nil
var str2:String = "Hello"
print("\(str ?? str2)") // ?? 뒤 str2는 str이 nil 일 경우 기본값
var optionalString : String? = "hello"
print(optionalString == nil) // false 가 찍힌다.
Control Flow
for ~ in
// 배열
let arr = [1,2,3,4]
for score in arr {
...
}
// 딕셔너리
let dict = [
"prime" : [2,3,5,7,11,13],
"Fibonacci" : [1,1,2,3,5,8],
]
for (kind, numbers) in dict {
for number in numbers {
...
}
}
// 딕셔너리는 순서가 없다. 순서대로 나온다는 보장이 없음!
for i in 0..<4 {
...
}
// range 0,1,2,3
while, repeat ~ while
while n < 100 {
n *= 2
}
repeat {
m *= 2
} while m < 100
if
if 조건 {
...
} else {
...
}
if optional 변수
if let name = optionalName {
...
}
optionalName 이 nil 이면 조건이 false가 된다. let은 optionalName을 unwrap 해서 name에 넣는다.
switch
switch vegetable {
case "celery" :
print(...)
case "cucumber" :
print(...)
case let x where x.hasSuffix("pepper") // 이런 것도 됨!
print(...)
default : // default 없으면 에러
print(...)
}
break 없어도 됨!
함수
// 선언
func greet(person:String, day:String) -> String {
return "Hello \(person), today is \(day)"
}
greet(person:"Bob", day:"Tuesday")
func greet(_ person:string, on day:String) -> {
// _ 를 쓰면 person 이라는 인자없이 호출가능
// on 은 호출할 때 인자가 됨. day는 함수 내부 변수
greet("Bob", on:"Tuesday")
// 튜플
func calc(scores:[Int]) -> (min:Int, max:Int,sum:Int) {
let statistic = calc(score:[5,3,100,3,9])
statistic.sum
// sum 은 아래처럼 접근가능
statistic.2
// min 이 0, max 가 1, sum 이 2
함수 안에 함수 선언 (nested)
func A() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
함수는 함수를 리턴할 수 있다.
func makeIncrementer() -> ((Int)->Int) {
func addOne(number:Int) -> Int {
return 1 + number
}
}
var incrementer = makeIncrementer()
incrementer(7)
함수를 인자로 받을 수 있다.
func hasAnyMatches(list:[Int], condition:(Int)->Bool) -> Bool {
// Int 를 받아 Bool 을 리턴하는 함수를 condition 에 인자로 줄 수 있다.
Closure
closure : block of code
numbers.map( { (number:Int) -> Int in
let result = 3 * number
return result
})
numbers.map({ number in 3 * number})
// 인자,리턴타입 생략, return 생략
// 인자를 이름이 아닌 숫자로 접근가능
// numbers.sorted{ $0 > $1 }
Class
class Shape {
var a = 10
func aaa() -> String {
return ...
}
// 생성자
init(name:String) {
self.name = name
}
}
var s = Shape()
// 접근
// s.a
// s.aaa()
// deinit 함수 : some clean-up 목적
- 상속
super class의 함수를 override 하려면 키워드 override 사용
super.init(name:name) {
- get, set
class B {
var perimeter : Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
// didSet, willSet 도 있음
}
}
enum
enum Rank : Int {
case ace = 1
case two, three, four, five
case jack, queen, king
func simpleDescription() -> String {
switch self {
case .ace :
return "Ace"
...
default :
return String(self.rawValue)
}
}
}
enum 의 생성자
if let convertedRank = Rank(rawValue: 3) {
Struct
struct 는 copied, class 는 referenced
Protocol
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
struct 안에서는 mutating 으로 받아 재정의, class 는 안 그래도 됨.
Extension
기존 타입에 함수 추가하는 방법
extension Int: ExampleProtocol {
var simpleDescription: String {
return "number"
}
mutating func adjust() {
...
}
}
// Int 에 함수와 변수가 추가됨
// 7.simpleDescription 으로 "number" 값 받을 수 있다.
Optional Binding
if let actualNumber = Int(possibleNumber) {
print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
print("The string \"\(possibleNumber)\" could not be converted to an integer")
}
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
}
}
// Prints "4 < 42 < 100"
Error Handling
enum PrintedError : Error {
case outOfPaper
case noToner
}
func send(job:Int, name:String) throw -> String {
if name == "Never" {
throw PrintedError.noToner
}
return "Job sent"
}
do ~ catch 로 try 해서 throw 를 받을 수 있다.
do {
let printerResp = try send(job:, name: "Shen")
print(printResp)
} catch {
print(error)
}
case처럼 에러마다 catch 사용 가능
catch PrintError.outOfPaper {
...
}
catch let printerError as PrinterError {
...
}
try? send(...
결과가 optional 이 된다. throw 받으면 무시되고 리턴값이 nil
defer
함수 안 다른 코드 다 실행되고 난 후(return 직전) 실행하라고
Generic
func makeArray<Item>(repeating item:Item, numberOfTimes:Int) ->[Item] {
...
}
public
weak
convenience int()
기본적으로 반드시 존재해야하는 init()에 보조적 역할을 하는 초기화함수 클래스 내의 변수를 초기화하면서 다시 init()을 호출할 때 사용한다.
class Person {
var name: String
var age: Int
var gender: String
init(name: String, age: Int, gender: String) {
self.name = name
self.age = age
self.gender = gender
}
convenience init(age: Int, gender: String) {
self.init(name: "zedd", age: age, gender: gender)
}
}
if let, guard let
//if let
func printName(){
var value:String?
value = "Lena"
print(value) // Optional("Lena")
if let name = value {
print(name) // "Lena"
}
//if문 안에서만 name 변수를 사용 가능.
}
//guard let
func printName(){
var value:String?
value = "Lena"
print(value) // Optional("Lena")
guard let name = value else { return }
print(name) // "Lena"
//name변수는 메소드 내에서 지역상수처럼 사용 가능.
}