호댕의 iOS 개발

[TWL] 22.01.19 ~ 22.01.21 (Reusable Indentifier의 하드코딩 방지, UIImagePickerController, Keychain, JPEG vs PNG 등) 본문

Software Engineering/TIL

[TWL] 22.01.19 ~ 22.01.21 (Reusable Indentifier의 하드코딩 방지, UIImagePickerController, Keychain, JPEG vs PNG 등)

호르댕댕댕 2022. 2. 11. 21:17

TWL을 블로그에 포스팅 하는 것이 늦어져서 지금에서야 미리 작성해놓았던 TWL을 포스팅한다... 

늦지 않게 꼬박꼬박 포스팅해야겠다. 

 

항상 꾸준하게!!! 

 

그럼 이때는 뭘 배웠는지 정리해보자!! 

 


슬기로운  Reuse Identifier 사용 방법

TableView나 CollectionView에서 Cell을 Register할 때나 dequeueReusableCell을 할 때 항상 reusable Identifier를 사용하게 된다. 이는 물론 String으로 작성해줄 수 있지만 이렇게 할 경우 기억하기도 쉽지 않고 하드코딩을 하게 된다. 

 

따라서 이를 방지하기 위해 이렇게 작성해줄 수 있다. 

protocol ReusableView: NSObject {
    static var reuseIdentifier: String { get }
}

extension ReusableView where Self: UITableViewCell {
    static var reuseIdentifier: String {
        return String(describing: self)
    }
}

extension ReusableView where Self: UICollectionViewCell {
    static var reuseIdentifier: String {
        return String(describing: self)
    }
}

extension UITableViewCell: ReusableView {}
extension UICollectionViewCell: ReusableView {}

이렇게 타입 이름으로 reuseIdentifier를 설정하고 바로 reuseIdentifier를 호출할 수 있다는 장점이 존재한다. 

이렇게 하면 reuseIdentifier의 네이밍도 따로 고민할 필요도 없고 하드코딩도 방지하게 된다. 

 

그렇다면 아예 reueIdentifier를 사용하는 곳에서 호출하지 않도록 구현할 순 없을까? 

 

이는 P.O.P! 즉 Protocol Oriented Programming을 통해 구현해줄 수 있다. 

protocol CellManagable {
    func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
    func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell
}

extension CellManagable {
    func register<T: UITableViewCell>(_ cellClass: T.Type) {
        register(cellClass, forCellReuseIdentifier: String(describing: cellClass))
    }
    
    func dequeueReusableCell<T: UITableViewCell>(_ cellClass: T.Type, for indexPath: IndexPath) -> T? {
        guard let cell = dequeueReusableCell(withIdentifier: String(describing: cellClass), for: indexPath) as? T else {
            return nil
        }
        
        return cell
    }
}

extension UITableView: CellManagable { }

요런 식으로 작성하여 이미 register 메서드와 dequeueReusableCell에 indentifier를 넣어주는 방법으로 작성한 후 새롭게 만든 register 메서드와 dequeueReusableCell 메서드를 호출하는 방식이다. 

 

UIImagePickerController

이는 사진(앨범)에서 이미지를 가져오기 위해 사용하는 것이다. 

만약 시뮬레이터의 앨범에 사진을 넣고 싶다면 컴퓨터에서 시뮬레이터로 사진을 단순히 드래그 앤 드롭만 해주면 된다. 

 

protocol ReusableView: NSObject {
    static var reuseIdentifier: String { get }
}

extension ReusableView where Self: UITableViewCell {
    static var reuseIdentifier: String {
        return String(describing: self)
    }
}

extension ReusableView where Self: UICollectionViewCell {
    static var reuseIdentifier: String {
        return String(describing: self)
    }
}

extension UITableViewCell: ReusableView {}
extension UICollectionViewCell: ReusableView {}

 

Keychain

Keychain 유저를 대신해서 안전하게 작은 단위의 데이터를 안전하게 저장하는 공간. 카드 번호, 생년월일, 비밀번호 등 작은 단위의 데이터를 저장하며 데이터베이스처럼 큰 단위의 데이터는 저장하지 않는다.

1️⃣ Keyed Archiver, User Defaults, CoreData와 다른 점은 무엇일까

  • Keyed Archiver: 저장할 데이터를 인코드하는 역할. objective-c에서 사용하던 방식으로 Swift의 Codable과 같은 역할이다. 현재는 많이 사용하진 않는다.
  • User Defaults: 사용자의 앱 관련 설정 등 간단한 데이터를 저장하는 공간 (재생 속도 등)
  • CoreData: 데이터를 어떻게 저장할 지를 정하는 역할 (영구 데이터, 캐시, 클라우드 등)

Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device.

2️⃣ iOS의 키체인과 macOS의 키체인의 차이는?

iOS 키체인 macOS 키체인
1. 기기 당 하나의 키체인만 가지고 있다
2. 보안메모 이런 항목이 보이지 않고, 비밀번호만 저장됨
3. 웹 양식 암호만 보임
1. 원하는 만큼 키체인을 생성할 수 있다
2. 보안 메모 등 다양한 항목으로 구성됨
3. 웹 양식을 포함한 응용프로그램, 공유기 암호 모두가 보임

3️⃣ 키체인 서비스를 사용하기 위해 k- 접두어를 사용하는 여러 타입과 값을 사용합니다

  • k- 접두어의 비밀은? k가 붙은 변수들을 보면 모두 let으로 선언된 것을 볼 수 있다. 따라서 전역 변수인 것을 표기하기 위해 헝가리언 표기법으로 k를 붙인 것이 아닐까? c_가 함수의 전역 변수를 의미하는데 이는 snakeCase이고 c를 그래도 쓰기엔 이는 int, short (주로 크기로 사용)를 나타내기 때문에 발음이 비슷한 k를 붙인 것
  • 어떤 프레임워크의 값일까? -> Security 프레임워크의 값이다. / Core Foundation (core가 붙은 경우 대부분 C로 구현된 프레임워크이다. 조금 더 성능에 초점을 두고 있다)
  • 그 프레임워크와 Foundation 프레임워크와의 차이는? 고수준 API는 Foundation이고 간단하지만 원하는 기능이 존재하지 않을 수 있다. 따라서 낮은 수준의 Access(구체적으로 구현이 필요한 경우)가 필요하다면 Security를 사용하는 것이 적합하다.

Always use the highest level API that meets your needs. The Security framework is not always your best option. For example, to conduct secure network communications, start by considering the Foundation framework's URL Loading System, which builds on the Security framework. Only if your app requires lower level access to security protocol functions would you use the secure transport API directly. 링크

4️⃣ 키체인은 언제 사용하면 좋을까? 간단한 데이터를 안전하게 저장해야 하는 경우 사용해야 한다.

5️⃣ 웹 세션과 쿠키는 무엇일까?

쿠키 세션
사용자의 정보를 담고 있다. 
1. 쿠키는 클라이언트가 로컬에 가지고 있다. 
2. 브라우저를 종료해도 남아있다. 
1. 호스트(서버)가 가지고 있다. 
2. 브라우저를 종료하면 삭제된다. 

 

JPEG VS PNG

UIImage를 Data로 변환할 때 pngData와 jpegData(compressionQuality:)라는 메서드가 존재한다. 프로젝트에서는 최대 300KB의 정말 작은 데이터를 받아야했고 jpegData(compressionQuality:)를 선택했다.

그렇다면 JPEG과 PNG의 차이는 뭘까 참고 링크: 링크 JPEG의 경우 프로그램 및 설정에 따라 다르지만 일반적으로 압축 비율이 10:1이다. 또한 위 메서드에서 compressionQuality를 직접 정해줄 수 있다. 이때 JPEG는 DCT(이산 코사인 변환?)을 통해 전체 이미지를 보고 이미지의 어떤 픽셀이 주변의 픽셀과 유사한지 비교하고 이를 병합하게 된다. 저장 용량 측면에서 효율적이지만 되돌릴 수 없는 정보 손실이 발생한다.

PNG의 경우 무손실 파일 형식이다. JPEG와는 다르게 PNG는 GIF 및 TIFF형식과 동일하게 LZW 압축 방식을 사용한다. 또한 투명도도 지원하여 픽셀을 투명하게 할 수 있다.

하지만 프로젝트에선 저장 용량이 중요한 문제였기 때문에 JPEG를 사용하는 것이 맞다고 판단했다

 

스크롤 뷰 attribute Inspector 에서 새롭게 찾은 것

내부에 스크롤 뷰가 구현되어 있는 경우 (ex. textView) 이런 attribute가 존재한다.

 

  • default는 do not dismiss로 키보드가 사라지지 않는다.
  • dismiss on drag의 경우 스크롤만 하면 키보드가 사라진다.
  • dissmiss interactively의 경우 사용자가 키보드를 아래로 끌어내릴 경우 키보드가 사라진다.

 

 

 

Comments