IOS application/Swift 27

[Swift] @discardableResult

@discardableResult 키워드는 무엇을 하는 것일까 @discardableResult 는 직역하면 버릴 수 있는 결과를 의미한다. 우리는 개발을 하다보면 IDE 환경에서 다음과 같은 Warning를 발견할 것이다. 변수나 함수나 등등 선언해놓고 생성해놓고 사용을 하지 않아서, 이거 혹시 뭔가 이상하지 않니? 이런 경고다. 하지만, 이런 것들이 필요없을 때가 존재한다. 이때, @discardableResult를 사용하면 된다. "나는 결과를 쓰든 안쓰든 신경 안 써도 돼. warning 띄워주지 마! " 라는 의미에 해당한다. Protocol에 선언된 이놈들은 사용하지 않아도 Warning을 띄우지 않게 된다.

26. [Swift] 시간과 날짜: Date(), DateComponents()

개발을 진행하다 보면 날짜와 시간을 이용해야 하는 경우가 너무 많다. 그래서 날짜와 시간을 이용하는 Date와 DateComponents에 대해 살펴보자. 현재의 날짜와 시간 구하기 Swift 개발 문서에 따르면, Date는 어떠한 달력과 Time Zone과는 독립적인 특정 시점의 시간 포인트이다. 아래의 코드는 Date Class를 생성함으로 상대시간과 절대시간을 정할 수 있다. // 득정 시점 init() // 현재 시점의 시스템의 날짜와 시간 init(timeIntervalSinceReferenceDate: TimeInterval) // 21세기 시작 지점 2001. 1. 1 00:00:00 UTC를 기준으로 TimeInterval만큼 후의 시간 init(timeIntervalSince1970: T..

25. [Swift] 고차함수 - map, flatMap, compactMap

map의 기능은 전체 아이템의 타입이나 상태, 형태, 값을 한번에 변경할 때 사용한다. mapping 하는 함수이다. 결과를 배열의 상태로 반환한다. map Declaration func map(_ transform: (String) throws -> T) rethrows -> [T] Example let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] names.map { $0 + "'s name" } // ["Chris's name", "Alex's name", "Ewa's name", "Barry's name", "Daniella's name"] let array = [1,2,3,4,5] array.map { $0 + 1 } // [2, 3, 4, 5..

24. [Swift] 고차함수 - forEach, filter, reduce

이번에는 꿀같은 고차함수들을 소개하려 한다. 원리는 간단하다. forEach - for문의 함수버젼 filter - 리스트에서 내가 원하는 요소만 빼온다. reduce - 리스트의 요소를 하나로 합쳐서 줄인다. forEach for-in(일반적인 For문)에서는 break, continue을 사용할 수 있고, return을 이용해서 빠져나오려면 에러가 납니다. forEach에서는 break, continue 구문을 사용할 수 없고, return을 통해서 빠져나갈 수 있습니다. (continue처럼 동작함) filter 리스트에서 원하는 값만 가져올때 사용한다. return 되는 값이 True가 되는 값들만 가져온다. true이면 값을 포함하고 false이면 값을 배제 합니다. reduce 리스트에 존재하..

23. Transfer data between TabbarController

우선 이런 logic이 필요한 이유를 설명하겠다. TabbarController들은 각각 독자전인 ViewController이다. 즉, 데이터를 이동하는 것이 가능은 하돼 이동시킨다는 개념을 이용하면 비효율적인 점이 존재한다. 그래서 내가 생각한 logic은 데이터를 관리하는 Object를 만드는 것이다. 나는 Login을 하게 되면 위에 있는 TabbarController로 넘어오도록 구현했었다. 그런데 TabbarController에서 데이터를 받는 것까지 완성했지만, 바로 첫번째 ViewController로 이동했다. TabbarController에서 첫번째 ViewController로 이동했는데, 데이터를 어떻게 이동해야 할지 고민하다가 결론지었다. 독립적인 ViewController들 사이에 데..

21. iOS TTS (Text-To-Speech)

iOS 10 이상부터 text data를 목소리 형태로 바꿀 수 있다. 코드는 아래와 같이 비교적 많이 간단하다. 주의할 점은 반드시 import AVFoundation 을 추가해야 한다. import UIKit import AVFoundation class TextToSpeechViewController: UIViewController { @IBOutlet weak var myTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) myTextView.text = "오빤 맨날 그런식이야"..

20. swift change multiple view by segmented control

각 Segment control에 의해 다른 뷰를 보여줘야 하는 경우가 존재한다. View가 비슷한 구조라면 Segment control에 의해 띄우는 데이터를 달리하면 된다. 하지만 다른 View가 등장해야 하면 그에 따른 설정이 필요하다. Storyboard (Home.storyboard) publicViewController에 연결된 UIView이다. 내부에는 View - Segment Control - ContainerView 가 존재한다. 이때, SegmentControl의 index에 의해 ContainerView에 보여질 View를 달리하면 된다. Storyboard (Public.storyboard) 여기에는 두 가지 ViewController가 존재한다. ImmediationViewCon..

19. 여러개의 ViewController를 한꺼번에 dismiss

회원가입이 완료되거나 긴 Segue로 연결된 ViewController를 한꺼번에 dismiss해야하는 경우가 발생한다. 처음으로 가는 방법인 것이다. 여기서 문득 의문이 생길 수 있다. Q. 그냥 마지막 페이지에서 첫 페이지를 present 하면 안되나?? A. 여러 페이지를 present한 경우 지금까지 거처온 페이지 들은 바로 뒤에 존재하고 있는 상태이다. 이는 resource 소모를 하고 있는 상태이다. dismiss를 한번 해보면 이를 바로 확인할 수 있다. 즉, 한꺼번에 여러 페이지를 dismiss 하는 것이 목적이다. 아래의 코드는 4페이지를 dismiss한 것이다. @IBAction func goFirstPage(_ sender: Any) { self.presentingViewControl..

18. UITextField underline

TextField의 경우 제공하는 4가지 형식 말고 다양한 구성을 원하는 경우가 있다. 그중 한가지가 아래와 같이 밑줄을 넣고 underline을 만드는 경우가 있고, 클릭되었을 때 반응하게 만드는 경우도 존재한다. 아래의 코드에서는 viewSize와 color을 파라미터로 받게된다. 자체적인 viewSize를 사용하는 경우 다양한 폰에서 textField의 크기를 인식 못한다는 점을 발견했다. 그래서 호출하는 당시에 view.bounds.width를 파라미터로 보내면 된다. color은 원하는 컬러를 호출하는 곳에서 결정하도록 만들었다. 예를 들어, emailTextField: UITextField 에서 수정을 "시작할 때 혹은 끝낼 때" 호출되는 함수에서 색을 지정해주면 위의 그림과 같이 수정된다. ..

17. currentFirstResponder

페이지를 구성하다보면 현재 FirstResponder이 누구인지를 판단해야 하는 경우가 발생한다. 그래서 직접 extension으로 구현해보았다. 원하는 상황에 currentFirstResponder()을 호출하게 되면 UIResponder에서 first에 해당하는 responder을 반환하게 된다. import UIKit extension UIView { func currentFirstResponder() -> UIResponder? { if self.isFirstResponder { return self } for view in self.subviews { if let responder = view.currentFirstResponder() { return responder } } return nil..

16. Normalization 정규화 - 규칙이 있는 String

다양한 페이지에서 String에 조건을 주고 싶을때 정규화를 사용할 것이다. 이때 정규화는 어떻게 구성되는 지를 설명하겠다. class Normalization { // 회원가입, 로그인 등 Normalization의 모든 검증을 하는 type method static func isValidRegEx(regExKinds: String?, objectString: String?) -> Bool { guard regExKinds != nil, objectString != nil else { return false } var regEx: String = "" switch regExKinds { case "name": regEx = "^[가-힣]{2,10}$" case "birth": regEx = "^[0-9..

15. 이용약관 동의 페이지

약관에 대한 내용을 DatailType의 case분류를 통해 확장성을 높힌것 같아 자랑하고 싶어서 올린다. 이용약관 상세페이지를 보려면 페이지를 이동하게 된다. 각 페이지에 약관 데이터를 넣는 것은 같은 형식의 코드를 여러번 사용해서 비효율 적이다. --> 약관동의에 대한 ViewModel로 데이터를 한번에 관리하고 어떤 case인지만 기재하면 된다. --> 약관 명을 보고 동의하는 페이지와 약관 상세페이지에서 동의하는 페이지 모두 동의한 것을 동일하게 인지하게 위해 instance property 보다 type property로 이를 선언하는게 용이하다고 판단함. 정답은 아니겠지만 생각을하고 코드를 짠다는 점 칭찬해~~ class TermsOfServicesViewModel { enum DetailTy..