Swift | The Basic (기본)
상수와 변수 선언
1. 상수와 변수의 정의
- 상수(let)
- 상수의 값은 최초 지정 후 변경이 불가능
- 변수(var)
- 변수의 경우 다른 값으로 변경이 가능
//상수 선언 후 값을 변경할 수 없다
let maximuimNumberOfLoginAttemps = 10
//만약 이런식으로 변경할 시 오류가 남
//maximuimNumberOfLoginAttemps = 20
//변수는 선언 후 값을 변경할 수 있다
var currentLoginAttempt = 0
2. 상수와 변수를 선언할 때 콤마로 구분하여 한 줄로 선언이 가능
//반드시 초기에 초기화를 해야함
//초기화를 하지 않을시 오류남
//만약 타입 명시를 할 시, 초기화를 하지 않아도됨
//but 초기화 하지 않은 값을 호출할 시 오류가 나게됨
var number3 = 0 , number4 = 0, number5 = 0
let number6 = 0, number7 = 0, number9 = 0
⚠️ 코드에서 저장한 값이 변경되지 않는다면 항상 let 키워드를 선언
타입명시
- 타입 명시 사용 이유 및 특징
- 상수 또는 변수를 선언할 때 저장할 수 있는 값의 종류를 명확하게 하기 위해 타입 명시를 제공
- 같은 타입에 여러개의 연관된 변수를 콤마로 변수 이름을 구분하고 마지막에 타입 명시를 통해 한줄 선언
💡 실제로 타입 명시가 필요한 경우는 드뭅 변수를 선언할 때 초기값을 지정하면 타입추론 가능var number: Int var number10: Int = 10 var message: String var message1 = "hello" //연관된 변수를 콤마로 이름을 구분하고 마지막에 타입 명시로 통해 한 줄 선언이 가능한 예 var red, gree, purple, black: String red = "red"
상수와 변수의 이름
- 특정 타입으로 상수 또는 변수 선언하면 동일한 이름으로 다시 선언하거나 다른 타입의 값을 저장하도록 변경하여 선언할 수 없음.
- 상수→ 변수 ❌
- 변수→ 상수 ❌
- 동일한 타입의 다른 값으로 이미 선언된 변수의 값을 변경할 수 있음
- 변수와 달리 상수 값은 지정된 이후에는 변경할 수 없음
//변수의 경우 값의 변경이 가능함
var message: String
message = "hello"
message = "bye"
//상수의 경우 값의 변경이 불가능함
//만약 변경하려고 하면 코드가 컴파일 때 오류가 발생함
let red = "red"
//this is compile error
red = "realRed"
- 상수와 변수 이름은 유니코드 문자를 포함하여 대부분의 문자를 포함할 수 있다
- 안되는 경우 : 공백, 수학적 기호, 화살표, 내부에서 사용하는 유니코드 스칼라값, 선과 박스 그리는 문자
let n = 3.14159 let 你好 = "你好世界" let 🐶🐮 = "dogcow"
상수와 변수 출력
- print 함수로 상수 또는 변수의 현재 값을 출력할 수 있음
⚡ print(:seperator:terminator:)
print(message)
💡 만약 줄바꿈없이 값을 출력하려면 ❓
⇒ print(someValue, terminator: "")
긴 문자열에 상수 또는 변수 이름을 포함하여 문자열 삽입 방법
print(”\(red) is beautiful color”)
주석
//한줄 주석
/*
여러줄 주석
*/
세미콜론
- swift에서 세미콜론(;)은 필수조건이 아님
- 여러 구문을 한줄로 작성할 경우 세미콜론은 필수로 작성되어야함
let cat = "mow"
print(cat)
정수 Int
- 정수의 뜻
- 분수가 아닌 전체 숫자
- signed ⇒ 부호가 있는 정수(양수, 0, 음수)
- unsigned ⇒ 부호가 없는 정수 (양수 ,음수)
- 정수 범위
- min, max property를 통해 각 정수의 최소값과 최대값을 가질 수 있음
let minValue = Int.min // -9,223,372,036,854,775,808 let maxValue = Int.max // 9,223,372,036,854,775,807 let minUValue = UInt8.min //0 let maxUValue = UInt8.max //255 let maxInt64bit = Int64.max //9,223,372,036,854,775,807 let maxInt32bit = Int32.max // 2,147,483,647 - Int
- 32-bit 플랫폼 : Int32
- 64-bit 플랫폼 : Int64
💡 32-bit 플랫폼에서도 Int 는 -2,147,483,648 과 2,147,483,647 사이의 값을 저장할 수 있으며 일반적인 사용성에 문제가 없습니다.
- UInt
- 64-bit 플랫폼 : UInt64
- 32-bit 플랫폼 : UInt32
부동 소수점 숫자
- 분수 성분을 가진 숫자
- Double → 64-bit 부동 소수점 숫자 표기
- Float → 32-bit 부동 소수점 숫자를 표기
💡 Double 15자리 소수점 정확도 Float 6자리 소수점 정확도
타입 세이프티와 타입 추론
var piNum = 0.14159
// 정수 + Double
let anotherPi = 3 + 0.14159 //Double 형으로 알아서 인식함
숫자 리터럴
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation(2진수)
let octalInteger = 0o21 // 17 in octal notation(8진수)
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation(16진수)
숫자타입변환
- 명시적으로 크기가 지정된 데이터 또는 성능, 메모리 사용, 또는 다른 성능 최적화를 위한 경우에만 다른 정수 타입을 사용함
- 명시적으로 크기의 타입을 사용하면 실수로 인한 값 초과를 포착하고 사용중인 데이터의 특성을 알 수 있음
- 정수변환
- Int8 : -128 과 127 사이의 숫자를 지정할 수 있음
- UInt8 0 과 255 사이의 숫자를 저장할 수 있음
//크기가 지정된 정수 타입의 상수 또는 변수에 맞지않는 숫자 작성
//컴파일 시에 오류 발생
let cannotBeNegative: UInt8 = -1
// UInt8 cannot store negative numbers, and so this will report an error
let tooBig: Int8 = Int8.max + 1
// Int8 cannot store a number larger than its maximum value,
// and so this will also report an error
//데이터 타입이 다른 값을 더하려면?
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
- 정수와 부동 소수점 변환
- 명시적으로 변환해야함
//three = Doulbe type으로 명시적 변환을 해야 소수점 상수와 덧셈이 가능함
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi equals 3.14159, and is inferred to be of type Double
//만약 Double형인 pointOneFourOneFiveNine를 Int형으로 변환하고 싶다면?
Int(pointOneFourOneFiveNine) //print = 0으로 나옴
타입별칭(Type Aliases)
💡 이미 존재하는 타입을 다른 이름으로 정의하고 키워드를 사용하여 정의할 수 있습니다
typealias AudioSample = UInt16
부울(Booleans)
- 참 거짓을 제공함
- let orangesAreOrange = true let turnipsAreDelicious = false var isTure = true isTrue = false
- if 구문과 같은 조건문으로 동작할 때 특히 유용
- if turnipsAreDelicious { print("Mmm, tasty turnips!") } else { print("Eww, turnips are horrible.") } // Prints "Eww, turnips are horrible."
- 비교 결과는 Bool type
//예제1
//비교하는 대상이 없기에 컴파일시 에러를 발생함
let i = 1
if i {
}
//예제2
//비교하는 대상이 있을 시 에러를 발생하지 않음
if i == 1{}
if i != 1{}
튜플(Tuples)
여러값을 단일 복합 값으로 그룹화 합니다. 튜플안에 값은 어떠한 타입도 가능하며 서로 같은 타입일 필요는 없다.
- 튜플의 내용을 별도의 상수 또는 변수로 분해하여 평소와 같이 접근이 가능
- 튜플의 값 중 일부만 필요한 경우 튜플을 분해할 때 밑줄(_)로 튜플의 일부를 무시가능
- 배열처럼 튜플의 개별 요소 값에 접근할 수 있음
- 튜플을 정의할 때 각 요소마다 이름을 정의할 수 있음
- 튜플 요소에 이름이 있다면 요소의 값에 요소 이름으로 접근이 가능
//튜플
var name : String = "name"
var adress : String = "adress"
var phoneNumber = 96710056
let http404Error = (404, "Not Found")
let loginSuccess = ("loginSuccess", name, adress, phoneNumber)
//변수로 분해하여 평소와 같이 접근이 가능함
let (statusCode, statusMessage) = http404Error
print("the status code is \\(statusCode)")
print("the status message is \\(statusMessage)")
//튜플의 값 중 일부만 필요한 경우 튜플을 분해할 때 밑줄로 튜플의 일부를 무시할 수 있음
let (justNeedStatusCodee, _) = http404Error
print("status code is \\(justNeedStatusCodee)") //404
//인덱스로 접근 가능
http404Error.0
http404Error.1
let http200Status = (statusCode: 200, description: "OK")
http200Status.statusCode
http200Status.description
💡 튜플은 관련된 값의 간단한 그룹에 유용 복잡한 데이터 구조를 생성하는데 맞지 않음 데이터 구조가 복잡한 경우 클래스나 구조체를 사용
옵셔널(Optionals)
값이 없는 경우에 옵셔널을 사용하는데 옵셔널은 2가지 기능성이 있다
- 지정된 타입의 값이 있고 옵셔널을 풀어서 값에 접근
- 값이 없을 수 도 있다(nil)
- nil의 정의
- Objective-C 객체가 존재하지 않는 포인터
- Swift 포인터가 아님 그저 특정 타입의 값이 없다는 의미
let possibleNumber = "123"
//Int가 옵셔널로 정의됨
//현재 possibleNumber가 초기화 실패할 수도 있기 때문에 옵셔널 타입으로 들어가게됨
let convertedNumber = Int(possibleNumber)
// The type of convertedNumber is "optional Int"
nil
- 값이 없는 상태를 나타낼 수 있습니다
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
//기본값이 없이 정의만 하게될 때 자동적으로 nil로 설정
var survayAnswer: String?
- if 구문은 옵셔널 nil을 비교하여 옵셔널 값이 포함되어있는지 확인 가능
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
if convertedNumber != nil {
print("convertedNumber contains some integer value.")
}
// Prints "convertedNumber contains some integer value."
💡 옵셔널이 아닌 상수 / 변수 에서는 nil을 사용할 수 없음 코드에서 상수 또는 변수가 특정 조건에서 값이 없이 동작하려면
적절한 타입의 옵셔널 값을 선언해야함 옵셔널이 아닌 값에 nil을 할당하면 컴파일 오류가 발생
- 값이 없을 때(nil) 수행할 수 있는 작업
- ! 연산자를 사용해서 프로그램을 멈춤
- ?? 연산자를 사용해 대체값을 제공
- nil을 반환하거나 옵셔널 체이닝에서 설명한 ?. 연산자를 사용하여 nil값을 전파
- 값이 nil일 때 해당값에 대한 동작을 건너뜀
옵셔널 바인딩 (Optional Binding)
옵셔널 값을 포함하고 있는지 확인하고 값이 있는 경우 해당 값을 임시 상수 또는 변수로 사용할 수 있게 해줌
옵셔널 바인딩은 if, guard, while 구문에서 옵셔널에 값이 있는지 체크하고 단일 동작의 일부로 상수 또는 변수로 추출할 수 있음
- if구문에서 옵셔널 바인딩
if let <#constantName#> = <#someOptional#> {
<#statements#>
}
let possibleNumber = "123"
//optional type
//값에 접근한 후에 기존 옵셔널 상수 또는 변수를 참조할 필요가 없다면 같은 이름으로 새로운 상수 또는 변수를 사용가능
if let actualNum = Int(possibleNumber) {
print("possibleNumber : \\(possibleNumber)")
} else {
print("possibleNumber could not be converted to an integer : \\(possibleNumber)")
}
//mynumber 값의 유무부터 확인
//만약 값이 있다면 myNumber라는 상수에 설정
//if 구문 안에서 myNumber은 옵셔널이 아닌 상수를 참조
let myNumber = Int(possibleNumber)
//언래핑 하는데 더 짧게 사용 가능
//언래핑할 상수 또는 변수의 이름만 작성
//언래핑된 새로운 상수 또는 변수는 암시적으로 같은 이름의 옵셔널 값을 사용
if let myNumber = myNumber {
print("my number is \\(myNumber)")
}
if let myNumber {
print("My number is \\(myNumber)")
}
//if 구문에서 옵셔널 바인딩으로 생서된 상수와 변수는 if구문의 본문내에서만 사용 가능
//, 를 통해서도 사용이 가능함
if let firstNumber = Int("4"), let secondNumber = Int("42"),
fistNumber < secondNumber && secondNumber < 100 {
print("\\(firstNumber) < \\(secondNumber) < 100 ")
}
//4 < 42 < 100
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\\(firstNumber) < \\(secondNumber) < 100 ")
}
}
}
//4 < 42 < 100
대체값 제공(Providing a Fallback Value)
누락된 값을 처리하는 다른 방법은 nil-결합연산자 (??) 사용하여 기본값을 제공하는 방법
옵셔널에서 ??의 왼편이 nil이 아니면 값이 언래핑되고 사용 그렇지 않으면 ?? 오른편에 값이 사용
//대체값 사용
//??
//옵셔널에 ??의 왼편이 nil이 아니면 값이 언래핑되고 사용
//그렇지 않으면 ?? 오른편에 값이 사용
let name: String? = nil
let greeting = "hello" + (name ?? "friend") + "!"
print(greeting) //"hello, friend"
강제 언래핑(Force Unwrapping)
- 프로그래머의 에러 또는 원치않는 상태와 같은 실패를 nil로 표현하려면 옵셔널의 이름 뒤에 !추가
- nil값을 강제 언래핑하면 런타임 에러가 발생하기 때문에 잘 사용해야함
//강제 언래핑
//!
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let number = convertedNumber!
guard let number = convertedNumber else {
fatalError("the number was invalid")
}
암시적으로 언래핑된 옵셔널(Implicity Unwrapped Optionals)
//암시적으로 언래핑된 옵셔널
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // Requires explicit unwrapping
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // Unwrapped automatically
let optionalString = assumedString
// The type of optionalString is "String?" and assumedString isn't force-unwrapped.
//"An implicitly unwrapped optional string."
if assumedString != nul {
print(assumedStinrg!)
}
//"An implicitly unwrapped optional string."
if let definiteString = assumedStinrg {
print(definiteString)
}
에러 처리
- 값의 유무를 사용하여 함수의 성공 또는 실패를 전달할 수 있는 옵셔널과 달리 에러 처리를 사용하면 에러 원인을 판별하고 필요한 경우 에러를 프로그램의 다른 부분으로 전달할 수 있음
- 함수에 에러조건이 되면 에러 발생하고 해당 함수의 호출자는 에러를 포착하고 적절하게 응답 가능
출처 : https://bbiguduk.gitbook.io/swift/language-guide-1/the-basics