Swift Language Guide: Basics
The Basics
서문
- 기존 개발에 사용되던 C와 Obj-C을 고려하여 유사점을 가지고 개발되었다
- 기존 언어C에 비해 Constant의 활용도가 높다 - for safer and clearer code
- 기존에 없던 튜플도 쓴다 (예시. 함수에서 여러 개 return 하기)
- Optional type이 등장.
- value가 없을 수 있음을 표현 (nil과 유사)
- Swift의 핵심 기능
- type-safe 언어이다 = 언어 자체가 개발자가 type을 명확히 파악하는데 도움을 준다 optional과 non-optional도 엄격히 구분
상수와 변수
- 선언
- 상수는 unchangeable, 변수는 changeable
- 값이 바뀌지 않으면 항상 상수로 선언할 것
- 한번에 여러 개를 선언할 수도 있다
var x = 0.0, y = 0.0, z = 0.0
- Type 명시
var welcomeMessage: String
var red, green, blue: Double
- 실제로는 Type 명시를 안해도 Swift가 initial value를 보고 적절히 부여한다
- 하지만, 선언시점에 initial value를 안 줄거면 Type 명시를 해야함
- 이름짓기
- any character가 가능하다. (대부분의 Unicode포함. 심지어 이모티콘같은 것도)
- 안되는 것 List
- 공백
- 수학기호 (+, *, - )
- 이상한 Unicode (private-use Unicode scalar values, or box-drawing)
- line-
- 숫자로 시작하면 안됨
- Swift의 reserved keyword를 사용하려면 백틱 ( ` ) 사용
var `class`: String = "aa"; print(`class`)
주석
- C랑 똑같다. 다만, nested로 써도 된다는 점이 다르긴 하다
// 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. */
세미콜론
- Swift는 세미콜론이 필요없다
- 물론 한 줄에 여러 statement를 쓰려면 구분을 위해 필요하긴 하다
let cat = "aaa"; print(cat)
정수
- 다른 언어와 같이 unsigned / signed가 있다 특별한 경우가 아니면, 심지어 non-negative더라도 signed로 통일하는걸 권장한다 Type 변환을 최대한 피하기 위함. 상호운용성(?)에 좋기 때문
- 8, 16, 32, 64 bit을 지원한다
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라고 사용하면 코드가 돌아가는 platform에 따라 Int32 혹은 Int64로 동작한다
Type safety / Type 추론
- 개발자가 사용하는 value의 Type들을 명확히 파악할 것을 요구하는 언어
- 그렇다고 모든 상수/변수에 type을 명시할 것을 요구하진 않음 (Swift 컴파일러가 코드 flow를 기반으로 Type 추론을 하기 때문)
- 비록 type-safe 언어이긴 하나 type이 명확한 경우 생략할 수 있다는 것도 Swift의 장점 중 하나임
- Type추론은 initial value가 있는 경우 특히 유용하다
- 가끔은 아래와 같이 무슨 타입인지 딱 짚진 않는(?) 리터럴(literal value)로 주어 행해진다
-
리터럴 : 소스코드에 무슨 값인지 보이는거
let meaningOfLife = 42
-
- 정수와 소수를 섞어 버리면 소수에 맞춰 Double로 추론
let anotherPi = 3 + 0.14159 // anotherPi is also inferred to be of type Double
숫자 표현 (Numeric Literals)
- 진법 표현
없음 → 10진법 0b ~ → 2진법 0o ~ → 8진법 0x ~ → 16진법let decimalInteger = 17 let binaryInteger = 0b10001 // 17 in binary notation let octalInteger = 0o21 // 17 in octal notation let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
-
Floating-Point
- 10진법 or 16진법만 사용가능
-
Exponential
- 10진법
- 1.25e2 == 1.25 x 10^2
- 1.25e-22 == 1.25 x 10^-2
- 16진법
- 0xFp2== 15 x 2^2
- 0xFp-22 == 15 x 2^-2
- 10진법
-
기타 가독성을 위한 특수문법
-
zero padding / 언더바
let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_1
-
Numeric 변환
- Integer를 표현할 땐 특별한 경우가 아니라면 상호운용성이 좋은 "Int"를 써라 (특별한 경우 : 성능, 메모리, 최적화, 코드에 명시적으로 표현하고 싶을 때 등)
- 정수 변환
- 변환예시
- 이런 변환 작업없이 바로 연산은 불가하다
let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one) SomeType(ofInitialValue)를 사용하면 "넣어주는 value"로 해당 Type의 initializer가 수행되며 새로운 인스턴스를 생성한다- "넣어주는 value"가 해당 Type의 initializer에서 수용가능한 Type이어야 한다
- 기존에 initializer가 구현되어 있지않은 Type을 변환하게 하려면 extension을 추가하는 방식으로 가능하다
- 이런 변환 작업없이 바로 연산은 불가하다
- 정수 ←→ 실수 간 변환
- 변환예시
let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine let integerPi = Int(pi)- 4.75 → 4
- -3.9 → -3.
- 참고사항
- Numeric 상/변수를 더하는 것과 리터럴을 더하는 것은 다름
- 상/변수로 이미 만들어진 것은 더할 때 Type check가 들어가지만 리터럴로 할 때는 아직 명시적인 type이 없기 때문에 먼저 더하고 Type 추론이 이루어진다
- Type 별명 설정
- 기존에 있던 Type의 이름을 달리 쓰고 싶다
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
- 경우에 따라 이런 표현이 가독성에 도움된다
Boolean
- 다른 언어의 bool과 동일하여 기본적인 설명은 skip
- if 문에 정수를 사용할 수 없다
let i = 1 if i { // 컴파일 에러 }
튜플
- 여러 value를 하나의 compound로 묶는 것
- 아무 type이나 사용가능하며 튜플 내 type을 통일할 필요도 없다
- 간단한 Data 묶음일 때 유용하고 complex하다면 class나 struct 사용을 권장
-
사용예시 - 선언
let http404Error = (404, "Not Found")- 여러 Type을 섞어 써도 된다
-
사용예시 - 값 추출
//값 추출 #1 let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") print("The status message is \(statusMessage)") //값 추출 #2 let (justTheStatusCode, _) = http404Error print("The status code is \(justTheStatusCode)") //값 추출 #3 print("The status code is \(http404Error.0)") print("The status message is \(http404Error.1)")- 굳이 뽑아내고 싶지 않은 값은 언더바 처리
- 바로 사용하려면 .0 혹은 .1 같은 숫자로 접근
-
사용예시 - Name을 부여할 수도 있다
let http200Status = (statusCode: 200, description: "OK") print("The status code is \(http200Status.statusCode)") print("The status message is \(http200Status.description)")
Optionals
- value가 존재하지 않을 수 있음을 인지시키기 위한 개념
- Objective-C에 "valid Object가 없음"을 뜻하는 nil return이 있지만 Obj에서 대해서만 쓸 수 있고 class, struct 등은 사용불가 (그래서 NSNotFound라는걸 사용하는데 일단 skip)
- 예시
-
정수 initializer 중 String → Int 변환자는 실패할 수 있으므로 optional을 return하도록 선언되어 있다
-
- nil
- value가 없는 상태를 표현하는 방법
- optional로 선언한 상/변수에만 사용할 수 있다
- optional로 선언한 상/변수에 초기값을 주지 않으면 nil로 초기화된다
- 참고로, Objective-C의 nil과는 다른 개념이다. (Obj-C에서는 존재하지 않는 오브젝트를 가리키는 '포인터'를 의미) (굳이 따지자면 C언어의 null과 유사한 듯하다. 단순히 값이 없음을 의미)
- 강제 unwrapping (with if문)
- if로 nil 검사 후 느낌표(!)로 과감히 까서 사용하는 기법이 있다
- nil 검사 안 했다가 nil을 느낌표로 까면 런타임 에러 발생
if convertedNumber != nil {
print("convertedNumber has an integer value of \(convertedNumber!).")
}
- Optional Binding (한국말로 뭘까)
- 느낌표처럼 unwrapping syntax가 명시적으로 존재하진 않지만 암묵적으로 수행된다
- 참고로, if let이든 if var이든 무관하다
- if 혹은 while 문에 아래 예시와 같이 작성하면 동작한다

if let actualNumber = Int(possibleNumber) { print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)") } else { print("The string \"\(possibleNumber)\" couldn't be converted to an integer") }
if let 구문의 의미는,
"Int(possibleNumber)에서 return되는 Optional Int 타입의 value가 존재하면 이를 unwrapping하여 actualNumber에 저장한다"
- 기타
- 한번에 여러개 Binding할 수도 있다
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") }
- if let 구문에서 선언한 상/변수는 if 중괄호 내에서만 사용가능하지만 guard let으로 선언하면 중괄호 밖에서도 (부모 함수 내에서) 사용 가능하다
- 암시적 Unwrapped Optionals
- 값이 코드끝까지 항상 존재함(=nil이 아님)을 이미 알고 있을 때 unwrap없이 바로 사용이 가능하도록 선언하는 방법
- class initialization에서 유용하다는데 일단 지금은 skip
- 선언 시점에 unwrap을 하는게 아니다. 사용 시점에 Optional로 사용될 수 있는 구문인지 먼저 check한 후에 불가하면 그제서야 unwrapping하는 구조로, 사용 시점에 그때그때 unwrapping이 발생한다
- 예시#1. unwrapping되는 경우
//일반 Optional let possibleString: String? = "An optional string." let forcedString: String = possibleString! // requires an exclamation point //암시적 Unwrapped Optionals let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // no need for an exclamation point - 예시#2. Optional인 그대로 사용되는 경우
let assumedString: String! = "An implicitly unwrapped optional string." //optionalString의 타입은 "String?"가 된다 let optionalString = assumedString //기본은 일반 Optional로 간주되므로 if let구문에도 사용가능 if let definiteString = assumedString { print(definiteString) }
Error Handling
- 예기치 않은 Error가 발생했을 때 그 내용을 파악하고 필요시 코드의 다른 부분으로 전달한다
-
Error를 던지는 함수임을 알림 - throws
-
Error가 발생할 수 있는 코드영역 - do
-
Error를 던지는(throw) 함수 - try
-
Error 발생 시 수행할 코드 - catch
func canThrowAnError() throws { // this function may or may not throw an error } do { try makeASandwich() eatASandwich() } catch SandwichError.outOfCleanDishes { washDishes() } catch SandwichError.missingIngredients(let ingredients) { buyGroceries(ingredients) } //parameter(ex. ingredients)를 넣어주면 error의 내용이 담긴다
Assertions and Preconditions
-
디버깅 목적으로 runtime 중에 어떤 확인 작업을 넣는 것
-
어떤 코드를 실행하기 전에 반드시 만족해야 하는 조건에 "예기치 않은" 문제가 있는지 확인절차를 넣을 수 있다.
-
명백히 일어나면 안되는 조건을 넣는 것이므로 복구같은 것 없이 app을 종료시킨다. 에러에 대한 예방책으로 동작하는게 아니다
-
이런 구문은 documentation 기능을 할 수도 있다
-
Assertions과 Preconditions의 차이는
-
Assertion은 Debug build에서만 동작
-
Precondition은 Debug + Product build 모두에서 동작
그러므로, 개발 중엔 Assertion을 막 써도 된다
-
- Assertion 예시
// assert(_:_:file:line:) let age = -3 assert(age >= 0, "A person's age can't be less than zero.") assert(age >= 0) //문구는 생략가능 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 { //이미 fail인게 확인되었으면 조건문없이 바로 assert assertionFailure("A person's age can't be less than zero.") }
- Precondition 예시
-
App을 종료시켜버리기 때문에 명백히 잘못일때만 사용할 것
// precondition(_:_:file:line:) precondition(index > 0, "Index must be greater than zero.") //이미 fail인게 확인되었으면 조건문없이 바로 precondition preconditionFailure("Index must be greater than zero.")
-
- compile 시 최적화 모드 중 unchecked mode (-Ounchecked) 사용 시 precondition이 동작하지 않는다 대신, fatalError(_:file:line:)를 사용하면 최적화와 무관하게 무조건 App 종료시키는데 미완성일 때 테스트용 정도로만 쓸만하다
Author And Source
이 문제에 관하여(Swift Language Guide: Basics), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yohanblessyou/Basics저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)