라벨이 Swift인 게시물 표시

Swift에서 Enum을 활용하는 10가지 방법

이미지
개발을 하고, 리팩토링을 하다보면 Enum을 썼을 때 좋은 결과를 얻은 경험이 많습니다. 그러나 너무 남발하게되면 또 코드가 더러워져서 어떻게 응용하면 좋을지 정리해 보도록 하겠습니다. 다음 아티클 을 보고 가져온 코드도 있고, 이해했는지 검증하기 위해 새로 짠 코드들도 있습니다. enum이 무엇인지 문법을 알지만 어떻게 활용해야 할지 모르는 분들 미래의 나를 위해 작성했습니다 프로퍼티 활용방법 enum에는 stored properties 를 만들 수 없습니다 즉 변수를 선언해서 할당할 수 없다는 뜻이죠. 하지만 computed properties 는 선언해서 활용할 수 있습니다. 예제 코드를 보여드릴게요 enum Food { case korean case japanese var name: String { switch self { case . korean: return "kimchi" case . japanese: return "sushi" } } } let todaysLunch = Food.korean.name print(todaysLunch) / / kimchi 위와 같이, 음식의 종류를 정했다면, 저장 프로퍼티인 name 을 만들어서 각각의 값을 저장 해 줄 수 있습니다. 저는 enum에 String을 지정해서 return을 해주려고 했었는데 이 방법이 훨씬 깔끔한 것 같아요. 각각에 변수마다 필요한 값들을 내려주는 것이 명확하네요 메소드 활용방법 프로퍼티 말고 메소드도 enum에 정의해서 활용할 수 있습니다. 아래의 예시를 통해 설명 드리도록 하겠습니다. enum Food { case korean case japanese func description () -> String {

Optional이란 무엇인지 설명하시오. 에 대답하지 못한 사람을 위한 글

이미지
이 글은 제목처럼 Optional이란 무엇인가요? 라는 질문에 대답하지 못하는 사람을 위해 쓰였습니다. Swift 문법 책에서 Optional은 써 보았지만, 무엇인지 왜 쓰는지 모르는 사람을 위해 쓰였습니다. 그리고 미래의 저를 위해 쓰였습니다. 옵셔널은 타입 옵셔널을 이해하기 위해서는 타입에 대한 이해가 필요합니다. 스위프트에는 두 종의 타입이 필요합니다. 하나는 이름이 있는 타입(named type)이고, 나머지 하나는 이름이 없는 혼합된 타입(compound Types)입니다. 사용자가 만든 클래스 타입, 배열, 딕셔너리 등은 전부 다 이름이 있는 타입입니다. 또한 데이터의 자료형을 나타내는 숫자, 문자 형들도 다 이름이 있는 타입이죠. 혼합 타입은 이름이 없이 정의된 타입입니다. 예를들면 튜플의 (Int, Double) 로 정의된 타입들이 혼합형 타입입니다. 이름이 없고, 이미 정의된 타입들이 섞여있습니다. 그렇다면 타입의 종류에는 어떤 것들이 있을까요? type → function - type type → array - type type → dictionary- type type → type -identifier type → tuple- type type → optional- type type → implicitly-unwrapped-optional- type type → protocol-composition- type type → opaque- type type → metatype- type type → any- type type → self- type type → ( type ) 타입들을 살펴보다보면, 옵셔녈 타입이 있습니다. 그러므로 옵셔널은 타입중에 하나 입니다. 이름 그대로 이미 정의된 타입에 값이 있을 수도 있고 없을 수도 있는 타입입니다. 옵셔널로 만들어 써보기 옵셔널 타입을 만드는 방법은 간단합니다. 타입의 뒤에 ? 기호를

[Swift] Encoding과 Decoding

이미지
[Swift] Encoding과 Decoding iOS개발의 많은 부분들이 데이터를 요청해서 받고, 또 보내는 것인데요. 할 때마다 헷갈려서 정리 해 놓으려고 합니다. Data 만약에 아래와 같은 json 데이터를 서버로 보내야 한다고 생각해봅시다. { "name" : "Leeo", "age" : 29, "pet" : { "name" : "coco", "type" : "dog" } } 어떻게 보낼 수 있을까요? 물론 문자열로도 만들 수 있지만, 그러면 같은 모양의 여러 데이터를 여러개 만들 때 비용이 너무 크게 들테니 모델을 만들어서 같은 데이터를 찍어내는게 좋겠습니다. 가장 바깥의 단계 부터 차례대로 구조를 보고 모델을 만들면, 객체를 만들 수 있을 것 같습니다. 아래와 같이 코딩을 하면 변환이 가능해 보입니다! import Foundation struct Person: Codable { var name: String var age: Int var pet: Animal } struct Animal: Codable { var name: String var type: String } Codable은 Decodable 과 Encodable을 동시에 채택한 프로토콜입니다. 그러면 Encodable은 뭐고 Decodable은 무엇일까요? Encodable 이 프로토콜을 채택하면, 이 구조체는 json데이터로 인코딩 될 수 있음을 보장합니다. Person만 Encodable을 채택하고, Animal은 Encodable을 채택하지 않으면, Person은 json으로 온전히 변환된다는 보장이 없으니, 모두 채택 해 주어야 합니다. 그럼 이제, 우리의 데이터를 json으로 만들어 봅시다. 순서는 다음과 같습

[swift] swift 기본 문법 스터디 4주차

이미지
[swift] swift 기본 문법 스터디 4주차 집단 자료 (collective Types) 관련있는 데이터 끼리 모아서 관리 할 수 있는 자료형입니다. 같은 형태의 여러개의 자료를 다룰 때 유용하게 쓸 수 있습니다. Array Set Tuple Dictionary Array 데이터에 index로 접근할 수 있습니다 순서가 있어서 계속 인덱스가 늘어납니다 하지만 중간에 데이터가 사라지면 앞으로 당겨집니다 반복 반복을 하는 방법이 다양합니다. 처음부터 끝까지 반복됩니다. 초기화 초기화 하는 방법에는 다양한 방법이 있습니다. 선언 : var name: [String] 초기화 : name = [String]() 동적할당 append - 맨뒤에 추가됩니다 insert(at) - 해당 인덱스 자리에 추가 후 나머지는 1씩 뒤로 밀립니다 append(contentsOf) - 여러개의 인자를 추가됩니다 범위 연산자 할당 당하는 영역보다 할당하는 영역이 크면 -> 길이가 늘어납니다 반대는 길이가 줄어듭니다 Set 중복이 없으며, 순서에 대한 보장도 없습니다. 대신 해시연산의 결과 값을 이용하여, 저장하기 때문에 불러올 때 성능이 매우 빠릅니다. 정의 Set () 추가는 .insert 로 할 수 있습니다. 순회가 가능합니다. 집합연산이 가능합니다. Array와 Set을 비교해서 사용처를 구분하는게 좋지 않을까요? 여부판단 말고 어떤 예제가 있을까요? Tuple 특별한 성격 집단의 자료형으로, 여러 타입의 데이터를 한번에 담을 수 있습니다. 하지만, 최초에 선언된 상태의 아이템만 사용하고, 수정삭제 추가 불가능 하다는 것이 특징입니다. () 을 사용하여 정의합니다. Dictionary 키와 밸류가 연결되어있는 자료형입니다. 배열과 같은 어노테이션을 사용하며, 같은 타입만 들어갈 수 있습니다. 값을 업데이트 할 수 있습니다. 또한 순회하면서 탐색할 수

[swift] swift 기본 문법 스터디 3주차

이미지
[swift] swift 기본 문법 스터디 3주차 이번주는 흐름제어에 대해 정리해 놓으려고 합니다. 가장 정확한 문서는 공식문서라고 생각하고, 링크 를 첨부해 놓겠습니다. 불면증을 위해 한 번 정독했습니다. 반복문 for ~ in 루프상수, 순회대상 루프상수의 생략가능 다중루프 -> 차원을 줄이는 것이 가능? 몇번 돌지 보통은 알지 않을까요? while 조건을 만족하는 동안 실행 한번은 실행을 보장해주는 repeat while 어떻게 만들어 진걸까요? Dictionary Array set 범위데이터 문자열 Sequence Iterator 조건문 if if 키워드 뒤에는 반드시 조건식이 와야합니다. 참 일 경우에는 if 뒤의 구문을 실행합니다. 중첩된 이프문의 조건 정리하는 꿀 팁 아시는 분? guard 조기 종료 참일 때 실행되는 구문이 없다 조건 체크에 사용하면 좋습니다 #available(<플랫폼이름 버전>, <플랫폼이름 버전>, <플랫폼이름 버전>…) switch 일치하는 패턴이 있다면 실행하고 switch문 종료 default 패턴 매칭 제어 전달문 break switch에서 사용, 반복문에서 사용 종료 continue 종료하지 않고 패스! label 신기! fallthrough 다음으로 넘어가지 않음! return 함수와 메소드에서 사용 값을 반환, 종료

[swift] swift 기본 문법 스터디 2주차

이미지
[swift] swift 기본 문법 스터디 2주차 변수와 상수 메모리에 값을 저장하려면 저장하고 싶은 메모리의 주소값이 필요합니다. 그리고 우리가 저장한 값을 가져올 때도 메모리의 주소값이 필요하겠죠? var x: Int = 10 print(x) withUnsafeMutablePointer(to: &x) { print("x address: \($0)") } x = 20 print(x) withUnsafeMutablePointer(to: &x) { print("x address: \($0)") } let y: Int = 30 print(y) withUnsafePointer(to: &y) { // error! print("y address: \($0)") } 위와 같은 방법으로 메모리 주소값을 찍어보았습니다. 생각보다 간단하지 않아 당황했네요. 그런데 아직 의문인것은 같은 변수이지만, let 변수는 mutable 하지 않기 때문에 withUnsafeMutablePointer로 주소를 찍을 수 없었습니다. 이 부분에 대해서는 어떤 의미가 있는지 더 찾아보고 수정하도록 하겠습니다. 또한 변수에는 한글, 알파벳, 아라비아숫자, 특수기호까지 지원하는데 영어와숫자를 사용하는 것 이외에 다른 방법으로 변수를 할당하는 예가 있다면 알려주세요! 자료형 우리가 저장한 변수에는 타입이 있습니다. 기본적으로는 같은 타임의 변수들끼리 연산이 가능하죠. 실제 자료형들은 구조체로 구현되어 있으며, 연산이 가능한 연사자들이 내부에 정의 되어 있습니다. Int - 정수를 저장할 때 씁니다. signed Int8 => 127 ~ -128 : 2^8(256) Int16 => 32767 ~ -32768 : 2^16(65,536) Int32 ^^;; Int64 ^^;; unsigned Int8 => 0 ~

[swift] 옵셔널 체이닝 vs 옵셔널 바인딩

이미지
[swift]옵셔널 체이닝 vs 옵셔널 바인딩 옵셔널 체이닝과 옵셔널 바인딩이 헷갈려 정리해 놓았습니다. 언제 필요할까요? 옵셔널은 프로퍼티에 값이 있을 수도있고, 없을 수도 없음을 나타내는데 사용되었습니다. 옵셔널은 값이 없을 때 nil을 할당 해줍니다. 문제는 우리가 필요한 값이 nil인지 아닌지 확인을 해야하는 번거로움이 있다는 것 입니다. 코드로 예를 들어보겠습니다. class Person { var name: String var job: String? var home: Apartment? init(name: String, home: Apartment?) { self.name = name self.home = home } } class Apartment { var buildingNumber: String var roomNumber: String var security: Person? var owner: Person? init(dong: String, ho: String, security: Person?) { self.buildingNumber = dong self.roomNumber = ho self.security = security } } let chulsoo: Person? = Person(name: "chulsoo", home: apart) let apart: Apartment = Apartment(dong: "101", ho: "202", security: chulsoo) let hyunho: Person? = Person(name: "leeo", home: apart) leeo 라는 사람의 apart 에 있는 security의 이름이 알고 싶습니다.

[swift] guard let, if let 차이

이미지
[swift] guard let, if let 차이 Optional 변수를 안전사게 사용하기 위해 방법을 찾던 중 if let과 guard let에 대해 정리하겠습니다. 변수에 값이 올지 않올지 확신할 수 없을 때 Optional을 씁니다. 그러면 Optional 타입의 변수에 값은 어떻게 꺼내어 사용할 수 있을까요? 간단합니다 옵셔널 바인딩을 해서 사용합니다. 값이 올지 안올지 정확히 알 수 없을 때 Optional 타입의 변수 를 사용하는데요 잘 모르는 분들이 이 전 글을 참고 해주세요! 안전하게 Optional 타입의 변수를 Unwrap하기 위해서는 옵셔널 바인딩을 해야하는데요 크게 두 두가지 방법이 있습니다. 바로 if let과 gurad let 입니다. 코드로 보는 예제 다음 예제 코드를 통해 둘의 차이점을 살펴 보겠습니다. func fullName(name:String, rawPrefix:String?){ // if let을 사용했을 경우 if let prefix = rawPrefix { print(prefix+name) } else { print("need prefix") } // guard let을 사용했을 경우 guard let prefix = rawPrefix else { print("need prefix") return } print(prefix+name) } fullName(name: "hyunho", rawPrefix: "Lee") 풀네임을 작성할 때 이름은 필수이지만 성은 언제나 들어오지는 않는 옵션널 한 값 입니다. guard let을 사용하는 경우에 이름만 들어오고 성이 들어오지 않았다면, 이런 케이스는 예외 케이스, 혹은 원하지 않는 상황 이라고 판단합니

[swift] Optional 뜯어보기

이미지
[swift] Optional 뜯어보기 swift에서 데이터를 저장하는 곳을 변수라고 하는데, 이 변수에 아무것도 들어있지 않은 상태를 표현해야 할 일이 있습니다. 0이 아니고 빈 문자열("")도 아닌 아무것도 없는 것. 변수에 아무것도 할당 되어있지 않은 것을 스위프트에서는 참을 수 없으니까요! 아무것도 들어있지 않다라는 것이라도 넣어 둡시다. 이때 사용되는 것이, 없다 라는 오브젝트인 nil입니다. 변수에 아무 값도 들어있지 않다는 뜻 입니다. 사용 법 정의 타입 뒤에 ?를 붙여주면 옵셔널타입 이라는 뜻 입니다. var name: String? = "leeo" print(name!) // leeo name = nil print(name!) // error 이렇게 사용가능합니다. 조금 더 자세히 살펴보면 var name: String? = "leeo" 이 코드에서 타입이 String?임을 알 수 있습니다. 정확히는 이런 뜻 입니다. var name: Optional<String> 왜냐하면 typealias String? = Optional<String> var name: String? 이렇게 한 것과 같은 의미기 때문이죠. 그렇다면 Optional 을 까보고 똑같이 구현해 보도록 하겠습니다. public enum CustomOptional<Wrapped>: ExpressibleByNilLiteral { case none case some(Wrapped) public init(nilLiteral: ()) { self = .none } public init(_ some: Wrapped) { self = .some(some) } } extension CustomOptional: CustomDebugStringConvertible { public var debugD

[swift] guard문으로 함수 입구 틀어막기!

이미지
[swift] guard 처음 가드문을 접한것은 옵셔널 체인의 guard let 에서 였습니다. 그래서인지, 오히려 if let 과 guard let 이 비슷 해 보였고 헷갈리기 때문에 정리 해 두려고 합니다. if문은 너무나 익숙 하기 때문에 따로 정리하지 않겠습니다. guard 형태는 다음과 같습니다. guard 조건 else { 조건이 false return || throw } 뭔가 if문과 비교한다기 보다는 생긴 것 그대로 해석을 해 보면, 특정 조건으로 부터 guard 해줍니다. 조건이 틀린 경우는 모두 버리고, 우리가 원하는 조건만 통과 시키겠다는 의미 입니다. 마치 성문 앞에서 통행증을 보고 통과 시켜주는 가드가 생각나는 군요. 사용 예제 guard문은 조건이 맞지 않으면 종료 시켜야 하도록 문법이 되어있기 때문에, 반드시 return이나 throw를 해주어야 합니다. 반대로 말하면 함수 내부에서 사용하도록 만들어진 녀석이죠. 함수에서 사용할 조건들에 맞지 않으면 걸러 보겠습니다. func guardTest() { let condition1: Bool = true let condition2: Bool = true guard condition1,condition2 else { return print("Bye!") } print("Come In!") } guardTest() 조건 2개를 검사하고 모두 만족할 경우에 들여보내드록 하겠습니다. 만약 조건 중 하나라도 거짓이라면 그 들은 내쫓길 것 입니다. 느낀 장점 개인적으로 느낀 장점은 코드의 가독성이 좋아집니다. 예를 들면 우리가 어떤 함수에서 실행해야 하는 조건이 3개라면, if문으로 썼을 때는 다음과 같습니다. func solution() { if condition1 { if condition2 {

[swift] Self VS .self

이미지
[swift] Self VS .self 코딩을 하다 보니, Self.name 을 쓸 때고 있고, leeo.self도 있어서 self라는 키워드는 언제 어떻게 써야하는지에 대해 정리해 놓겠습니다. Self Self 라는 키워드 는 자기 자신의 동적 클래스를 가리킵니다. 아래의 코드를 보시면 Self는 클래스 자기 자신을 가리켜 Self. 으로 인스턴스의 프로퍼티나 메소드에 접근할 수 있는 것을 볼 수 있습니다. class Student { class var name: String { return "Leeo" } func printName() { print(Self.name) } } class Leeo: Student { override class var name: String { return "hyunho" } } let student = Student() student.printName() let leeo = Leeo() leeo.printName() .self .self 를 이해하려면 Metatype에 대해서 알아야 합니다. 이 글의 주제는 아니기 때문에 .self를 언제 사용하는지에 대해서만 간단히 정리하겠습니다. 아래의 결과가 모두 이해된다면 당신은 이미 .self에 대하여 알고 있는 것 입니다! 아니라면 Metatype에 대해서도 공부해 보시길 권해드립니다. let word = "testString" print(word is String) // true print(word is String.Type) // false print(type(of: word) is String.Type) // true print(type(of: word) == String.self) // true //print(type(of:

[swift] Type Method (class func vs static func)

이미지
[swift] Type Method instance vs class vs static 클래스를 사용할 때에 static이 붙은 메소드를 사용하지 못해서 문득 아 얘를 언제 쓰는지 모르고 있구나 라는 생각에 정리해 두겠습니다. func 라는 키워드는 함수를 만들 때 많이 들 보셨을 것이라고 생각합니다. 오늘은 이 앞에 붙는 키워드들의 종류와 그 이유에 대해 알아보고 정리하겠습니다. 아무것도 붙지 않음 func instanceFunc() {} class가 붙음 class func classFunc() {} static이 붙음 static func staticFunc() {} How to make Func 아무것도 붙지 않은 함수는 평범하게 아래와 같이 사용이 가능합니다. class Student { func instanceFunc(){ print("instance func leeo") } class func classFunc() { print("class func leeo") } static func staticFunc() { print("static func leeo") } } let student = Student() student.instanceFunc() Student.classFunc() Student.staticFunc() // instance func from Parents // class func from Parents // static func from Parents 그렇다면 다른 두 키워드 class , static 은 언제 쓰는 것이고 어떤 장점이 있는 걸까요? 이 두 키워드는 클래스가 만든 인스턴스에서 사용하는것이 아닌 클래스 자체에서 사용하는 메소드입니다. 이 두개를 타입 메소드라고 부르는데 어떤 의미냐 하면, 인스턴

[swift] if 문에서 콤마와 && 연산자의 차이점

이미지
[swift] if 문에서 콤마와 && 연산자의 차이점 코딩을 하다가 Bool? 타입의 변수에 true값이 왔는지를 체크하다가 우연히 찾게된 코드를 보고 이해하기 위해서 정리 해놓습니다. 원래 사용했던 코드는 아래와 같았습니다. let result: Bool? if let result = result { if result { print("result is true") } else { print("result is false") } } else { print("result is nil") } 옵셔널일 때 값이 있는지 없는지를 검증하고 나서 그 안의 값을 사용하는 코드를 짰었습니다. 하지만 실제로 false일 때의 경우에는 아무런 행동을 하지 않았기 때문에 else라인은 비어있었습니다. 논리 적으로 아래 코드와 같이 써서 사용할 수 있을 줄 알았는데 동작하지 않았습니다. if let result = result && result { print("result is true") } if let으로 옵셔널을 제거 해 준 후에 사용할 수 있기 때문입니다. 검색을 통해 찾아보니 이럴 때 comma를 이용해 코드를 명확하게 짤 수 있었습니다. let result: Bool? = false if let result = result , result { print("result is true") } else { print("result is nil or false") } 막상 짜 놓고 보니 &&와 comma가 왜 다른지 이 구문이 어떻게 동작하는지에 대해 잘 모르고 있었기에 정리 해 놓겠습니다. 공식 문서 의 if Statement 부분을 참고해보니 이런 내용이 있었습니다. if Stat

[swift] 클로져 개념 잡고 가기

이미지
[swift] 클로져(closures)_v2 함수라고 알고 있던 클로져를 공부하면서 기록합니다. 어느 순간 이해가 안되는 코드들이 클로져로 이루어져있다는 것을 알게된다음 정리와 적용과정이 필요하다는 것을 알고 정리해 놓습니다. 클로저란? 클로저 는 코드에 전달되어 사용할 수있는 독립적인 기능 블록입니다. Swift의 클로저는 C 및 Objective-C의 블록 및 다른 프로그래밍 언어의 람다와 유사합니다. 라는 정의가 공식문서에 적혀있습니다. 하지만 이 개념은 이해가 가지 않았고, 개인적으로는 이름이 없는 함수이고 축약을 위한 다른 규칙들이 있다라고 이해하고 있습니다. 클로저의 문법 함수의 생김새와 사용방법 let name = "hyunho" func printName() { print(name) } printName() // hyunho 클로져의 생김새 let name = "hyunho" let printName = { print(name) } printName() // hyunho 함수같이 생겨서 구조를 뜯어보았습니다. // 함수 func 함수이름(파라미터) -> 리턴타입 { (코드 블럭) } // 클로저 { (파라미터) -> 리턴타입 in (코드 블럭) } 클로져 축약과정 아래의 예시를 들어 함수를 사용하는 방법과 클로져의 사용을 정리해 보겠습니다. 기본설정 func squared(i: Int) -> Int{ i * i } squared(i: 5) // 25 let array = [1,2,3,4,5] squared 함수를 만들어 놓고, 5를 입력하면 25를 반환합니다. 리스트를 만들어서 하나씩 입력 해보겠습니다. 함수와 클로저 사용 // 함수를 매개변수로 전달 let arrayFunctionUsed = array.map(squared) print(arrayFunctionUsed) // [1

[swift] Codable이 뭔지도 모르는 사름을 위한 글

이미지
Codable Codable 프로토콜 API서버와 통신을 하면서 Codable프로토콜을 채택해서 사용해 보았습니다. JSON의 데이터 구조와 맞아야 하는 것 같다는 느낌만 있어서 어떻게 구성되어있고, 어떻게 사용해야하는지 정리해 놓겠습니다. 먼저 애플의 공식문서 에 들어가서 살펴보겠습니다. Codable is a type alias for the Encodable and Decodable protocols. Encodable과 Decodable을 각각 알아야 하는군요. 그럼 알아보겠습니다. Encodable 내가 가진 데이터를 외부의 데이터 타입으로 인코딩 할 수 있게 해주는 프로토콜 입니다. 아래 코드를 가지고 예를 들어보겠습니다. 데이터를 가지고, json을 만들어 보겠습니다. 데이터를 담을 모델이 필요하겠죠? 간단한 모델을 하나 작성해 줍시다. struct Fruit { var name: String? var color: String? } let banana = Fruit(name: "Banana", color: "Yellow") Fruit 이라는 모델을 하나 만들고, 데이터를 넣어 즙니다. 이 데이터를 어떻게 json의 형태로 Encoding을 할 수 있을 것인가? 최족 목표는 아래와 같은 json을 만들어 주는 것 입니다. 무엇을 넣어주면, json으로 만들어 줄 수 있는 걸까요? /// Encodes the given top-level value and returns its JSON representation. /// /// - parameter value: The value to encode. /// - returns: A new `Data` value containing the encoded JSON data. /// - throws: `EncodingError.invalidValue` if a non-conforming floating

[swift] 입문자를 위한 Generic에 대한 기초 개념

이미지
Generic에 관하여 제네릭에 대해 알아보자 제네릭이라는 단어를 듣고 여러 타입을 가리키는 타입변수 라는 정의만 알고있고 실제로 제네릭을 쓰기만 하고 구현해보지 않아 익숙하지 않은 부분이 존재하는 것 같아서 직접 함수를 구현해보면서 온전하게 이해해 보도록 하겠습니다. 설명은 애플 공식문서에 잘 나와있기 때문에 참고하였습니다. 문서 보러가기 제네릭이 왜 필요하게 되었지 편리한 것들은 과거에 어려움이 있었기 때문에 그 문제를 해결하기 위해서 생겨나겟 되었습니다. 제레릭이 어떤 문제들을 해결하기 위해 생겨났는지 살펴보겠습니다. 아래의 코드를 한번 살펴보시죠. func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) // someInt : 107, anotherInt : 3" 쉬운 예제네요. 두 변수의 주소값을 입력 해주면 두 변수의 값이 서로 바뀌어 있습니다. 이 함수를 잘 쓰고 있다가, Double형이나 String 형도 변환할 일이 생기면 다음과 같이 추가로 구현해 주어야합니다. func swapTwoStrings(_ a: inout String, _ b: inout String) { let temporaryA = a a = b b = temporaryA } func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { let temporaryA = a a = b b = temporaryA } 와… 그러면 같은 기능에 변수의 타입이 다를 경우 전부 다 구현해주어야 하는걸꺼요? 그래서 생긴 개념이 이 제네릭입니다. 그럼 어떻게 사용

[swift] 커스텀 버튼을 만들고 커스텀 뷰를 그리기

이미지
[swift] 커스텀 버튼을 만들고 커스텀 뷰를 그리기 버튼영역 내에 그림을 그려 커스텀 버튼을 만들고, UIView에 그림을 그려주는 기능을 구현하려합니다. 삼각형 버튼, 원버튼, 정사각형 버튼을 만들고, 각각의 버튼이 눌렸을 때 뷰의 그림이 버튼의 모양과 같이 나와야 합니다. 구조 메인 뷰 컨트롤러, 도형이 그려진 뷰, 버튼 3개 스토리 보드에는 버튼 개를 올려놓고, 라벨을 그리고, 그 아래 커스텀 뷰를 그려줍니다. 도형 그리기 새 파일을 만들어서 UIButton을 만들어 줍니다. class 앞에 @IBDesignable 을 붙이면, 그린 결과가 storyBoard에 바로 적용됩니다. // // CircleButton.swift // viewTest // // Created by 이현호 on 2020/07/20. // Copyright © 2020 tempYsoup. All rights reserved. // import UIKit @IBDesignable class CircleButton: UIButton { var shape:Shape = .circle override func draw(_ rect: CGRect) { let path = UIBezierPath(ovalIn: rect) UIColor.blue.setFill() path.fill() } } 그리고, draw라는 함수를 override해 주면 커스텀 하게 그릴 수 있습니다. 위와 같이 삼각형, 정사각형도 그려줍니다. 스토리 보드에 배치 해 주었던 버튼의 클래스로 설정으 해주시면 짜잔 그림이 그려집니다. 클릭 이벤트 뷰 컨트롤러에 @IBAction 버튼 클릭을 클릭한 버튼을 인식해 label의 text를 변화시켜 줍니다. enum Shape :String { case triangle case square case circle

[swift] Delegate 패턴 감잡기

이미지
[swift] Delegate 느껴보고 이해하기 delegate를 구현하다가, delegate에 대해 정리 해보는 기회를 가지면 좋을 것 같아서 좋은 예제를 보고 정리해놓는다. 정의 delegate를 사전에 검색해 보면 대리자, 위임자라고 나온다. delegate를 쓰면 무언가를 위임 받는 것 같다. 실제 사용되는 곳을 보면 프로토콜을 사용해서 무엇을 구현해야 하는지 제안한다. 간단한 예제 이름을 입력받아, 라벨에 출력해주는 앱을 제작한다. 구현방법은 다음과 같다. import UIKit class ViewController: UIViewController { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func buttonClicked(_ sender: Any) { nameLabel.text = textField.text; } } 버튼이 눌릴 때, nameLabel.text = textField.text; 하게 된다. 비슷한 기능을 delegate를 사용해서 구현해보자. UITextFieldDelegate TextField에서 일어나는 일에 대한 위임을 ViewController가 받아서 처리해보자. 일단 자 이제부터 이녀석 에게 일어나는 일은 내가 처리해줄게! 를 선언합니다. override func viewDidLoad() { super.viewDidLoad() textField.delegate = self # self는 ViewController입니다 } 간단하죠? textField의 위임자(delegate)는 self야 가 굉장히 직관적입니다. 그럼 그 다음에 textField