The Basic

Groot·2022년 6월 7일
0

Swift Language Guide

목록 보기
1/24
post-thumbnail

📌 Swift 란?

  • iOS, macOs, watchOS 앱 개발을 위한 새로운 프로그래밍 언어입니다. 하지만, C 및 Objective-C로 개발한 경험이 있다면 익숙함을 느낄 수 있습니다.
  • Swift는 type-safe 언어입니다. 그렇기 때문에 코드에서 사용할 수 있는 값의 유형을 명확하게 구분합니다.
  • 이러한 type-safety 한 성질은 개발 프로세스에서 가능한 한 빨리 오류를 포착하고 수정하는 데 도움이 됩니다.

📌 Constants and Variables

  • Constants: 초기화 후 변하지 않는 값을 설정 (let)
  • Variables: 초기화 후 변하는 값을 설정 (var)
  • Declaring Constants and Variables
    let maximumNumberOfLoginAttempts = 10
    var currentLoginAttempt = 0
    

코드에 저장된 값이 변경되지 않으면 항상 let 키워드를 사용하여 상수로 선언합니다. 변경할 수 있어야 하는 값을 저장하는 경우에만 변수를 사용합니다.


📌 Type Annotations

  • 상수 또는 변수가 저장할 수 있는 값의 종류를 명확히 할 수 있습니다.
    var currentLoginAttempt: Int = 0
    
  • currentLoginAttempt의 타입을 Int로 선언 -> 여기서 적어준 "Int" 가 Type Annotations 입니다.
  • 최종 변수 이름 뒤에 단일 유형 주석을 사용하여 쉼표로 구분하여 한 줄에 동일한 유형의 여러 관련 변수를 정의할 수 있습니다.
    var red, green, blue: Double
    

📌 Naming Constants and Variables

  • 상수 및 변수 이름에는 유니코드 문자를 포함하여 거의 모든 문자가 포함될 수 있습니다.
  • 상수 및 변수 이름에는 공백 문자, 수학 기호, 화살표, 전용 유니코드 스칼라 값 또는 선 및 상자 그리기 문자를 사용할 수 없습니다.
  • 숫자가 이름의 다른 곳에 포함될 수 있지만 숫자로 시작할 수도 없습니다.

📌 Printing Constants and Variables

  • print(_:separator:terminator:) 함수를 사용하여 상수 또는 변수의 현재 값을 인쇄할 수 있습니다.
    print(friendlyWelcome)
    // Prints "Bonjour!"
    
  • print(_:separator:terminator:) 함수는 Xcode의 "콘솔" 창에 출력을 인쇄합니다. 구분자 및 종결자 매개변수에는 기본값이 있으므로 이 함수를 호출할 때 생략할 수 있습니다.
  • string interpolation
    • 스위프트는 문자열 보간 방법을 사용해서 문자열 내에 상수나 변수를 포함 할 수 있습니다.

      print("The current value of friendlyWelcome is \\(friendlyWelcome)")
      // Prints "The current value of friendlyWelcome is Bonjour!"
      

📌 Comments

  • 주석을 이용해서 코드의 설명이나, 알림으로 포함할 수 있습니다.
  • 주석은 컴파일 될 때 무시됩니다.
  • 주석의 사용법
    // This is a comment.
    
    /* This is also a comment
    but is written over multiple lines. */
    
    /* This is the start of the first multiline comment.
     /* This is the second, nested multiline comment. */
    This is the end of the first multiline comment. */
    

📌 Semicolons

  • swift에선 기본적으로 Semicolons을 사용하지 않습니다.
  • 그러나 한 줄에 여러 개의 명령문을 작성하려면 세미콜론이 필요합니다.
    let cat = "🐱"; print(cat)
    // Prints "🐱"
    

📌 Integers

  • Swift는 8, 16, 32, 64비트 형식의 정수를 제공합니다.
  • Integer Bounds
    • min 및 max 속성을 사용하여 각 정수 유형의 최소값 및 최대값에 액세스할 수 있습니다.

      let minValue = UInt8.min
      // minValue is equal to 0, and is of type UInt8
      let maxValue = UInt8.max
      // maxValue is equal to 255, and is of type UInt8
      

Int

  • 32비트 플랫폼에서 Int는 Int32와 크기가 같습니다.
  • 64비트 플랫폼에서 Int는 Int64와 크기가 같습니다.
  • 32비트 플랫폼에서도 Int는 -2,147,483,648에서 2,147,483,647 사이의 모든 값을 저장할 수 있으며 많은 정수 범위에 대해 충분히 큽니다.

UInt

  • 부호없는 정수
  • 양의 정수를 표현하는데 사용

📌 Floating-Point Numbers

  • Double은 64비트 부동 소수점 숫자를 나타냅니다.
  • Float은 32비트 부동 소수점 숫자를 나타냅니다.

    Double의 정밀도는 최소 15자리 소수점 이하 자릿수인 반면 Float의 정밀도는 소수점 이하 6자리까지 가능합니다.
    두 유형 중 하나가 적절한 상황에서는 Double이 선호됩니다.


📌 Type Safety and Type Inference

  • Swift는 type-safe language입니다.
  • Swift는 유형이 안전하기 때문에 코드를 컴파일할 때 유형 검사를 수행하고 일치하지 않는 유형을 오류로 플래그 지정합니다.
  • 필요한 값의 유형을 지정하지 않으면 Swift는 유형 추론을 사용하여 적절한 유형을 계산합니다.
  • 초기화시점에 값을 지정해주면 따로 유형을 작성해주지 않아도 자동으로 유형을 정합니다.
let meaningOfLife = 42
// meaningOfLife is inferred to be of type Int

let pi = 3.14159
// pi is inferred to be of type Double

let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double

📌 Numeric Literals


📌 Numeric Type Conversion

  • 음수가 아닌 것으로 알려진 경우에도 코드의 모든 정수 유형의 상수 및 변수에 Int 유형을 사용합니다.
  • 일상적인 상황에서 기본 정수 유형을 사용한다는 것은 정수 유형의 상수와 변수가 코드에서 즉시 상호 운용이 가능하고 정수 리터럴 값에 대해 추론된 유형과 일치함을 의미합니다.
  • 다른 정수 유형(Int외)은 특별히 필요할 때만 사용하거나 성능, 메모리 사용 또는 기타 필요한 최적화를 위해 사용하십시오.

Integer Conversion

  • 정수 상수 또는 변수에 저장할 수 있는 숫자의 범위는 숫자 유형마다 다릅니다.
  • Int8 상수 또는 변수는 -128에서 127 사이의 숫자를 저장할 수 있는 반면 UInt8 상수 또는 변수는 0에서 255 사이의 숫자를 저장할 수 있습니다.
  • 크기가 지정된 정수 유형의 상수나 변수에 맞지 않는 숫자는 코드가 컴파일될 때 오류로 보고됩니다.
    let cannotBeNegative: UInt8 = -1
    // UInt8 can't store negative numbers, and so this will report an error
    let tooBig: Int8 = Int8.max + 1
    // Int8 can't store a number larger than its maximum value,
    // and so this will also report an error
    
  • 각 숫자 유형은 다른 범위의 값을 저장할 수 있으므로 사례별로 숫자 유형 변환을 선택해야 합니다.
  • 이 옵트인 접근 방식은 숨겨진 변환 오류를 방지하고 코드에서 형식 변환 의도를 명시적으로 만드는 데 도움이 됩니다.
  • 특정 숫자 유형을 다른 유형으로 변환하려면 원하는 유형의 새 숫자를 기존 값으로 초기화합니다.
  • 아래 예에서 상수 twoThousand는 UInt16 유형이고 상수 하나는 UInt8 유형입니다.
  • 같은 유형이 아니기 때문에 더하기를 할 수 없습니다. 대신 이 예제에서는 UInt16(one)을 이용해 값 1로 초기화된 새 로운 UInt16을 만들고 원본 대신 이 값을 사용합니다.
    let twoThousand: UInt16 = 2_000
    let one: UInt8 = 1
    let twoThousandAndOne = twoThousand + UInt16(one)
    
  • SomeType(ofInitialValue)은 Swift 유형의 이니셜라이저를 호출하고 초기 값을 전달하는 기본 방법입니다.

Integer and Floating-Point Conversion

  • 정수와 부동 소수점 숫자 유형 간의 변환은 명시적으로 이루어져야 합니다.
    let three = 3
    let pointOneFourOneFiveNine = 0.14159
    let pi = Double(three) + pointOneFourOneFiveNine
    // pi equals 3.14159, and is inferred to be of type Double
    
  • 여기서 상수 3의 값은 Double 유형의 새 값을 만드는 데 사용되므로 더하기의 양쪽이 동일한 유형이 되도록 합니다.
  • 부동 소수점에서 정수로의 변환도 명시해야 합니다. 정수 유형은 Double 또는 Float 값으로 초기화할 수 있습니다.
let integerPi = Int(pi)
// integerPi equals 3, and is inferred to be of type Int
  • 부동 소수점 값은 이러한 방식으로 새 정수 값을 초기화하는 데 사용할 때 항상 잘립니다. 이것은 4.75가 4가 되고 -3.9가 -3이 됨을 의미합니다.

📌 Type Aliases

  • 유형의 대체 이름을 정의합니다.
  • typealias 키워드를 사용하여 유형 별칭을 정의합니다.
typealias AudioSample = UInt16

var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound is now 0
  • typealias으로 선언해준 AudioSample는 UInt16의 별칭으로 사용됩니다. 그렇기 때문에 maxAmplitudeFound 값으로 UInt16의 최솟값 0이 초기화 됩니다.

📌 Booleans

  • true 및 false의 두 가지 값을 제공하는 타입입니다.
  • if 문과 같은 조건문으로 작업할 때 특히 유용합니다.
if turnipsAreDelicious {
    print("Mmm, tasty turnips!")
} else {
    print("Eww, turnips are horrible.")
}
// Prints "Eww, turnips are horrible."

📌 Tuples

  • 튜플은 여러 값을 단일 복합 값으로 그룹화합니다.
  • 튜플 내의 값은 모든 유형이 될 수 있으며 서로 동일한 유형일 필요는 없습니다.
    let nameAge = ("kim", 22)
    
  • 튜플이 정의될 때 튜플의 개별 요소 이름을 지정할 수 있습니다.
    let nameAge = (name: "kim", age: 22)
    print(nameAge.name)
    // Prints "kim"
    print(nameAge.age)
    // Prints 22
    

    튜플은 특히 함수의 반환 값으로 유용합니다. 웹 페이지 검색을 시도하는 함수는 페이지 검색의 성공 또는 실패를 설명하기 위해 (Int, String) 튜플 유형을 반환할 수 있습니다.

    튜플은 관련 값의 간단한 그룹에 유용합니다. 복잡한 데이터 구조 생성에는 적합하지 않습니다.
    데이터 구조가 더 복잡할 가능성이 있는 경우 튜플이 아닌 클래스 또는 구조로 모델링합니다.


📌Optionals

  • 값이 없을 수 있는 상황에서 사용합니다.
  • 두 가지의 가능성을 가지고 있습니다.
    • 값이 있고 해당 값에 액세스하기 위해선 옵셔널의 래핑을 풀어야 합니다.
    • 값이 전혀 없습니다. (nil)
  • 옵셔널의 선언 방법은 타입유형에 ?, ! 를 붙여 사용합니다.
  • nil
    • 변수를 값이 없는 상태로 설정합니다.

      var serverResponseCode: Int? = 404
      // serverResponseCode contains an actual Int value of 404
      serverResponseCode = nil
      // serverResponseCode now contains no value
      
  • 기본값을 제공하지 않고 optional을 정의하면 변수가 자동으로 nil로 설정됩니다.
    var surveyAnswer: String?
    // surveyAnswer is automatically set to nil
    

If Statements and Forced Unwrapping

  • if 문을 사용하여 옵셔널을 nil과 비교하여 옵셔널에 값이 포함되어 있는지 확인할 수 있습니다.
    let convertedNumber: Int? = 1
    if convertedNumber != nil {
        print("convertedNumber contains some integer value.")
    }
    // Prints "convertedNumber contains some integer value."
    

Forced Unwrapping

  • 옵셔널에 값이 포함되어 있다고 확신하면 느낌표(!)를 추가하여 기본 값에 액세스할 수 있습니다.

Optional Binding

  • 옵셔널 바인딩을 사용하여 옵셔널에 값이 포함되어 있는지 확인하고, 존재하면 해당 값을 임시 상수나 변수로 사용할 수 있도록 합니다.
  • 다음과 같이 if 문에 대한 선택적 바인딩을 작성합니다.
        if let 사용할상수이름 = 비교할 Optional  {
            동작내용
        }
    

    비교할 Optional의 값이 존재하면 그 값은 옵셔널 상태가 아닌 기본 상태로 사용할상수이름에 초기화 됩니다.
    동작내용에선 기본적으로 사용할상수이름을 이용한 동작을 구현합니다.
    if 문의 첫 번째 분기 내에서 사용할상수이름을 변경해야 하는 경우 if var 사용할상수이름으로 작성해서 변경이 가능합니다.

    • 쉼표로 구분하여 필요한 만큼 단일 if 문에 Optional Binding과 조건을 포함할 수 있습니다.
    • 다음 if 문은 동일합니다.
    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"
    

Implicitly Unwrapped Optionals

  • Optional 로 만들려는 유형 뒤에 물음표(?) 대신 느낌표(!)를 배치하여 암시적으로 래핑되지 않은 선택 항목을 작성합니다.
  • 옵셔널의 값이 존재하는 것으로 확인되고 그 이후의 모든 지점에 존재한다고 확실히 가정할 수 있을 때 유용합니다.
  • Swift에서 Implicitly Unwrapped Optionals은 클래스 초기화 과정에 주로 사용됩니다.
  • 옵셔널 값을 언래핑할 필요 없이 일반값처럼 사용할 수 있습니다.
    let possibleString: String? = "An optional string."
    let forcedString: String = possibleString! // 강제 추출
    let assumedString: String! = "An implicitly unwrapped optional string."
    let implicitString: String = assumedString // 암시적 추출
    

📌Error Handling

  • 오류 처리를 통해 실패의 근본 원인을 판별하고 필요한 경우 프로그램의 다른 부분에 오류를 전파할 수 있습니다.
    • 함수는 선언에 throw 키워드를 포함하여 오류를 throw할 수 있음을 나타냅니다.

      func canThrowAnError() throws {
          // this function may or may not throw an error
      }
      
    • Swift는 catch 절에 의해 처리될 때까지 오류를 현재 범위 밖으로 자동으로 전파합니다.

      do {
          try canThrowAnError()
          // no error was thrown
      } catch {
          // an error was thrown
      }
      

📌Assertions and Preconditions

  • Assertions and Preconditions은 런타임시에 실행하는 검사입니다.
  • 조건이 true로 평가되면 코드 실행이 되지만, 조건이 false로 평가되면 코드 실행을 멈추고 앱이 종료됩니다.
  • Assertions은 개발 중에 실수와 잘못된 예상조건을 찾는 데 도움이 되며 Preconditions은 프로덕션 문제를 감지하는 데 도움이 됩니다.
  • 위에서 설명한 Error Handling과 다르게 Assertions and Preconditions은 복구 가능하거나 예상되는 오류에 사용되지 않습니다.
  • Assertions and Preconditions이 실패하는 경우는 잘못된 프로그램 상태를 나타내므로 소스상에서 복구가 불가합니다.
  • 코드가 유효하지 않은 상태가 감지되는 즉시 실행을 중지하면 그로인한 인한 손상을 제한하는데 도움이 되기 때문에 Assertions and Preconditions을 사용합니다.
  • Assertions and Preconditions을 사용합니다.의 차이점은 확인 시점에 있습니다. Assertions 디버그 빌드에서만 확인되지만 Preconditions은 디버그 및 프로덕션 빌드 모두에서 확인됩니다. 프로덕션 빌드에서 Assertions 내부의 조건은 평가되지 않습니다. 즉, 프로덕션 성능에 영향을 주지 않고 개발 프로세스 중에 원하는 만큼 Assertions을 사용할 수 있습니다.

Debugging with Assertions

  • Swift 표준 라이브러리에서 assert(::file:line:) 함수를 호출하여 작성합니다.
    
    let age = -3
    assert(age >= 0, "A person's age can't be less than zero.")
    // age의 값은 -3으로 age >= 0 조건은 false가 되므로 프로그램은 A person's age can't be less than zero. 을 출력하며 종료됩니다.
    
    func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
    
  • 코드의 조건을 확인 한 경우엔 assertionFailure(_:file:line:) 함수를 사용하여 주장이 실패했음을 나타냅니다.
    if age > 10 {
        print("You can ride the roller-coaster or the ferris wheel.")
    } else if age >= 0 {
        print("You can ride the ferris wheel.")
    } else {
        assertionFailure("A person's age can't be less than zero.")
    }
    

Enforcing Preconditions

  • 조건이 거짓일 가능성이 있을 때마다 Preconditions을 사용하세요. 그러나 코드가 계속 실행되려면 반드시 참이어야 합니다.
  • 예를 들어, 값이 범위를 벗어나지 않았는지 확인하거나 함수에 유효한 값이 전달되었는지 확인하려면 Preconditions을 사용합니다.
  • precondition(::file:line:) 함수를 호출하여 Preconditions을 작성합니다.
    // In the implementation of a subscript...
    precondition(index > 0, "Index must be greater than zero.")
    
  • assertionFailure와 마찬가지로 preconditionFailure(_:file:line:)을 사용할 수 있습니다.
  • Parameters

    condition
    테스트할 조건입니다.조건은 playgrounds와 -Onone 빌드(Xcode의 디버그 구성에 대한 기본값)에서만 사용이 가능합니다.

    message
    조건이 false로 평가되는 경우 인쇄할 문자열입니다. 기본값은 빈 문자열입니다.

    file
    실패할 경우 메시지와 함께 인쇄할 파일 이름입니다. 기본값은 assert(::file:line:) or precondition(::file:line:) 가 호출되는 파일입니다.

    line
    실패할 경우 메시지와 함께 인쇄할 줄 번호입니다. 기본값은 assert(::file:line:) or precondition(::file:line:)가 호출되는 줄 번호입니다.

    unchecked 모드(-Ounchecked)로 컴파일하면 전제 조건이 확인되지 않습니다. 컴파일러는 전제 조건이 항상 참이라고 가정하고 그에 따라 코드를 최적화합니다.
    하지만, fatalError(_:file:line:) 함수는 최적화 설정에 관계없이 항상 실행을 중지합니다.

    프로토타이핑 및 초기 개발 중에 fatalError(_:file:line:) 함수를 사용하여 스텁 구현으로 fatalError("Unimplemented")를 작성하여 아직 구현되지 않은 기능에 대한 스텁을 만들 수 있습니다.
    치명적인 오류는 절대 최적화되지 않기 때문에 assertions or preconditionsd와 달리 스텁 구현이 발생하면 실행이 항상 중지됩니다

profile
I Am Groot

0개의 댓글