목록개발 (43)
Stacking Fire
UIView에는 animate(withDuration:animations:completion:)라는 애니메이션 메서드가 있습니다. 프레임(frame) 베이스의 앱에서는 아주 직관적이고 편리한 메서드입니다. 하지만 오토 레이아웃을 쓰게 되면 좀 혼란스러워지죠. 프레임처럼 단순히 값만 바꿔주는 걸로는 작동하지 않습니다. 애초에 프레임 값의 변화를 캐치해서 애니메이션으로 만들어 주는 메서드이기 때문입니다. 찾아보면 슈퍼뷰(superview)에 layoutIfNeeded()를 사용하면 된다고 하는데, 모든 서브뷰를 다시 레이아웃하는 메서드인 만큼 부작용이 따를 수 있습니다. 게다가 뷰의 레이아웃 뿐만 아니라 컬러라든가 컨텐츠 등을 업데이트하는 것도 같은 타이밍에 애니메이션되어야 한다면 머리가 좀 아파집니다. 관..
이니페이 모바일(INIPay Mobile)은 이니시스(INICIS)의 서비스 중 하나로, 앱 내에서 웹뷰를 이용해 결제 서비스를 제공할 수 있도록 하는데요. 직접 iOS에 붙이면서 배운 점을 정리해 보았습니다. 언어는 Swift 4.0입니다. 주의할 쿼리, P_RESERVED 앱 내에서 웹뷰를 띄울 때를 위한 대부분의 설정은 여기서 해 줍니다. 그런데 P_RESERVED는 '복합 필드'라고 해서, P_라는 프리픽스가 붙는 쿼리들과 섞여서 요청되게 되는데 그 값에 문자열 &이나 = 들어가야만 합니다. INIPay 문서 쪽에는 이 처리를 위한 iOS 가이드가 없습니다. 따라서 캐릭터셋 중에 .alphanumerics이라는 놈을 이용하여 퍼센트인코딩을 해 주었습니다. 일단 잘 동작하긴 하지만, 테스트를 많이 ..
Closure 안에서 self를 무심코 참조하여 쓰는 경우가 많습니다. 하지만 Swift에서는 Closure가 일급 객체이기 때문에, self의 프로퍼티로 저장될 수도 있습니다. 아무 조치 없이 그냥 쓴다면 상호참조로 인해 메모리 누수가 발생하기 쉬운데요. 그래서 클로저 파라미터 앞에 [weak self]를 넣어 리테인 카운트를 올리지 않은 채 참조할 수 있도록 해주는 것이 필요합니다. 이렇게 weak 키워드를 넣으면 클로저 내부에서는 self를 옵셔널로 판단합니다. 쓰려면 까 주어야죠. someInstance.someFunction { [weak self] param in guard let `self` = self else { return } self.someOtherFuction(param) //아니..
앱 개발을 하게 되면 보통 UI 디자인은 Sketch로 하게 됩니다.그리고 그 디자인을 제플린이나 여타 툴로 받아서 구현하게 되는데요. 제플린은 정말 좋은 툴이라 텍스트에 필요한 여러 옵션을 읽어서 글꼴 프리셋을 만들어 주기도 합니다. 하지만 늘 그렇듯 자동화라는 게 스스로 짜놓은 것만 못하고, 또 어쩌다가 실수로 0.1만 틀려진 설정도 다 다른 설정으로 받아들입니다. 그렇다고 안 쓰자니, Sketch에서는 버튼 한 두개로 바꿀 수 있는 설정이 개발에서는 그리 간단히 되질 않습니다. 그래서 스케치에서 할 수 있는 글꼴 설정의 (거의) 모든 걸 지원할 수 있는 익스텐션을 만들었습니다. Code extension String { enum AttributePreset { case body case headli..
(이 포스팅은 StackOverFlow의 이 답변의 아이디어를 기반으로 간단한 수정만을 거쳤음을 알립니다.) iOS에서 로컬라이제이션을 하려면 아래와 같은 코드를 사용합니다. myLabel.text = Bundle.main.localizedString(forKey: "쓰고자 하는 글", value: nil, table: nil) 스트링이 들어가는 모든 부분에 말이죠. 한두번도 아니고 말그대로 수십번 이렇게 쓰는 것은 쉬운 일이 아닙니다. 그래서, 이 똑같은 걸 간단하게 바꾸는 아이디어가 있기에 가져와 보았습니다. 그러니까 스트링이 들어가는 모든 부분에 필요한 거잖아요. 그럼 스트링한테 시키면 된다는 겁니다. extension String { var localized: String { return Bund..
개요 Crashlytics는 모바일 앱에서 발생한 크래시를 개발자가 알 수 있도록 해 주는 솔루션입니다. (언어 : Swift) 사용법 Fabric ID가 필요하며, iOS에 해당하는 라이브러리는 CocoaPods을 통해 설치합니다. Kit를 프로젝트에 추가하기 // Podfile pod 'Fabric' pod 'Crashlytics' // Run Script Build Phase "${PODS_ROOT}/Fabric/run" ##################API KEY################ // Info.plist Fabric APIKey ##################API KEY################ Kits KitInfo KitName Crashlytics Crashlytics ..
회사에서 새롭게 만드는 프로젝트의 중요 기능에 유닛 테스트를 적용하기 위해 방법을 정리해 보았다. 방법 테스트 타겟을 만들어 특정 함수가 기대하는 결과를 내는지를 검증. 순서 : 유닛 테스트 타겟 추가 → 테스트용 인스턴스 생성 → 결과 확인을 XCTest 함수에 연결 → ⌘ + U로 실행 테스트용 인스턴스 테스트용 인스턴스는 setUp()에서 만들고 tearDown()에서 풀어준다. setUp() 에서는 super.setUp()아래에 인스턴스를 만든다. tearDown()에서는 super.tearDown() 위에서 nil을 할당해 준다. var instanceForTesting: ClassForTesting! override func setUp() { super.setUp() instanceForTes..
Monad [|mɑ:nӕd;|moʊn-](철학)모나드(무엇으로도 나눌 수 없는 궁극적인 실체)Oxford Advanced Learner's English-Korean Dictionary ...왜 이 개념이 이렇게 쓰였는지는 아직 모르겠습니다. 더 공부해 보겠습니다. 컨텍스트 맥락. 어떤 위치에 어떤 값이 존재할 수 있는 맥락. 옵셔널은 맥락은 존재하지만 값이 필연적으로 존재하지는 않을 수도 있는 부분에 들어감. 값과 컨텍스트는 다르다. 그래서 옵셔널은 값을 대신할 수 없다! func add3(to int: Int) -> Int { return int + 3 } add3(to: Optional(2)) // 오류! // 값이 들어가야 하는 곳에 컨텍스트만이 들어갔다. 함수객체 함수객체란 맵을 적용할 수 있는..
map, filter, reduce는 객체에 데이터를 보내서 받는 전통적인 형태의 함수가 아닙니다. 클로저로 다른 함수를 받아 데이터셋을 변형시키는 고차 함수입니다. 옵저빙 프로퍼티와 함께 함수형 프로그래밍 '스러운' 기능을 지원하는 것입니다. 아래는 단순히 사용법이지만, 체인처럼 걸어서 사용할 수 있습니다. 맵 for-in처럼 각 요소에 특정한 행동을 수행해준 후에 그 각각 처리된 요소를 이용한 컬렉션을 만들어줍니다. 반환하지 않는 클로저를 전달하면 그냥 반복문으로 사용 가능. //긴 버전 var doubled: [Int] = numbers.map { (i: Int) -> Int in return i * 2 } print(doubled) //짧은 버전 var dbld: [Int] = numbers.ma..
옵셔널 체이닝 윗물이 맑으면 아랫물은 괜찮을 수도 있다. 체이닝의 끝은 늘 Optional! 바인딩과 함께 써 보도록 하자. 백견이 불여일RUN //옵셔널인 놈에게만 궁금증을 가진다! ash?.bag.badgeCase?.append(grayBadge) //바인딩과 함께 바인딩! if let firstBadge = ash?.bag.badgeCase?[0] { print(firstBadge) } 빠른 종료 guard let 한 코드 블럭에서 여러 개의 옵셔널을 다루어야 할 때가 있다. 쓸 때마다 언 함수, 메서드, 반복문 등 특정 블록 내에서만 사용이 가능. 반환값이 있는 함수 내에서 사용할 경우 반환값을 요구하기도 한다. func greet(person: [String: String]) { guard le..