☀️ SeSAC Daily Reporting

Comments
  • [220826] TIL

    [220826] TIL

    • 이제 뷰에 대해서 달라지는 것은 거의 없다. 레이아웃 짜는 것은 거의 동일하고, 고려해야 할 부분은 Dynamic하게 들어오는 데이터를 어떻게 처리하고 관리할 수 있을지를 고민하는 것이 더 좋을 것 같다.
    • Realm, TableView 갱신, TableView 로드
    TIL Done day39 
    opened by Taehyeon-Kim 6
  • [220819] TIL

    [220819] TIL

    BaseViewController

    사실 이전에도 BaseViewController를 만들어서 서브클래싱하는 작업을 해왔었는데 어느 순간 프로토콜을 쓰는 게 좋다는 주변 말이 많이 들렸다. 그래서 그런가라는 생각을 나도 덩달아 했었는데, 상속을 하는 구조가 무작정 나쁘다는 생각을 하는 것이 오히려 잘못되지 않았나라는 생각이 들었다. 어차피 상속은 하나의 클래스만 할 수 있고, 모든 컨트롤러에서 공통적으로 쓰여야 하는 내용이라면 하나의 BaseViewController로 상속받아 사용하는 것이 더 낫지 않나 생각이 든다. 개인적으로 그 외적인 것들을 프로토콜로 관리하는 것이 더 맞는 것 같다. 상속과 합성을 적절히 사용하는 것이 가장 적절한 것 같은데 그 정도를 찾기가 정말 어려운 것 같다.

    BaseView

    • View를 만들 때에 공통적으로 들어가는 작업을 모아놓고 상속받아 사용하는 아이디어
    • 뷰 객체를 선언하고 등록하는 작업을 BaseView를 상속받은 서브클래스에서 진행
    class BaseView: UIView {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            
            configureUI()
            setConstraints()
        }
    
        @available(*, unavailable)
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented") // 런타임 오류
        }
        
        func configureUI() {}
        func setConstraints() {}
    }
    

    LoadView

    코드 베이스로 작업을 할 경우 Controller의 역할, 부담을 좀 더 덜어주기 위해 UI 객체를 한 번 더 덜어내는 작업을 수행한다. 간단하게 말해서 RootView를 교체해주는 작업을 해주는 것인데 RootView를 갈아 끼워주는 작업을 LoadView 메서드에서 수행한다.

    • UIViewController의 인스턴스 메서드
    • viewDidLoad전에 호출
    • 원래는 ViewController가 가지고 있는 View는 기본적으로 nil 값이다.
    • loadView에서 View를 채워주는 작업을 한다. 스토리보드의 경우는 자동으로 loadView를 호출하고, View를 가지고 와서 끼워준다.
    • super.loadView()의 호출은 하지말아야 한다.
    override func loadView() {
        print(self.view!) // 신기하다.. 여기서 print찍으면 호출이 안 됨
        self.view = WriteView()
    //        print(self.view)
    }
    

    self.view에 view를 할당하지 않고, self.view를 호출하면 loadView 메서드가 무한 호출된다.

    Notification

    • 신호를 쏘는 쪽, 신호를 받는 쪽으로 구분해서 생각
    • 유튜버와 구독자의 관계로 생각해도 좋다.
    • 원하는 value는 userInfo(딕셔너리)로 전달할 수 있다.
    • 정방향 시점에는 노티가 정상 동작하지 않는다. (메모리에 올라가 있지 않은 인스턴스에 신호를 쏘기 때문)
    • 계층에 상관없이 신호를 전달 가능하다는 장점이 있다.
    NotificationCenter.default.post(
        name: Notification.Name("Post"),
        object: nil,
        userInfo: ["name": nameTextField.text!, "value": 123456]
    )
    
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(action),
        name: Notification.Name("Post"),
        object: nil
    )
    
    @objc func action(_ notification: NSNotification) {
        if let name = notification.userInfo?["name"] as? String {
            self.nameButton.setTitle(name, for: .normal)
        }
    }
    
    TIL Done day34 
    opened by Taehyeon-Kim 3
  • [220812] TIL

    [220812] TIL

    돌아보며

    의식의 흐름대로 몇 자 적으면서

    새싹 과정을 시작하고 벌써 30번째 TIL이다. (1, 2일차 TIL은 어쩌다 보니 빼먹게 되었지만) 참 시간 빠르다... 처음에는 완벽하게 쓰고 싶어서 미루다가 정말 많이 밀렸었는데 이러다가 하나도 못 쓸 것 같아서 간단하게 필기해 뒀던 거 짤막하게 올리는 형태로 바꾸었다. 나중에 다시 찾아볼 수 있는 키워드를 모아놓았다고 생각하면 충분히 좋은 자산이 되지 않을까 싶다. (30일차까지 그래도 몇 자 적으려고 노력한 것은 칭찬한다.)

    여기서 자체 피드백을 하자면, TIL은 그날 그날 쓰는게 베스트인 것 같고 키워드가 있다면 그에 대해 고민했던 나의 생각을 최대한 많이 적는 방식으로 보완해나가려고 한다. 그리고 코드 조각도 많이 모아놓으면 좋겠다고 생각이 든다. 사실 30일차까지의 TIL은 내용을 채워넣기에 급급했던 것 같고, 깊이가 많이 부족한 것 같다. 그동안 뭔가 자기 합리화하면서 너무 많이 나태해졌던 것 같고 시간도 막 쓴 것 같다. 조금 더 엄격하게 나를 통제하고, 중간 중간 복습 못 했던 내용 꼭 조금씩이라도 보완해나가보자.

    미디어 관련

    1. 사진 촬영
    2. 갤러리 접근
    3. 갤러리 저장

    🏞 UIImagePickerController - 커스텀 불가, 사진 촬영 🎥 AVFoundation - 커스텀 (미디어 관련한 세부 처리) 🌆 PHPickerViewController - iOS 14이상, 갤러리 접근, 갤러리 저장, 다중 선택

    YPImagePicker

    • 인스타 그램과 같은 이미지, 비디오 피커
    • Third-party 라이브러리
    • 기본 ImagePicker는 커스텀이 제한적이기 때문에, 작업 기한 및 규모 등을 보고 적절하게 라이브러리를 이용하도록 하자.
    • TLPhotoPicker라고 또 많이 쓰는 라이브러리가 있다. 그러나 YPImagePicker가 더 많이 쓰인다고 한다.

    자세한 작동 방법은 공식 문서를 참고하도록 하자.

    let picker = YPImagePicker()
    picker.didFinishPicking { [unowned picker] items, _ in
        if let photo = items.singlePhoto {
            print(photo.fromCamera) // Image source (camera or library)
            print(photo.image) // Final image selected by the user
            print(photo.originalImage) // original image selected by the user, unfiltered
            print(photo.modifiedImage) // Transformed image, can be nil
            print(photo.exifMeta) // Print exif meta data of original image.
            
            self.imageView.image = photo.image
        }
        picker.dismiss(animated: true, completion: nil)
    }
    present(picker, animated: true, completion: nil)
    

    UIImagePickerController

    iOS 14.0 이상 부터는 갤러리 접근, 저장 같은 경우는 PHPickerViewController를 이용하도록 하자.

    카메라

    guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
        return
    }
    
    picker.sourceType = .camera
    picker.allowsEditing = true // 편집화면 등장
    
    present(picker, animated: true)
    

    앨범

    guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
        return
    }
    
    picker.sourceType = .photoLibrary
    picker.allowsEditing = false // 편집화면 X
    
    present(picker, animated: true)
    

    사진 저장

    if let image = imageView.image {
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
    

    델리게이트 메서드

    기본적으로 UIImagePickerController는 네비게이션 컨트롤러를 상속 받고 있다. 그래서 아래에 UINavigationControllerDelegate도 함께 채택해주고 있음.

    extension CameraViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
        // UIImagePickerController - 사진을 선택하거나 카메라 촬영 직후 실행
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            // - 원본, 편집, 메타 데이터 등 infoKey
            // - 갤러리 상에 있는 이미지는 originalImage
            if let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
                self.imageView.image = image
                dismiss(animated: true)
            }
        }
        
        // UIImagePickerController 5. 취소 버튼 클릭 시
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            // code
        }
    }
    

    Clova 얼굴 인식 API + MultipartFormData

    문자열이 아닌 파일, 이미지, PDF 파일 자체가 그대로 전송 되지 않는다. 그래서 파일을 텍스트 형태로 인코딩하여 서버로 전송해야 한다. 결국 이 형태도 body에 담아보내는 post 요청의 한 형태라고 볼 수 있다.

    import Alamofire
    import SwiftyJSON
    
    @IBAction func clovaFaceButtonTapped(_ sender: UIButton) {
        let url = "https://openapi.naver.com/v1/vision/celebrity"
        
        let headers: HTTPHeaders = [
            "X-Naver-Client-Id": "-",
            "X-Naver-Client-Secret": "-",
            "Content-Type": "multipart/form-data"
        ]
        
        // UIImage를 텍스트 형태(바이너리 타입)로 변환해서 전달
        // MIME Type
        guard let imageData = imageView.image?.jpegData(compressionQuality: 0.5) else { return }
    
        AF.upload(multipartFormData: { multipartFormData in
            multipartFormData.append(imageData, withName: "image")
        }, to: url, headers: headers)
        .validate(statusCode: 200...500)
        .responseData { response in
            switch response.result {
            case .success(let value):
                let json = JSON(value)
                print(json)
                
            case .failure(let error):
                print(error)
            }
        }
    }
    

    Content-Type

    어떤 파일의 종류가 전송되는지 명시해줄 필요가 있다. 여러 파일을 업로드 해야 하는 경우라면 헤더에 Content-Type을 multipart/form-data로 명시해주어야 한다.

    UIImage를 바이너리 타입으로 변환

    // pngData()라는 메서드도 있다.
    // 크기가 큰 이미지를 서버로 보내려고 하면 통신이 안되는 경우도 있는데 아래와 같이 압축해서 보내면 해결할 수 있다.
    guard let imageData = imageView.image?.jpegData(compressionQuality: 0.5) else { return }
    
    TIL Done day30 
    opened by Taehyeon-Kim 2
  • [220804] TIL

    [220804] TIL

    서버 통신 시 셀에 보여줄 UIImage 변환 시점

    urlString ▶️ url ▶️ image

    url로 바꾸고 또는 image로 바꾸는 과정을 어디에서 진행하는 것이 좋을까?

    1. 서버 통신 시점에서 할지 => 시간이 오래걸리고, 사용자가 보지 않을 수 있는 정보에 대해서도 작업을 진행할 수 있어서 비효율적
    2. 셀에서 처리할지 => 조금 더 적절해보인다.

    마찬가지로 서버 통신을 셀에서 할 경우 셀이 꺼내질 때마다 요청이 들어가 call 수가 증가할 수 있다.

    Alamofire의 데이터 받아오는 메서드

    Serialization, Deserialization

    Serialization

    • 직렬화
    • Encoding
    • 외부에서 알아들을 수 있는 형태로 변환

    Deserialization

    • 역직렬화
    • Decoding
    • 시스템에서 사용할 수 있는 형태로 변환

    Pagination

    swift에서 구현하기

    1. will display cell 이용
    • 셀이 그려지기 전에 호출, 실제 셀을 그려주는 역할은 cell for row at이 함
    • 예상치 못한 방식으로 동작할 수 있음
    1. scrollView의 scroll 시점 이용
    • 많이 쓰이는 방식
    • contents의 끝에 도착했을 때 delegate method를 호출해서 적절한 처리를 해주면 됨
    • contentSize, contentOffset 개념을 이해해야 함
    1. DataSourcePrefetching 프로토콜 이용
    • 가장 적합한 방식에 가까움
    • 작업 취소 기능도 포함 (만약 사용자가 스크롤을 너무 빨리 한다면 중간 중간 취소를 하는 것이 효율적일 수 있기 때문에 적절한 상황에 이용하기)

    클로저

    • 이름이 있는 함수 = 메서드 함수
    • 이름이 없는 함수 = 클로저 함수
    TIL Done day24 
    opened by Taehyeon-Kim 2
  • 타입 추론과 타입 어노테이션의 속도 차이에 관하여

    타입 추론과 타입 어노테이션의 속도 차이에 관하여

    타입 추론과 타입 어노테이션의 속도 차이에 관하여

    그 동안 막연하게도 타입 어노테이션(명시)가 컴파일 속도가 더 빠르다고 생각했던지라 아무 생각 없이 타입 명시를 하는 습관을 들이고 있었다. 그러나 최근 듣고 있는 교육 과정에서 멘토님께서 타입 추론을 하는 것이 더 나아보인다라는 말씀을 해주셨고, 왜인지 궁금했던지라 여쭤보게 되었다. 답변 주신 것으로는 컴파일러의 성능이 점점 더 개선되고 있고, 타입 추론이 컴파일 속도가 더 빠르다는 실험 결과도 있다고 답변주셨다.

    실제로 아래에 첨부한 링크를 보면 간단한 실험 결과를 확인해볼 수 있다.

    let a = "hello, world!" // type is inferred
    let b = String("hello, world!") // type is inferred from String(...) and then passed to the root (the constant b)
    let c: String = .init("hello, world!") // type inference is not required
    let d: String = "hello, world!" // type inference is not required
    

    결과를 보면 1번(타입 추론)을 한 것이 속도가 가장 빨랐다.

    Benchmark #1: xcrun swiftc -typecheck a.swift
      Time (mean ± σ):     175.7 ms ±   3.5 ms    [User: 82.9 ms, System: 81.9 ms]
      Range (min … max):   171.0 ms … 182.8 ms    16 runs
    
    Benchmark #1: xcrun swiftc -typecheck b.swift
      Time (mean ± σ):     224.8 ms ±   2.8 ms    [User: 131.1 ms, System: 81.7 ms]
      Range (min … max):   220.2 ms … 228.2 ms    13 runs
    
    Benchmark #1: xcrun swiftc -typecheck c.swift
      Time (mean ± σ):     672.3 ms ±   8.0 ms    [User: 568.3 ms, System: 93.7 ms]
      Range (min … max):   662.4 ms … 685.1 ms    10 runs
    
    Benchmark #1: xcrun swiftc -typecheck d.swift
      Time (mean ± σ):     213.3 ms ±   2.0 ms    [User: 119.8 ms, System: 81.6 ms]
      Range (min … max):   210.2 ms … 216.5 ms    13 runs
    

    나는 타입을 추론하는데 더 많은 리소스가 들 것이라고 그냥 생각하고 있었는데 타입 추론이 속도가 더 빠르다니... 물론 실험 결과 중 1가지이긴 하지만 되게 신기했다. 덧붙여서 멘토님께서는 ***타입을 명시하게 되면 컴파일러가 명시된 타입과 초깃값을 비교하는 작업이 추가되어서 더 느리고, 애초에 타입 명시와 타입 추론 속도 차이 자체도 밀리세컨드 단위 차이로 미세하다***라고 말씀 해주셨다.

    컴파일 성능 자체에 영향을 크게 주는 것이 아니라면, 타입 명시를 하나하나 해주는 것은 정말 비효율적인 작업일 것이다. 타입 추론을 하는 방향으로 코드 작성 습관을 바꾸도록 해야겠다. 그리고 확실한 근거 없이 막연히 무엇이 더 좋겠다라고 생각했던 나 자신을 반성하고자 한다.

    Done Swift 
    opened by Taehyeon-Kim 2
  • 쇼핑 목록 리스트에 Realm Database 구현하기

    쇼핑 목록 리스트에 Realm Database 구현하기

    📍 Issue

    쇼핑 목록 리스트에 Realm Database 구현하기

    ✅ To-do

    • [x] SceneDelegate 시작 화면 변경하기
    • [x] Realm Database 추가
    • [x] 데이터 저장
    • [x] 데이터 로드
    • [x] 데이터 바인딩
    • [x] 데이터 삭제
    • [x] 데이터 업데이트(체크, 즐겨찾기 반영)
    • [x] UIMenu + Realm 정렬/필터 기능 구현

    220824

    • [x] DataBaseManager 싱글톤 클래스 생성 + 코드 수정
    • [x] FileManager 이용해서 Document에 사진 저장, 조회, 삭제 구현
    Done Assignment day35 day36 day37 
    opened by Taehyeon-Kim 1
  • [220822] TIL

    [220822] TIL

    Notification.Name

    • 기본적으로 제공되는 Notification이 많다.

    awakeFromNib, init

    특성에 맞게 어느 것이 호출되는 것이 더 적절한지 확인해본다.

    1. SB, CB 둘 다 호출이 되는지 확인해본다.
    2. 어떤 것이 먼저 호출되는지 확인해본다. (Break Point 확인)

    화면을 띄울 때

    1. viewDidLoad()에서 Alert을 띄울 수 없다. (viewDidLoad는 화면을 띄우기 직전이라고 생각하면 됨, viewDidAppear에서 호출하기)
    2. 화면을 항상 현재 화면에서 present, push 하는 것은 아니다. 현재 window의 rootViewController에서 띄우는 경우도 많다.

    SnapKit

    1. make
    2. remake
    3. update

    셀 레이아웃(Cell Layout)

    셀 레이아웃을 잡을 때는 contentView위에 구현해주자.

    제스처

    • 하나의 객체에 등록할 수 있는 제스처는 1개이다. 2개 이상 들어갔을 때 에러가 발생할 수 있다. (- responder chaining)
    • 기본적으로 cell - select (gesture) 들어가 있는데 여기에 제스처를 넣어주면 에러가 발생할 수 있다.
    • 스크롤 뷰에도 기본적으로 pinch와 swipe 제스처가 있다. 여기에 다른 제스처를 또 넣어주면 에러가 발생할 수 있다.

    DataBase

    데이터를 저장한 파일들의 집합체

    • UserDefaults: Apple이 제공되는 경량화된 DB
    • Realm: 일기 앱, 메모 앱

    DBMS

    • 데이터베이스를 관리하기 위한 시스템 소프트웨어

    RDBMS

    • 테이블 구조
    • 테이블 안에다가 데이터를 넣어두는 구조
    • 엑셀 테이블을 하나 만든다라고 생각하면 편함

    Terms

    • Schema/Table
    • Column(열 하나)
    • Record(행 하나)
    • PK, FK, Unique Key

    데이터 갱신 문제

    present를 overCurrentContext, overFullScreen로 실행하고, dismiss하면 viewWillAppear가 실행되지 않는다.

    // A.swift
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print(#function)
        
        // 화면 갱신은 화면 전환 코드 및 생명 주기 실행 점검이 필요하다.
        // present, overCurrentContext, overFullScreen > viewWillAppear가 실행되지 않는다.
        // RootView가 그대로 남아있기 때문이다.
    }
    
    ...
    
    @objc func plusButtonClicked() {
        let vc = WriteViewController()
        vc.modalPresentationStyle = .fullScreen
        present(vc, animated: true)
    }
    

    Realm

    • 오픈 소스 개체 데이터베이스 관리 시스템
    TIL Done day35 
    opened by Taehyeon-Kim 1
  • [220805] TIL

    [220805] TIL

    클로저

    • 함수의 형태와 함수의 호출 구조를 잘 이해한다면 쉽게 받아들일 수 있을 것 같다.
    // 다음도 잘 구분할 수 있으면 클로저의 이해를 도울 수 있다.
    func example() {}
    
    example       // 함수 자체
    example()     // 함수 호출
    

    기본 구조

    클로저 헤더와 클로저 바디 부분을 잘 이해하자.

    { (매개 변수) -> 리턴 타입 in	// 클로저 헤더
      실행 구문			// 클로저 바디
    }
    

    인라인 클로저 (inline closure)

    // 코드를 생략하지 않고 클로저 구문 씀, 함수의 매개변수 내에 클로저가 그대로 들어간 형태
    // => 인라인 클로저
    getStudyWithMe(study: { () -> () in
        print("주말에도 공부하기")
    })
    

    트레일링 클로저 (trailing closure)

    // 함수 뒤에 클로저가 실행
    // => 트레일링 클로저(= 후행 클로저)
    getStudyWithMe() { () -> () in
        print("주말에도 공부하기")
    }
    

    매개변수(+ 반환값)가 있는 클로저

    let result = { (number: Int) -> String in
        return "행운의 숫자는 \(number)입니다."
    }
    

    클로저 표현식 변환 과정

    randomNumber(result: { (number: Int) -> String in
        return "행운의 숫자는 \(number)입니다."
    })
    
    randomNumber(result: { (number) in
        return "행운의 숫자는 \(number)입니다."
    })
    
    randomNumber(result: { (number) in
        "행운의 숫자는 \(number)입니다."
    })
    
    randomNumber(result: {
        "행운의 숫자는 \($0)입니다."
    })
    
    randomNumber {
        "행운의 숫자는 \($0)입니다."
    }
    

    Non-escaping, Escaping 클로저

    Non-Escaping 클로저

    • 함수의 실행이 종료되기 전에 실행되는 클로저

    Escaping 클로저

    • 클로저가 함수의 인자로 전달됐을 때, 함수의 실행이 종료된 후 실행되는 클로저
    • 서버 통신이 끝난 후에 외부에 값을 전달하고자 할 때 사용하고는 함 (이 예에 한정되지 말고, 원리를 이해하는 것이 중요)

    고차함수

    • map, filter, closure
    • 일반 반복문보다 속도가 빠름
    • CFAbsoluteTimeGetCurrent() 메서드로 시간 차이를 측정해보자.
    • 진짜 고차함수를 잘 쓰는 것이 중요하다는 것을 많이 느끼고 있다.

    외부함수, 내부함수

    • 외부함수와 내부함수의 생명주기의 관찰도 중요한 부분인 것 같다.
    • 일반적으로 함수가 종료되면 메모리에서 내려가게 된다.
    • 그렇다면 외부함수가 종료되었을 때 그 내부에 존재하던 내부함수 또한 메모리에서 내려가야 하는 것이 아닐까?
    • 그런데 내부함수의 생명주기는 외부로부터 차단되어 있다. 이를 은닉성이라고 표현한다.
    • 내부함수를 외부함수에서 반환해서 어떠한 변수나 상수에 담아서 사용하게 되면 외부에서도 접근할 수 있게 된다.
    • 이렇게 되면 외부함수가 종료되었다고 하더라도 내부함수는 곳곳에서 사용할 수 있게 된다.
    • 떠돌이가 되는 것이다.
    • 클로저를 사용하게 되었을 때, 주변 환경에 포함된 변수나 상수가 메모리에 남아있을 수 있는 것인데 이를 값이 캡처되었다고 표현한다.
    • 값의 캡처에 대해서는 다시 한 번 살펴보도록 하자.

    필요에 의해 역할과 관심사를 분리하다보면 자연스럽게 아키텍처와 패턴을 찾아보게 되고, 그런 코드 작성 방식에 가까워진다.

    이후에 공부는 해야겠지만 너무 얽매이지 말자.

    네트워크 코드에 관해

    • Controller에 작성하는 코드 라인 수가 증가하면서 역할과 코드의 분리에 대해서 생각을 하게 된다.
    • 보통 네트워크 코드는 따로 분리해서 작성하는 편이며, Manager, Service 등등의 다양한 단어를 붙여서 클래스를 구성한다.
    • 통신 받아온 값을 Controller에서 사용하기 위해 escaping closure를 사용한다.
    • indicator 또는 progress bar를 사용하여 ux를 고려할 필요가 있다.
    TIL Done day25 
    opened by Taehyeon-Kim 1
  • [220803] TIL

    [220803] TIL

    인증키와 gitignore

    1. 항상 gitignore는 먼저 처리하자. 이후에 인증키를 처리하려고 하면 commit에도 남아있고, 이전 기록에 남아있으므로 번거롭다.
    2. 프로젝트 내에서 empty 파일 생성 후 프로젝트 바로 밑에 .gitignore 생성 가능
    3. 협업 시에는 property list, configuration을 이용하는 식으로도 인증키를 관리한다.
    4. 숨겨야 하는 파일이 많으면 public repository가 적합한지부터 판단하자.
    5. gitignore.io에 가면 쉽게 파일에 들어갈 내용을 만들 수 있다.
    6. 숨김파일로 잘 등록하면 프로젝트 내의 파일 옆에 A(추가)/M(수정) 마크가 뜨지 않는다.

    Type Inference와 Type Annotation 속도 차이

    Type Annotation을 이용하기로 하자. 자세한 내용은 블로그 글 참고 바람.

    날짜 계산

    • TimeInterval 이용
    • Calendar 이용 (Apple에서 권장 하는 편)
    • Date, DateFormatter, Calendar 잘 정리해보자.

    네트워크 통신

    • 서버 통신에 대한 예외 처리 잘하기
    • 네트워크 속도가 느린 환경 테스트 필요, 실기기 테스트 시 condition 조절이 가능하다.
    • 한글로 쿼리를 날릴 때 인코딩 필요(utf-8방식 이용) : addingPercentEncoding , .urlQueryAllowed character set 이용

    Pagination (페이지네이션)

    • 데이터가 많은 상황을 가정해보자.
    • 많은 데이터를 적당한 리소스로 분할하는 것이 필요하다.
    • 크게 offset, cursor 기반 페이지네이션으로 나뉜다.
    • iOS에서 구현하는 방법은 크게 3가지 정도가 있다. 다음 TIL에서 내용 확인 바람.

    소켓 vs HTTP

    • 음악, 채팅과 같은 기능은 소켓 통신 방식을 이용해서 구현하는 편이다.
    • 연결을 끊지 않고 통신을 유지하는 것이 필요하고 실시간성이 보장되어야 하기 때문이다.
    • 또한, 양방향 통신으로 이루어진다.

    First Class Object (일급 객체)

    1. 객체
    2. 함수
    3. 프로토콜

    일급 객체의 특성

    1. 변수, 상수에 함수를 넣을 수 있음
    2. 반환 타입으로 함수 사용 가능
    3. 인자 값으로 함수 사용 가능
    TIL Done day23 
    opened by Taehyeon-Kim 1
  • [220727] TIL

    [220727] TIL

    뷰와 데이터 관련한 것은 분리하도록 하자.

    역할을 분리해서 함수를 작성하자.

    UIViewController + UITableView

    UITableViewController만 사용할 수 있으면 얼마나 편할까? 그러나 UITableViewController를 사용하는 경우에는 좀 더 유연한 화면 구성이 어렵다. 이미 화면 전체가 테이블뷰로 가득 차 있어 영역의 크기 조정이 어렵기 때문이다. (이 말인 즉슨 RootView가 UITableView라는 것이다.) 그렇기에 TableView만 따로 올려서 화면을 구성하는 경우가 더 많다.

    1. TableView 생성 + 아웃렛 연결
    2. TableViewCell 생성 (프로토타입 셀, XIB 이용) + 셀 클래스 연결 + 아웃렛 연결
    3. TableView에 필요한 프로토콜 선언 + 필수 메서드 구현
    4. 뷰 객체와 프로토콜 연결(위임)

    Property Observer

    저장 프로퍼티에서 사용된다. 프로퍼티의 값이 변경될 때마다 호출된다.

    • willSet (newValue) : 값이 변경(저장)되기 직전에 호출
    • didSet (oldValue) : 값이 변경(저장)된 이후에 호출
    var nickname: String {
        willSet(newNickname) {
            print("유저 닉네임이 \(nickname)에서 \(newNickname)로 변경될 예정이에요")
        }
        didSet {
            print("유저 닉네임 변경 완료!!!! \(oldValue) -> \(nickname)으로 바뀜!")
        }
    }
    
    static var totalOrderCount = 10 {
        willSet {
            print("총 주문 건수가 \(totalOrderCount)에서 \(newValue)로 변경될 예정입니다.")
        }
        didSet {
            print("총 주문 건수가 \(oldValue)에서 \(totalOrderCount)로 변경되었습니다.")
        }
    }
    
    TIL Done day18 
    opened by Taehyeon-Kim 1
  • Raw Strings

    Raw Strings

    Swift5부터 지원하는 문자열 표현 방법에 대한 개선점을 같이 알아봅시다.

    SE-0200 Enhancing String Literals Delimiters to Support Raw Text

    많은 다른 언어와 마찬가지로 Swift는 이스케이프 문자( \ )를 사용해서 문자열 리터럴 내에서 후속 문자의 특별한 해석을 만듭니다. 이스케이프 문자 시퀀스는 문자열 구분 기호(큰 따옴표), 이스케이프 문자(백 슬래시), 문자열 보간 등에 대한 문자 집합을 나타냅니다.

    사실 이스케이프 문자를 사용하는 것은 너무 귀찮은 일이고, 문자열 리터럴 안에 많은 이스케이프 시퀀스가 포함되어 있으면 읽기 어렵습니다. 이를 Apple에서 알아주었는지 Swift 5부터는 조금 더 단순하고 깔끔하게 문자열 리터럴 구문을 작성할 수 있게 되었습니다.

    사용법: Hash(#) 구분 기호 사용

    해시(#) 구분 기호를 사용해서 단순하고 깔끔한 구문을 작성할 수 있습니다.

    1. 기본 사용법

    let rawStrings = "Hello, \"Raw Strings\"."
    
    let rawStrings = #"Hello, "Raw Strings"."#
    
    Output)
    Hello, "Raw Strings".
    Hello, "Raw Strings".
    

    2. 이스케이프 시퀀스의 역할을 유지하고 싶을 때

    Raw String에서는 모든 문자와 이스케이프 시퀀스가 그대로 출력이 됩니다. 줄바꿈도 하고 싶고, 그냥 백 슬래시도 쓰고 싶은데 어떡하죠? 두 번째 코드처럼 작성하면 문제를 해결할 수 있습니다.

    let escapeStrings = #"줄을 바꾸고 싶어요. \n\n 여기서 부터요."#
    // output)
    // 줄을 바꾸고 싶어요. \n\n 여기서 부터요.
    
    let escapeStrings = #"줄을 바꾸고 싶어요. \#n\#n여기서 부터요."#
    // output)
    // 줄을 바꾸고 싶어요. 
    //
    // 여기서 부터요.
    

    3. 변수와 함께 사용하고 싶을 때 (- 문자열 보간법)

    해시 기호의 개수는 사용하는 부분에서 동일하게 맞춰주기만 한다면 문제가 없습니다. 특별한 이유가 없다면 1개만 쓰는 것이 낫겠죠?

    var onlineService = "WhaleOn"
    var finalNotice = ##"온라인 라이브 수업은 \##(onlineService)으로 진행합니다."##
    // output)
    // 온라인 라이브 수업은 WhaleOn으로 진행합니다.
    

    4. 여러 줄에서 사용하고 싶을 때

    시작과 끝에 해시 기호를 붙여주면 됩니다.

    let number: Int = 2
    let multiline = #"""
    This is
    SeSAC \#(number).
    """#
    

    5. 정규식 사용 시

    How to use raw strings in Swift 5 아티클을 읽어보면 정규식을 사용할 때에도 Raw String이 유용하게 사용될 수 있다는 것을 확인할 수 있습니다. 기존에 정규식을 작성해 본 사람이라면 백 슬래시()가 많이 사용되는 것을 경험해보셨을 것입니다. 문자열 리터럴 내에서 백 슬래시를 올바르게 사용하려면 또 하나의 백 슬래시를 붙여줘야 했었죠. 이러한 귀찮음, 복잡함을 해시(#) 기호를 붙임으로서 해결할 수 있습니다.

    let regex = try NSRegularExpression(pattern: "\\\\\\([^)]+\\)")
    
    let regex = try NSRegularExpression(pattern: #"\\\([^)]+\)"#)
    

    기존 정규식의 사용되던 백 슬래시의 수를 절반으로 줄일 수 있고, 또한 가져온 정규식 표현을 그대로 사용할 수 있다는 장점이 있습니다.

    Done Assignment day7 
    opened by Taehyeon-Kim 1
  • Unit 테스트

    Unit 테스트

    • 작은 단위로 테스트 진행
    • 소스 코드 기준으로 테스트 진행
    • 속도가 상대적으로 빨라야 함
    • 테스트는 항상 같은 결과를 반환해야 함 -> Repeatable
    • 다른 테스트에 영향을 주지 않도록 고립시켜서 코드를 작성해야 함 (종속적인 부분을 제거해야 함)
    setUpError() throws
    tearDownWithErrors() throws
    
    • setUpError : 인스턴스 생성
    • tearDownWithErrors : 초기화 / 테스트간 영향을 줄 수 있는 부분을 방지하기 위함
    Unit 테스트 
    opened by Taehyeon-Kim 2
  • Swift 정리(2)

    Swift 정리(2)

    함수

    함수, 매개변수, 반환값

    조건문의 사용

    • 단락평가 (논리식에서 결과 도출에 필요한 최소한의 코드 조건만 실행하는 것)
    • Short Circuit Evaluation
    • https://velog.io/@din0121/Operator

    매개변수

    • 외부(argument label) : 함수 호출 시에 사용, argument : call 시에 실제 사용되는 값
    • 내부(parameter) : 함수 안에서 사용
    • https://eunjin3786.tistory.com/465
    • 와일드 카드(_) 패턴 : 외부 매개변수 대체
    • 매개변수의 기본값 : 전달되는 인자가 없을 때 기본적으로 사용되는 값
    func greeting(to name: string = "손님")
    
    // 오버로딩 가능
    // greeting()
    // greeting(to:)
    
    • inout 매개변수
    • 가변 매개변수 (...) : 여러 개의 타입을 가변 매개변수로 사용 가능

    반환값

    • Implicit return / 생략 가능
    • 반환값 없음 void, [], ()
    • @discardableResult
    • print vs return
    • https://www.hackingwithswift.com/forums/swift/about-print-and-return-what-makes-them-different-from-each-other/1382

    프로퍼티/메서드

    • 인스턴스 : let var func
    • 타입 : static, class - 메모리에 한번만 올라감, 앱 종료시까지 유지됨, 컬러/폰트 등에 사용, 처음 접근시에 올라감(지연 초기화 방식으로 동작)

    프로퍼티

    • 저장(stored) : 메모리에 공간 필요
    • 연산(computed) : 메모리에 공간 불필요, 열거형에서 많이 보임, get/set 구문(set: newValue)
    • 옵저버(observer) : willSet(newValue), didSet(oldValue)

    mutating

    • 값 타입의 경우 기본적으로 수정이 불가능함
    • 값을 변화시키고 싶을 때 mutating 키워드를 사용함
    • https://velog.io/@wonhee010/mutating

    클래스 vs 구조체

    |클래스|구조체| |:--|:--| |참조 타입|값 타입| |상속 o|상속 x| |타입 캐스팅 가능|-| |타입 캐스팅에서 에러가 발생하면 런타임 에러 발생|| |ARC|| ||멤버와이즈 이니셜라이저|

    Dispatch

    • static vs dispatch
    • 메서드가 메모리에서 동작하는 방식

    Static Dispatch

    • 성능 최적화와 관련
    • final keyword (컴파일 타임에 확인할 것이 줄어듬, 범주 제한)
    • class는 기본적으로 Dynamic Dispatch로 동작 (final class -> static dispatch로 동작하도록 변경)
    • https://jcsoohwancho.github.io/2019-10-11-Dynamic-Dispatch%EC%99%80-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94/
    Swift 
    opened by Taehyeon-Kim 0
  • UI 테스트

    UI 테스트

    테스트

    CI/CD

    스크린샷 2022-11-29 오전 10 34 45

    • 어플리케이션 개발 단계의 자동화를 통해, 짧은 주기로 고객에게 애플리케이션을 제공
    • 일부 단계를 자동화(ex. 회원가입 플로우)

    CI: 지속적 통합

    • 코드 레벨 테스트 자동화
    • ex. 핸드폰 번호 정규식, 이메일 유효성 검증 등

    CD: 지속적 서비스 제공/배포

    • 프로덕션 환경 릴리즈

    fastlane

    • Code Signing
    • Appstore Deployment
    • TestFlight Deployment
    • Automatic ScreenShots
    • CI에 가까운 툴 -> CD기능까지 구현하려면 외부 툴을 붙여서 많이 사용(ex Bitrise 등..)

    Test Pyramid

    • Testing fundamentals
    • User Interface - Integration - Unit
    • Unit Test(단위 테스트)
    • Integration(통합 테스트) : 작은 단위의 테스트는 통과해도 통합 테스트는 실패할 수 있음
    테스트 
    opened by Taehyeon-Kim 1
  • Swift 정리(1)

    Swift 정리(1)

    변수와 함수

    변수 -> 프로퍼티 함수 -> 메서드

    명칭

    • https://enterkey.tistory.com/165
    • 클래스, 구조체, 열거형(특정 범위 내, 특정 객체) 안에서 쓰이는 것들을 프로퍼티, 메서드라고 부를 수 있다.
    • 함수 내에서 확인해본다면 프로퍼티보다는 변수라고 볼 수 있다.

    변수

    • 컬렉션 타입의 종류와 특징은 무엇인가?

    왜 컬렉션 타입인가(정의)

    • 컬렉션 타입의 자체의 특성
    • 어떤 프로토콜을 채택하고 있는가, 어떤 기능을 하고 있는가
    • Collection 프로토콜을 채택하고 있는 묶음 -> Collection 프로토콜은 무엇인가 -> Iterator, Sequence
    • Copy on Write
      • 처음에는 복사하지 않고, 값이 변경되거나 수정되면 값을 복사되는 것
      • 같은 데이터를 갖는 주소값을 공유하는 것

    종류와 특징

    • 배열, 딕셔너리, 집합

    Foundation, UIKit

    • Int, String은 왜 Struct이지? -> Foundation / -> Class라면 Element 하나하나에 대한 추적이 어렵다
    • UIKit은 왜 Class 기반이지? -> 이 사람들은 왜 그렇게 만들었나

    Foundation

    데이터와 연관되어 있는 대부분의 녀석들, 근간이 되는 프레임워크

    • String, Int 등의 데이터 타입
    • Date
    • Network 객체들(URLSession)
    • FileManager

    옵셔널

    옵셔널에 대해 아는대로 설명하시오.

    • 구조부터 시작하자. -> 사용방법은 그 이후다.
    • 옵셔널은 열거형으로 이루어져있다.
    • 열거형은 제네릭형태로 이루어져있다.
    • case는 2가지로 정해져있다. 값이 있을수도 있고, 없을 수도 있음을 나타낼 수 있다.
    • 옵셔널로 인해 런타임 이슈가 발생할 수 있다.
      • 런타임 이슈를 발생하지 않도록 하기 위해, 옵셔널 바인딩/옵셔널 체이닝/언래핑(묵시적 해제/강제 해제) 등등의 방법을 사용할 수 있다.
      • 체이닝 : 점근법으로 하위 속성으로 들어갈 때 옵셔널을 판단해주는 방식, 체이닝 역시 !/?를 사용할 수 있다. ! 는 강제해제와 같은 방식으로 동작해서 런타임에러가 발생할 수 있습니다.
      • 바인딩 : guard - let, if - let -> 목적은 언래핑, Swift 5.7에서 문법 구조가 변경됨.
    • 열거형은 컴파일 타임에 이슈를 잡을 수 있다.

    컴파일, 런타임 이슈

    • 컴파일 타임과 런타임 타임을 설명해보시오.

    열거형

    • 컴파일 시점에 모두 대응이 가능 -> 그렇기 때문에 인스턴스를 만들필요가 없음
    • 인스턴스 생성 x
    • 메모리에 이미 다 올라감
    • 멤버와 값을 분리 -> 우리는 일반적으로 프로퍼티와 메서드, 즉 객체 안에 들어있는 것들을 멤버라고 부른다. case 역시 열거형 안에 들어있는 것이기 때문에 멤버라고 부른다.
    • case(-멤버), 원시값(rawValue), 연관값(associateValue)
    • case로 대응하기 어려운 값들이 있으니 연관값을 사용한다.
    • 어트리뷰트 키워드(@frozen, @unknown) -> 컴파일과 관련
    • CaseIterable
    Swift 
    opened by Taehyeon-Kim 2
Owner
Taehyeon Kim
Wanna be  iOS Developer
Taehyeon Kim
SeSAC(Seoul Software Academy Cluster) iOS Project

Product Name Short blurb about what your product does. One to two paragraph statement about your product and what it does. Installation OS X & Linux:

Minjun Kim 2 Nov 4, 2021
A simple Swift package for measuring and reporting the time taken for operations

Duration A simple Swift package for measuring and reporting the time taken for operations. It is derived from a version for Playgrounds that I blogged

Swift Studies 325 Nov 6, 2022
In-App iOS Debugging Tool With Enhanced Logging, Networking Info, Crash reporting And More.

The debugger tool for iOS developer. Display logs, network request, device informations, crash logs while using the app. Easy accessible with its bubble head button ?? . Easy to integrate in any apps, to handle development or testing apps easier. First version, there is plenty of room for improvement.

Remi ROBERT 1.8k Dec 29, 2022
Awesome bug reporting for iOS apps

Buglife is an awesome bug reporting SDK & web platform for iOS apps. Here's how it works: User takes a screenshot, or stops screen recording User anno

Buglife 498 Dec 17, 2022
Dotzu In-App iOS Debugging Tool With Enhanced Logging, Networking Info, Crash reporting And More.

Dotzu In-App iOS Debugging Tool With Enhanced Logging, Networking Info, Crash reporting And More. The debugger tool for iOS developer. Display logs, n

Remi ROBERT 1.8k Jan 3, 2023
Buglife-iOS - Awesome bug reporting for iOS apps

Buglife is an awesome bug reporting SDK & web platform for iOS apps. Here's how it works: User takes a screenshot, or stops screen recording User anno

Buglife 498 Dec 17, 2022
Lightweight MetricKit-based diagnostics reporting

MeterReporter Lightweight MetricKit-based diagnostics reporting. MeterReporter will capture MetricKit payloads and relay them to a backend. It uses Me

Chime 24 Dec 26, 2022
In-app feedback and bug reporting tool for apps.

Instabug iOS SDK Instabug is an in-app feedback and bug reporting tool for mobile apps. With just a simple shake, your users or beta testers can repor

Instabug 274 Dec 14, 2022
Daily News is a news app with good looking user interface ! Apps architecture is MVVM and used RxSwift for binding.

Daily News Hey ! Daily News is a news app with good looking user interface ! Apps architecture is MVVM and used RxSwift for binding. Architecture I pr

Latif Atci 39 Dec 13, 2022
Are you sure the chemical compounds of your daily use are 100% safe? Use Chem-Aware, identify them right now!

View Project On Devpost: Built With: PubChem's REST API How To Install Chem Aware: Prerequiste: Latest Version of Xcode and Simulators installed The a

Jerry Zhang 5 Aug 23, 2022
🎸🎸🎸 Common categories for daily development. Such as UIKit, Foundation, QuartzCore, Accelerate, OpenCV and more.

?????? Common categories for daily development. Such as UIKit, Foundation, QuartzCore, Accelerate, OpenCV and more.

77。 423 Jan 4, 2023
News app to see daily news from new York Times

News This project is demo project for newyork time apis news feed. Generally thi

kamalesh 0 Dec 18, 2021
An open-source task management app for daily general operations

Taskaholic An open-source task management app for daily general operations, sepa

Aiden 1 Sep 19, 2022
SwiftUI iOS app for tracking daily hydration, logs to HealthKit!

HydrationCompanion SwiftUI iOS app for tracking daily hydration, logs to HealthKit! Screenshots: Home view: see all intake logs and progress Settings

Jesse Liu 7 Dec 31, 2022
Apple's SwiftUI Essentials Series. An iOS app that helps users manage their daily scrums.

Scrumdinger (Work in progress) Apple's SwiftUI Essentials Series An iOS app that helps users manage their daily scrums. To help keep scrums short and

Vinícius Moreira 1 Feb 14, 2022
WordleAverage - Adds an Average Guesses statistic to the viral daily word game Wordle

WordleAverage Adds an "Average Guesses" statistic to the viral daily word game W

null 0 Jan 26, 2022
A simple to use yet very powerful tool for the tech heads looking for daily dose of tech news

A simple to use yet very powerful tool for the tech heads looking for daily dose of tech news. This app is built using SwiftUI and also uses catalyst to run on MacOs as well.

Dishant Nagpal 1 Feb 27, 2022
Skredvarsel app - an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Skredvarsel (Avalanche warning) app is an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Jonas Follesø 8 Dec 15, 2022
👨‍💼Reduce daily routine with sasha

Sasha is an easy-to-use CLI app for routine designer tasks. Features • Using • Installing • Author • License Features Icon slicing for different platf

Artem Novichkov 29 Jun 10, 2022
iScheduleYourDay is a watchOS 8.5 app that can help order your daily tasks

Currently developing an App for watchOS 8.5 to help order your tasks daily. The app is a simple approach to the actual Apple App Remainders to become an improved version of it

Marta Granero I Martí 2 Aug 11, 2022