이번엔 먼저 nil과 Optional, 반복문이나 함수 내에 _ 정의부터 하고 문법 포스팅을 하려 한다.
nil
Swift에서 nil은 우리가 흔히 사용한 언어 C나 Java, Javascript에서 사용한 null 대신 사용할 수 있지만 null 과는 조금 다르다.
null은 어떠한 값도 가지지 않다는 뜻이고, nil은 특정 타입에 대한 값의 부재를 표현하는 것이다.
Objective-c에서는 클래스 객체와 다른 포인터 자료형을 참조할 때 각각 다른 빈 포인터 값을 사용했지만, Swift에서는 아예 유저가 포인터를 통해 객체를 접근하는 것을 막음으로써 null은 필요 없어졌다.
헷갈리면 그냥 null 대신 nil 사용한다~ 라고 생각해도 무방하다.
nil은 Golang에서도 사용되고 있다.
Optional
Optional은 위에서 설명한 nil이 될 수 있는 변수의 타입을 뜻한다.
다음과 같이 타입에 ?가 붙지 않으면 name 변수는 nil값이 될 수 없는 타입이다.
let name: String = "ybchar"
하지만 response 결과에 따라 값이 생성될 필요가 있을 수 있다. 그래서 nil 상태도 지원이 되게 만들어야 한다.
다음과 같이 타입 옆에 ?를 붙이면 nil값을 가질 수 있다.
let location: String? = nil
_ (underscore)
먼저 함수 내에 underscore _는 보통 argument 앞에 특정 라벨을 붙일 것을 요구하는데 따로 라벨을 붙이지 않는데에 사용한다.
즉 no named라는 뜻이다.
func Person(_ name: String, _ hobby: String) -> String {
return "Hi My name is \(name), My hobby is \(hobby)"
}
print(Person("ybchar", "basketball"))
반복문 내에 underscore _는 따로 인덱스를 할당하지 않는다는 뜻이다.
// _는 i를 사용하지 않는다는 뜻으로 index값을 사용하지 않는 용도로 쓰면 된다.
for _ in 0..<25 {
let randomNumber = Int.random(in: 0...100)
randomInts.append(randomNumber);
}
print("random numbers : \(randomInts)");
Day4
// for 문
// 0에서 5
for i in 0...5 {
print("i: \(i)")
}
// 0에서 4
for i in 0..<5 {
print("< i: \(i)")
}
// 0에서 4까지 짝수
for i in 0..<5 where i % 2 == 0 {
print("짝수 i: \(i)")
}
var randomInts: [Int] = []
// _는 i를 사용하지 않는다는 뜻으로 index값을 사용하지 않는 용도로 쓰면 된다.
for _ in 0..<25 {
let randomNumber = Int.random(in: 0...100)
randomInts.append(randomNumber);
}
print("random numbers : \(randomInts)");
첫 for문은 i in 0...5 로 알고 있던 (i = 0; i <= 5; i++) 과 똑같은 코드다.
...으로 range를 설정하여 loop를 돌게 한다.
두 번째 for문은 (i = 0; i < 5; i++) 과 똑같은 코드다.
<5를 하여 5보다 작은 값을 가져오도록 하는 loop문이다.
세 번째 for문은 이전 포스팅 foreach 설명한 것처럼 똑같이 where 조건에 맞는 loop를 돌게 한다.
이번 Day4는 range 를 어떻게 표현하는 지가 핵심이다.
마지막 for문은 앞서 설명한 _를 사용한 for문이다.
따로 index i값이 필요없고 range 0~25번만 loop를 도는 코드이고 25번동안 0에서 100사이의 랜덤 숫자를 임시 배열 변수인
randomInts에 append 한다.
출력 결과
Day5
// Optional variable unwrapping
var someVariable : Int?
// 값이 nil이면 90을 넣는다.
if someVariable == nil {
someVariable = 90
}
// 값 존재 여부
if let otherVariable = someVariable {
print("var is not nil : \(otherVariable)" )
} else {
print("var is nil")
}
someVariable = nil
// someVariable 에 값이 있다면 기본값으로 10
let myValue = someVariable ?? 10
print("myValue : \(myValue)")
var emptyVariable : Int?
myFunction(parameter : myValue)
myFunction(parameter : emptyVariable)
func myFunction(parameter: Int?) {
print("myFunction() called")
// 값이 존재하지 않으면 return
guard let unWrappedParam = parameter else { return }
print("unWrappedParam: \(unWrappedParam)")
}
someVariable은 Optional 변수로 선언하여 값이 있는 지 없는 지 선언한다.
다음으로 if 문은 값이 비어있으면 90을 넣어준다.
그리고 다음 if문에 otherVariable 변수를 선언하여 someVariable을 할당하여 출력한다.
이 과정에 언래핑(unwrapping)이 들어가있는데 someVariable을 unwrapping 즉, 감싸져있는 것을 벗겨내어
다른 이름으로 할당하는 방법이다.
만약 벗겨낼 값이 없다면 else문을 실행할 것이다.
※ 여기서 하나 더 알려줄 것은 코드라인 7번째에 someVariable을 출력하면 "Optional(90)"이 출력된다.
즉, Optional로 wrapping되어 있다는 뜻인거다.
출력하면 아래 사진과 같이 90이 출력된다.
이후 nil로 할당하고, myValue는 someVariable이 nil이면 10을 넣겠다고 선언한다.
출력해보면 10이 출력된다.
Javascript로 비유하면 let myValue = someVariable === null ? 10 : someVariable 이렇게 된다.
다음으로 emptyVariable를 Int Optional로 선언해보았다.
그리고 myFunction(parameter: myValue), myFunction(parameter: myValue) 두 가지를 실행하였다.
그러면 myFunction 함수를 선언해야 하므로, myFunction은 Optional Int로 파라미터를 인자로 선언하고,
guard let 변수로 만약 값이 있으면 unwrapping하여 할당하고, 없으면 return 시킨다.
출력 내용
Day6
// class와 struct의 차이
// memberwise initializer 때문에 좋다.
// 생성자를 만들지 않아도 된다. struct가 만들어준다.
struct youtuberStruct {
var name : String
var subscribersCount: Int
}
let devCha = youtuberStruct(name: "ybchar", subscribersCount: 2396)
var devChaClone = devCha
print("devJeongClone name: \(devChaClone.name)")
devChaClone.name = "kane"
// 값이 복사이기 때문에 둘의 값이 다르다.
print("struct - devChaClone.name: \(devChaClone.name)") // kane
print("struct - devCha.name: \(devCha.name)") // ybchar
class youtuber {
var name: String
var subscribersCount: Int
// init으로 매개변수 가진 생성자 메소드를 만들어야 매개변수 넣고 객체 생성가능하다.
init(name: String, subscribersCount: Int){
self.name = name
self.subscribersCount = subscribersCount
}
}
var ybchar = youtuber(name: "ybchar", subscribersCount: 2396)
var me = ybchar
print("class - me.name : \(me.name)")
me.name = "kane"
// 서로 연결되어 있기에 (참조) 둘 다 값이 같다.
print("class - me.name : \(me.name)") // kane
print("class - ybchar.name : \(ybchar.name)") // kane
일단 struct, 구조체는 각 데이터를 담는 덩어리라고 생각하면 된다.
이 덩어리에 name, subscribersCount (이름, 구독자 수) 변수를 정의하고 묶는 것이다.
devCha라는 변수를 선언하고 이름과 구독자 수를 정의하여 메모리에 저장한다.
그리고 devChaClone으로 새로 선언한 다음, 이름을 새로 정의한다.
그러면 출력 내용으로 Clone 변수는 kane이 들어가고 원래 devCha는 그대로 ybchar 이름이 출력될 것이다.
즉, Clone 구조체는 새로 정의된 구조체이고, 그 구조체에만 값을 변경한 것일 뿐이다.
다음으로 youtuber라는 클래스를 정의해보았다.
클래스는 struct, 구조체와 조금 다르다.
코드를 보면 값을 똑같이 정의해보고, 여기에 생성자(init)를 정의하는 데 메모리에 올린다는 뜻이다.
메모리에 올릴려면 값을 정의하여 메모리에 정의하고 init으로 메모리에 올리는 것이다.
그리고 똑같이 ybchar를 선언하고 이름과 구독자 수를 정의한다.
다음으로 me라는 변수에 ybchar를 할당을 해본다.
그리고 me.name에 kane이라는 이름을 새로 정의하고 출력해보면
kane이 나오고 ybchar.name을 출력해보면 똑같이 kane이 나온다.
즉, 클래스는 서로 연결되어 있고, me는 클래스를 참조하는 것일 뿐이며, sync가 된다는 것이다.
출력 내용
출처: https://medium.com/@codenamehong/swift-underscore-90dcbec5072f
'iOS > Swift 문법' 카테고리의 다른 글
Swift 기초 문법 - 클로저 (2) (1) | 2022.09.29 |
---|---|
Swift 기초 문법 - 클로저 (1) (0) | 2022.09.28 |
Swift 기초 문법 - 프로퍼티 옵저버, 함수 매개변수, 제네릭 (0) | 2022.09.20 |
Swift 기초 문법 - 조건문, forEach 반복문, enum case (2) | 2022.09.01 |