목록전체 글 (30)
sanichdaniel의 iOS 개발 블로그
요약 Set의 원소 Dictionary의 키값으로 내가 만든 타입을 사용하려는 경우 Hashable을 채택을 해야 된다. 특정 조건만 만족이 된다면, Hashable 채택만으로 기본 구현이 제공된다. 이때 조심해야하는건, Set, Dictionary의 contains 함수는 hashValue를 비교하여 존재여부를 파악한다. swift 현재 버전에서는 hash(into:) 함수로 hashValue가 생성되는데, hash(into:) 함수에서 Equatable 구현에서 비교에 사용되는 프로퍼티에 맞추어 combine(:)을 호출해주지 않으면 contains(:) 함수가 비정상적으로 동작할수 있다. 애플 공식 문서의 정의는 A type that can be hashed into a Hasher to produ..

의존성 주입을 위해 DI 컨테이너를 사용하는 방식을 채택했다. 이때 어느곳에서 DI 컨테이너로부터 의존성을 받아와야 할까라는 의문이 들었다. 예를들어 A 객체는 외부에 의존성이 있고, A 객체는 B 객체에서 생성되는 상황이다. A가 직접 컨테이너에 접근해서 의존성을 받아와야 할까? 그러면 A가 컨테이너에 의존하게 된다. B가 A를 생성할때 컨테이너에 접근한다면 B가 컨테이너에 의존성이 생기니, 의존성 해결을 생성해주는 쪽으로 미룬것이나 다름없다. 이런 고민을 하던중 Pure DI 에대해 알게되었다. Pure DI DI 컨테이너 없이, Composition Root 한곳에서 모든 의존성이 주입된다. 출처: blog.ploeh.dk/2014/06/10/pure-di/ Compositon Root 의존성 트리..
iOS에서는 정형화된 DI 방식이 없는데, Android에서는 Dagger을 많이들 쓰는것 같았다. Dagger을 참고하여 iOS에서 DI를 구현해보면 어떨까하는 생각에 이르게 되었다. 프로퍼티 래퍼를 이용해 의존성 주입을 할려했으나, 실상은 Service Locator 패턴에 가까웠다. 프로퍼티 래퍼를 통해 Locator 레이어를 타겟 객체로부터 숨겼던것 뿐이었다. 하지만 타겟 객체가 직접 의존성을 요청하지 않고, 프로퍼티 래퍼 안에서 의존성을 요청한다는점에서 Serice Locator 패턴에서 진화된 형태로 볼 수 있을거시다. 프로퍼티 래퍼를 이용한 Service Locator 패턴의 장점으로는 단순함이 있을것 같다. 어떻게, 어디서 의존성을 넣어줄지 고민을 안해줘도 된다. @어노테이션만 붙이면 타겟..

프로퍼티 래퍼를 이용하여 DI를 구현해보던중 안드로이드 Dagger2를 참고해보면 좋을것 같다는 생각이 들어 Dagger를 공부해보았다. Dagger의 장점으로는 어노테이션만 붙이면 의존성이 해결된다는 점이다. 즉 작업하면서 의존성에대해 고민할 필요가 없어진다. Dagger 기본개념 1. Module 2. Inject 3. Component 4. Subcomponent 5. Scope 1. Module 의존성을 생성하는 함수들을 가진 클래스 @Module은 클래스에 붙고 @Provides는 각 메서드에 붙는다 대거가 이 모듈을 파싱할때, 리턴 타입과 메서드를 associate 한다. 근데 만약 함수가 인자를 받는다면, 그 인자의 타입과도 associate 한다. (associate한다가 어떤 의미지?) ..

Property Wrapper을 이용하여 DI를 작업하다가, Property Wrapper을 이용한 DI는 DI가 아니라 Service Locator 패턴이라는 글을 읽어서 Service Locator 패턴이 무엇인지 궁금해졌다. DI와 Service Locator 모두 IoC 구현 방법중 하나이다. Inversion of Control 원리는 말 그대로 제어 흐름을 반대로 한다는 뜻이다. Dependency Injection 타겟 객체는 외부에서 의존성을 주입받는다. 장점 1. 유닛 테스트 하기 수월하다. 외부에서 mock으로 갈아끼워서 넣어주면 된다 2. 생성자만 보고 어떤 의존성이 있는지 알 수 있다. Service Locator Service Locator는 앱에서 사용되는 모든 의존성에 대해 알..

Property Wrapper 내부에서 enclosing self 를 접근하는 방법으로 KeyPath를 이용하는 해결방안이 있었는데 KeyPath가 뭐지.. 알아보자! 정의 KeyPath는 타입의 프로퍼티 값을 읽거나, 수정하지 않고 참조하는 방법을 말합니다. Swift 4 전까지는 KeyPath를 사용하려면 클로져로 래핑하거나, #keyPath() 문법을 써야했으나, 4부터는 사용하기 편리하도록 바뀌었다. struct Person { let name: String func greet() { print("Hello \(name)!") } } let p = Person(name: "Samus") let greeter = p.greet // stores the method without evaluating ..
장점 1. 의존성이 한군데서 관리된다 (관심사의 분리) 2. 한군데서 관리되기에 인스턴스의 생명주기도 관리하기 편하다 3. 한번 의존성을 등록하면, 다시 꺼내서 사용하기가 편리하다 4. configuration 스위치를 만들기 편리하다. 배포용과 테스트용 컨테이너를 만들고 상황에따라 바꿀수 있다 단점 1. DI Container 자체에 대해 공부를 해야한다. 2.사용하기 편리한만큼 코드가 우리에게 추상화가 되어있어 이해하기 어렵다. 3. DI 컨테이너를 모든곳에서 접근할수 있다면, Service Locator 안티패턴으로 이어질 가능성이 크다. 따라서 Composition Root 같이 특정한곳에서 최소한으로 노출이 되어야한다. 출처 StackOverflow DI 컨테이너 도입 토론의 장
Generic where문을 사용하며 문법이 헷갈리는 경우가 많아 정리해보았다 제너릭 where문으로 type paramter과 associated type에 추가적으로 더 요구사항을 줄 수 있다 where 요구사항 요구사항은 type paramter가 특정 클래스를 상속받거나, 프로토콜을 채택함으로 나타낸다. -> where T: Comparable 요렇게 문법적 슈가로 쓸수도 있지만 where S.Iterator.Element: Equatable 로 사용하여, S 가 Sequence protocol 채택하고, associated type S.Iterator.Element가 Equatable protocol을 채택함을 나타낸다. where S1.Iterator.Element == S2.Iterator...

실용주의 프로그래머 책을 읽다가 AOP라는 단어가 나와서 공부해보았다. OOP, POP, FP는 들어봤어도 AOP AOP를 번역하면 관점 지향 프로그래밍이다. 로직을 핵심적인 관점, 부가적인 관점으로 분리하고 그 관점을 기준으로 모듈화를 하겠다는 의미이다. 핵심적인 관점은 결국 우리가 적용하고자 하는 핵심 비즈니스 로직이 된다. 또한 부가적인 관점은 핵심 로직을 실행하기 위한 부가적인 코드로 다른말로는 흩어진 관심사라고 한다. 이 부가적인 코드들은 여러 곳에 횡적으로 흩어져 반복적으로 사용되고 있다. iOS에서는 로깅, 데이터 저장, 캐싱 관련 코드가 있겠다. 위처럼 흩어진 관심사를 Aspect로 모듈화하고 핵심적인 비지니스 로직에서 분리하여 재사용하는것이 AOP이다. AOP의 개념들 Joinpoint:..
요약 Opaque 타입은 변수, 메서드의 리턴타입을 프로토콜 타입으로 숨긴다. 이는 모듈과 모듈을 호출하는 코드 사이에서, 구체 타입을 숨길때 유용하다. 프로토콜을 리턴하는것과의 차이점은 Opaque 타입은 항상 하나의 구체타입을 가르키기에 type의 identity를 간직한다. 물론 caller에게는 프로토콜로만 보인다. 구체 타입은 변수, 메서드의 구현이 결정한다. 이는 caller가 타입을 결정하는 제너릭과 반대이다. 따라서 프로토콜을 리턴하는 상황에서 Self, associatedType 제약이 걸려있는 경우에도, Opaque 타입은 type identity가 간직되기에 프로토콜을 리턴 할 수 있다. (프로토콜을 리턴하는 경우에는 type-erasure wrapper클래스를 구현안해도될수도) Op..
Use Case를 작성하면서 enum과 protocol중 어떤걸 사용할지 고민되는 경우가 많았다. 결론부터 말하면 프로토콜을 지향해야하는데 왜 enum보단 프로토콜을 지향해야하는지 알아보자 UseCase로서 Enum을 사용하는 경우가 많다. Enum은 하나의 namespace로서 작동하고, case를 작성하기 쉽기 때문이다. (namespace: 여러타입, symbol을 하나의 이름으로 묶어준다) 하지만 usecase로서 Enum은 여러가지 문제점이 있다. api 정의를 위해 Enum이 사용된 경우를 생각해보자 enum API { case apiA case apiB case apiC } API는 HTTPMethod, url, parameter들이 정의 되어야 한다. extension API { var h..

요약 프로토콜을 제너릭하게 쓰고 싶으면 associatedtype을 사용하면 된다. associatedtype은 프로토콜이 채택한 순간에 구체 타입으로 교체된다. 하지만 프로토콜을 채택하지 않고 그냥 함수의 인자, 리턴타입, 변수의 타입, 콜렉션의 타입으로 쓰는 경우 컴파일타임에 associatedtype의 구체 타입이 결정이 안되어 컴파일 에러가 난다. 이런경우에는 type-erasure wrapper-class를 만들어서 해결할수 있다. 애플 디벨로퍼 문서를 읽다가 Type-Erasing Wrappers를 발견했다. 무엇인지 알아보기 위해 공부해보았다. Protocols & Associated Types type-erasure에 앞서 protocol과 associated type에 대해 알아야한다. ..