Swift 문법 정리


변수

  • 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변수는 메소드 내에서 지역상수처럼 사용 가능.
}

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다