Search
Duplicate

Swift Deep Dive

Resources in Swift

1) Variables

var a = 5 // 변수
Swift
복사
특정 DataType으로 지정하고 싶으면 아래와 같이 사용할 수 있다.
이때 DataType의 모든 앞글자는 대문자이다!
var data: Int = 1234
Swift
복사
option + click 을 통해서 DataType을 알 수 있다

2) Constants

let a = 3 // 상수
Swift
복사

3) Commenting

// single line commenting /* multi line commenting */
Swift
복사

4) Range Convention

a...b -> Closed Range a..<b -> Half Open Range ...b -> One Sided Range
Swift
복사

5) Optionals

Swift를 공부하다보면 특정 타입 뒤에 ? 혹은 !가 따라 나오는 것을 볼 수 있다. 이 때, 이 기호들이 바로 Optional정보를 나타낸다.
DataType <var hardness: String?> Optional
Swift
복사
Swift는 DataType을 가진 기본 변수에 nil(C로 치면 null)을 넣을 수 없다. 생각해보면 맞는 말이다. nil은 String이라고 할 수 없기 때문... 즉, Optional이 해주는 역할은 아래와 같다
이 변수에는 값이 있을 수도, 없을 수도 있다!
그래서 Swift에서는 타입 뒤에? 를 붙이면서 값이 없을 수도 있다는 상황을 알려주는 것이다.

Example

var player1Username: String = nil // error var player1Username: String? = nil // OK var player1Username: String? // OK (위와 동일) player1Username = "username"
Swift
복사
만약 위 변수를 그냥 출력하면 아래와 같은 결과를 얻을 수 있다.
print(player1Username)
Swift
복사
우리가 원하는 결과는 "username"인데 Optional() 이라는 블록 안에 값이 나오고 있다. 왜 이런 결과가 생기는 걸까?

Wrapping

그 이유는 바로 Wrapping이다. Optional 타입은 기본적으로 wrap되어 있는 이다. 즉, Optional로 선언된 변수들은 값이 있는 것인지, nil인 것인지 wrap되어 있어서 모르는 상태이다. 그렇기 때문에(컴파일러 입장에서는 변수가 nil일 수도 있기 때문에) wrap된 상태에서는 설령 변수에 value값이 있다고 하더라도 바로 value가 출력되지 않는다.(Swift 3.0에서 반영된 사항) 
var optionalString: String? =Helloprint(optionalString) // 출력 결과: Optional(“Hello”)
Swift
복사
이 경우, optionalString이 nil일 수도 있기 때문에, 결과값 “Hello”가 출력되지 않고, Optional(“Hello”) 가 콘솔창에 출력된다.

그렇다면 그냥 원하는 값만 출력하려면 어떻게 해야할까?

방법은 간단하다 바로 Forced Unwrapping을 사용하는 것이다.
print(optionalString!)> Forced Unwrapping
Swift
복사
이 때, optionalString이 nil이면 error가 날 수 있다. 따라서 if문을 통해 안전한 프로그래밍을 하는 것을 추천한다.
if optionalString != nil{ print(optionalString!) }
Swift
복사

5 - 1) Optional Binding, Chaining, and the Nil Coalescing Operator

항상 새로 선언할 때마다 !붙여야함.. 불편
1.
optional binding
if let saefOptional = optional { safeOptional }
C
복사
2. nil coalescing operatior
optional ?? defalutValue let text: String = myOptional ?? "i am default"
C
복사
optional class or struct?
3. optional chaining
nil이 아닐때만 실행해라!
optional?.property optional?.method()
C
복사

6) Null? Nil? 무엇이 다를까?

스위프트를 하다보면 null이 아니라 nil을 사용하는 것을 바로 눈치챌 수 있을 것이다. 처음에는 똑같은 표현을 표기만 다르게 해서 쓰나보다 하고 생각하다가 갑자기 궁금해져서 찾아보게 되었다.
간단하게 말하면, 원래 Objective-C 에서 null과 nil을 따로 사용하면서 그 잔재로 생긴 것이라고 한다. swift에서는 포인터의 개념이 없기 때문에 nil만 가져온 것이라고..(obc에서 null은 포인터의 부재를 나타낸다)
즉, Swift에서의 nil은 포인터가 아니라 특정 타입에 대한 값의 부재를 나타내는 것이다.

7) Immutability!!

let : immutable
var : mutable
struct inside : immutable
// error!!! let name: String var citizens: [String] var resources: [String: Int] ... func harvestRice() { resources["Rice"] = 100 } }
Swift
복사
// OK!! can change state of struct mutating func harvestRice() { resources["Rice"] = 100 }
Swift
복사
struct outside : mutable

Type in Swift

1) String

"This is text!!"
Swift
복사

string concatenation

let password = "a" + "b"
Swift
복사

2) Int

정수 타입, 64비트 정수형
var intValue: Int = 100 var intValue: Int = 100.1 // error!
Swift
복사

2 - 1) UInt

양의 정수 타입, 64비트 양의 정수형
var uintValue: UInt = 100 var uintValue: UInt = -100 // error!
Swift
복사

3) Double

실수 타입, 64비트 부동 소수형
var doubleValue: Double = 3.14
Swift
복사

4) Float

실수 타입, 32비트 부동 소수형
var floatValue: Float = 3.14
Swift
복사

5) Bool

true와 false만을 값으로 가지는 타입
var boolValue: Bool = true var boolValue: Bool = false boolValue = 0 // error! boolValue = 1 // error!
Swift
복사

Data Structure in Swift

1) Array

var name = [data, data, data ... ][num]
Swift
복사
var numbers = [45, 73, 195, 53] var computedNumbers = numbers for i in 0...3{ print(computedNumbers[i]) }
Swift
복사

2) Dictionary

var dict = ["key1" : val1, "key2" : val2] var dict : [String : Int ] = ["String" : Int, "String" : Int]
Swift
복사

3) Struct

struct Town{ let name = "42land" var citizens = ["4", "2"] var resources = ["Test" : 100, "Subject" : 42, "Cadet" : 1000] }
Swift
복사
init 함수 사용해서 struct initialize!
import UIKit struct Town{ let name: String var citizens: [String] var resources: [String: Int] init(townName: String, people: [String], stats: [String: Int]) { name = townName citizens = people resources = stats } func fortify() { print("Defences increased!") } } var anotherTown = Town(townName: "SU", people: ["1","2"], stats: ["coconuts": 100]) anotherTown.citizens.append("3") print(anotherTown.citizens)
C
복사
self 키워드로 구조체 내부 변수 나타내기
struct Town{ let name: String var citizens: [String] var resources: [String: Int] init(name: String, citizens: [String], resources: [String: Int]) { self.name = name self.citizens = citizens self.resources = resources } func fortify() { print("Defences increased!") } }
C
복사

4) Classes

클래스 생성할 때에는 무조건 파일 이름과 동일하게 지어야 한다.

5) Struct vs Classes

struct : unable to inherit
클래스는 무조건 init함수가 있어야한다.
class Enemy { var health: Int init(health: Int) { self.health = health } }
Swift
복사
클래스는 래퍼런스가 복사된다.
// 두개의 다른 객체 생성 let ske1 = Enemy(health: 100, attackStregth: 10) let ske2 = Enemy(health: 100, attackStregth: 10) // 하나의 객체에 두 개의 변수가 참조 let ske1 = Enemy(health: 100, attackStregth: 10) let ske2 = ske2
Swift
복사
생성자를 따로 써야 다시 만들어짐!!!
구조체는?
let -> 변경불가능 but 구조체는 완전히 복사됨
Swift
복사
struct : passed by value, immutable
class : passed by reference, mutable, inheritance

Structures vs Classes

Swift를 공부하면서 struct를 쓰는 것을 보고 조금 의아했다. class가 있는데 굳이 struct를 사용해야하나? 처음 사용법을 배우면서도 너무나도 비슷한 활용법에 의문을 품어서 대체 왜 struct와 class를 나눠서 사용하는지 찾아보았다.
이 포스트는 Apple의 Swift Documents를 보고 작성하였습니다

Comparing Structures and Classes

Both can:

Define properties to store values
Define methods to provide functionality
Define subscripts to provide access to their values using subscript syntax
Define initializers to set up their initial state
Be extended to expand their functionality beyond a default implementation
Conform to protocols to provide standard functionality of a certain kind
각각의 기능들에 대한 추가적인 설명은 아래 페이지에서 볼 수 있다.

Classes can:

class가 struct보다 더 많은 기능을 담고있기 때문에, class가 어떤 것을 더 할 수 있는지 알아보자.
Inheritance enables one class to inherit the characteristics of another.
Type casting enables you to check and interpret the type of a class instance at runtime.
Deinitializers enable an instance of a class to free up any resources it has assigned.
Reference counting allows more than one reference to a class instance.
각각의 기능들에 대한 추가적인 설명은 아래 페이지에서 볼 수 있다.
Apple공식 문서에서 두 구조 중 하나를 고르는 기준을 간단하게 정의해 두었다.
The additional capabilities that classes support come at the cost of increased complexity. As a general guideline, prefer structures because they’re easier to reason about, and use classes when they’re appropriate or necessary.
일반적인 상황에서는(특별히 복잡한 기능이 필요없는) struct를 사용하는 것을 권장하고, 만약 필요하다면 class를 사용하라고 나와있다. 아무래도 class는 추가적인 기능이 많기 때문에 많은 코드들을 담는 프로젝트에서 무분별한 사용보다는 필요한 상황에 적절히 사용하는게 좋은 것 같다.

Definition Syntax

이제 각각 어떻게 선언하는지 살펴보자
// structures struct SomeStructure { // Do Something } // classes class SomeClasses: SomeParentsClasses { // Do Something }
Swift
복사
Whenever you define a new structure or class, you define a new Swift type. Give types UpperCamelCase names (such as SomeStructure and SomeClass here) to match the capitalization of standard Swift types (such as String, Int, and Bool). Give properties and methods lowerCamelCase names (such as frameRate and incrementCount) to differentiate them from type names.
이 때, type은 uppercamelcase로, 속성이나 메서드는 lowercamelcase로 적는 것을 규칙으로 한다. 또한 struct, class의 이름은 되도록이면 파일의 이름과 동일하게 만든다.
ex. Student.swift → class Student

Structure and Class Instances

선언한 구조들의 객체는 아래와 같이 생성할 수 있다.
let someStruct = SomeStructure() let someClass = SomeClasses()
Swift
복사

Structures and Enumerations Are Value Types

A value type is a type whose value is copied when it’s assigned to a variable or constant, or when it’s passed to a function.
C++을 공부하다보면 Call by Value, Call by Reference와 같은 것을 자주 볼 수 있다. 해당 개념을 익히고 있다면 아래 부분을 어렵지 않게 이해할 수 있을 것이다.
Swift의 structures는 Value Type이다. 간단하게 예시를 통해서 살펴보자. 우선 BoxSize라는 struct를 만들었다. BoxSize는 height와 width를 가지고 있다. Main에서 BoxSize의 instance를 생성해 hd라는 변수에 담아보자.
struct BoxSize { var height: Int = 1080 var width = 1920 // 타입을 생략하면 타입추론을 해준다 }
Swift
복사
// in Main var hd = BoxSize() print("height = \(hd.height)") print("width = \(hd.width)")
Swift
복사
이 때, hd는 BoxSize로 생성한 객체이기 때문에 height와 width를 고정적으로 가지고 태어난다.
이제 우리는 여기서 cinema라는 객체를 만들어서 hd를 복사해보자. 그리고 cinema의 width property를 2048로 수정해보자
// in Main ... var cinema = hd cinema.width = 2048
Swift
복사
결과를 보면 cinema의 width속성만 바뀐 것을 알 수 있다. cinema는 hd의 모든 value를 그대로 복사해서 가져가 완전히 새로운 하나의 객체를 생성한 것을 알 수 있다.
그렇다면 Class는 어떨까?

Classes Are Reference Types

Unlike value types, reference types are not copied when they’re assigned to a variable or constant, or when they’re passed to a function. Rather than a copy, a reference to the same existing instance is used.
위의 설명에서 볼 수 있듯이 Classes는 함수에 전달되거나 변수에 할당될 때, 복사 대신 기존 객체에 대한 참조가 사용된다. struct에서 사용한 예시를 동일하게 class로 바꾸어 보자
class BoxSize { var height = 1080 var width = 1920 }
Swift
복사
// in Main var hd = BoxSize() var cinema = hd cinema.width = 2048 print("hd height = \(hd.height)") print("hd width = \(hd.width)") print("cinema height = \(cinema.height)") print("cinema width = \(cinema.width)")
Swift
복사
hd를 복사해서 cinema에 넣고 cinema의 width값을 바꿨을 뿐인데 hd와 cinema의 값이 모두 바뀐 것을 알 수 있다. class는 위에서 말했듯이 값을 복사해 넣는게 아니라 객체에 대한 참조를 사용하기 때문이다. 아래의 그림이 이해를 도와줄 것이다.

Identity Operators

클래스는 reference type이기 때문에 하나의 객체를 참조하는 여러개의 변수가 존재할 수 있다. 이 때, 각 변수들이 동일한 객체를 참조하는지 확인하는 도구가 있으면 유용할 것이다! 아래 연산자를 보자
=== // Identical to !== // Not Identical to
Swift
복사
Identical은 Equal과 다르다. Identical은 두 변수가 동일한 객체를 가리크는 것을 나타낸다. Equal에 대한 정의는 개발자의 역할이다.

Functions in Swift

1) Parameters

함수에 parameter를 넣으려면 아래와 같은 형태로 넣어준다.
func printSomething(parameter: DataType) { // Do something }
Swift
복사
해당 함수를 호출할 때에도 동일한 형태가 되어야한다
printSomething(parameter: Contetns)
Swift
복사

2) Functions with Outputs

func getSomething(money: Int) -> Int { // Do something return value }
Swift
복사

3) IF / Else

if something == Value{ // do } else { // do }
Swift
복사

Example

func loveCalculator() { let loveScore = Int.random(in: 0...100) if loveScore == 100{ print("You love each other") } else { print("You will alone...") } } loveCalculator()
Swift
복사

4) Switch / Case

switch value{ case: //code case: //code default: //code }
Swift
복사

Example

func loveCalculator() { let loveScore = Int.random(in: 0...100) switch loveScore { case 81...100: print("You love each other") case ...40 print("something") default: print("You love each other") } } loveCalculator()
Swift
복사