IOS application 46

[Swift] SwiftLint 적용해보기 (저자의 방법은 계속 업데이트 됩니다)

SwiftLint는 무엇이고, 왜 사용할까요? SwiftLint의 정의는 Linter, Formatter Library 입니다. 'Linter'란 커뮤니티나 팀에서 정한 스타일 규칙을 따르지 않는 코드 부분을 식별하고 표시하는 것을 돕습니다. 코딩 표준이라고도 불리는 코딩 컨벤션은 코드를 작성할 때 추천하는 코딩 스타일, 괜찮은 사례등을 모아놓은 가이드 라인 입니다. 우리가 프로젝트를 진행할 때 같이 협업을 하게 됩니다. 만드는 과정에서 협업하는 다른 iOS 개발자의 코드를 리뷰를 하게 될 것입니다. 그런데, 상대방의 코드 작성하는 방법이 나와 많이 다르다면 효율은 당연히 떨어지겠죠. 여백을 주는 방법, 중괄호를 열고 닫는 방법, if-else문에서 else의 위치 등 각 개발자가 다른 습관을 갖는 다면..

[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..