Coder Social home page Coder Social logo

ios-open-market's Introduction

iOS Engineer at Hyundai Motor Group (2023.03 ~)

  • working on next-generation Connected Car Service Applications that integrate with Hyundai, Kia, and Genesis brands to provide global customers with improved connectivity.

  • using SwiftUI and The Composable Architecture(TCA), etc.

iOS Developer at Flitto (2022.06 ~ 2023.02)

About Me

Education

  • Yagom Academy iOS Career Camp

    • 2021-10-04 ~ 2022-04-01 (6 months)
    • studied Swift, UIKit, SwiftUI, HIG, git/github
    • completed 9 projects with pair programming and code reviews.
    • 🎨 See all projects
  • Yagom Academy iOS Starter Camp

    • 2021-08-02 ~ 2021-09-03 (5 weeks)
    • studied basic Swift
  • 🎓 Korea Univ. ('17)

    • BS in Science & Economics (double major)

Hits

ios-open-market's People

Contributors

jager-yoo avatar yagom avatar yeahg-dev avatar

Stargazers

 avatar  avatar

Forkers

yeahg-dev

ios-open-market's Issues

TableViewCell 내부의 오토레이아웃 충돌 이슈 해결

💣 문제 상황

앱을 실행할 때마다, 콘솔로그에 반복적으로 오토레이아웃 관련 이슈가 프린트돼서 불편함을 느끼던 도중
이 이슈를 해결해보기로 했습니다.


image


먼저, 콘솔로그에 나타나는 오토레이아웃 관련 에러를 통째로 복사해서("용의자들"이라 지칭해볼게요.)
WTFautolayout 사이트에 입력해서, 문제 상황을 시각적으로 변환해봤습니다!


image


위 캡처에서 확인할 수 있듯이, 문제는 ImageView 의 width 였습니다.
왜냐면, TableViewCellContentView 의 width 에서는 0.15배의 비율로 설정되라고 명령하고
동시에, ImageView 의 height 에서도 특정 비율로 설정되라고 동시에 명령하고 있기 때문이었습니다.

특히, 둘의 우선순위가 모두 1000 으로 설정되어 있어서, 도대체 어떤 명령을 들어야할지, 명확하지가 않았던 것입니다.
저희는 둘 중 하나의 우선순위를 750으로 낮춰서 문제를 해결할 수 있었습니다.


image


✨ 결론

  • 오토레이아웃 이슈는 WTFautolayout 사이트를 적극 이용해보자.
  • 하나의 UI 컴포넌트에 중복해서 Constraint 를 걸면, 우선순위 이슈가 발생한다.
  • Constraint 를 중복으로 걸지 않게 조심해야 하고, 만약 중복으로 걸어야 한다면 우선순위에 차등을 주자! 😄

✅ 추가로 해결된 점

  • 스크롤을 빠르게 움직이면, 글자들이 이상하게 물결치던 현상이 해결됐습니다. 아마 동일한 우선순위로 부여된 2개의 오토레이아웃 사이에서 갈팡질팡(...) 했기 때문에 부들부들 떨었던 것 같아요. 🥶

CollectionViewCell 에서 UILabel 들의 배치가 기기마다 다르게 보이는 이슈

💣 문제 상황

CollectionViewCell 의 height 가 width 의 길이에 비례해 결정되고 있습니다.
따라서, height(높이) 는 cell 내부에 어떤 콘텐츠가, 어떤 높이로 들어가는 지를 반영해주지 못하고 있습니다.

아래 캡처를 보면, 아이팟 터치 7세대와 같은 작은 화면에서는 cell 의 높이가 충분하지 않아서, 제목 Label 이 잘리는 걸 확인할 수 있는 반면
아이폰 11에서는 cell 의 높이가 넉넉하게 주어져서, Label 들간의 간격이 불필요하게 넓어지는 문제가 있습니다.

image
image


✅ 해결 방법

다음에 알아보자.

cell 이 자신의 내부에 담기는 콘텐츠들의 height 값들을 측정해서, 다이나믹하게 intrinsic size가 조정되게 만드는 게 제일 최선의 해결 방법이지 않을까 생각했습니다.

하지만 그걸 구현하는 방법은 아직 찾지 못했습니다. 🤣

빠르게 스크롤링을 하면 페이지네이션이 중복으로 작동하는 이슈

💣 문제 상황

릴리가 앱을 관찰하던 도중, 동일한 상품이 다시 보이는 것 같다는 현상을 제보했습니다.
페이지네이션이 중복으로 되는 것 같다는 가설을 세우고, 검증을 위해 reloadData() 메서드가 불리기 직전에 print문을 삽입해봤습니다.

천천히 스크롤링할 때는 문제가 없었으나, 아주 빠르게 스크롤링을 하면 동일한 페이지가 중복해서 호출되는 현상을 관찰했습니다.

image


🐛 문제 원인

저희는 페이지네이션을 tableView 의 willDisplay 메서드에 조건문을 넣어 구현했습니다.
아래와 같이, 하단에 특정 indexPath.row 까지 보여지는 시점에서 동작하게 만들었는데요, 크기를 비교할 때 >= 부등호를 사용한 게 원인이었습니다.

왜냐면, 부등호 우측의 products.count 는 통신이 완료된 이후에서야 숫자가 증가하는데, 스크롤링을 빠르게 하면 통신이 완료되기 전에 현재 메서드가 여러번 호출되면서 여러 개의 cell 이 guard문을 통과해 페이지네이션이 작동하는 것입니다.

image


🔧 문제 해결

아주 간단하게 문제를 해결했습니다.
부등호를 사용하면, 범위가 되기 때문에 위험한 것이므로, 부등호가 아닌 등호(==)를 사용했습니다.

이렇게 수정하니까, 스크롤링을 빠르게 하더라도 페이지네이션이 중복으로 작동하는 버그는 사라졌습니다!

image

키보드 활성화되면 편집중인 뷰가 잘보이지 않는 이슈

💣 문제 상황

키보드가 활성화되면 키보드의 영역만큼 뷰를 가리면서 편집중인 뷰가 보이지 않는 문제가 발생합니다.

문제 상황 예시
: 상품설명을 편집하려고 키보드를 활성화면 상품설명 TextView 가 가려져서 보여지지 않습니다.


❇️해결 과정

시도1️⃣

UIResponder.keyboardWillShowNotificationUIResponder.keyboardWillHideNotification에 대한 Observer를 상품등록 뷰 컨트롤러에 추가하고, selector에 self.view.frame.origin.y 를 keyboard 높이만큼 수정해주는 메서드를 구현했습니다.

// Keyboard Notification Observer 추가
  private func addKeyboardNotificationObserver() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(keyboardWillShow(_:)),
            name: UIResponder.keyboardWillShowNotification,
            object: nil
        )
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(keyboardWillHide(_:)),
            name: UIResponder.keyboardWillHideNotification,
            object: nil
        )
    }

// Notification이 post되면 호출할 메서드 
extension ProductRegistrationViewController: UITextFieldDelegate {
    
    @objc private func keyboardWillShow(_ sender: Notification) {
        if let keyboardFrame: NSValue = sender.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
            let keyboardRectangle = keyboardFrame.cgRectValue
            let keyboardHeight = keyboardRectangle.height
            self.view.frame.origin.y = -keyboardHeight
        }
    }
    
    @objc private func keyboardWillHide(_ sender: Notification) {
        self.view.frame.origin.y = .zero
    }
}

키보드높이만큼 스크롤이 되지 않는 문제 발생

Jan-25-2022 17-39-55

스크롤뷰의 FrameLayoutGuide가 키보드 높이만큼 올라가서 문제가 발생한것이 아닌가? 추측중입니다...🧐
image

이미지 다운로드가 완료되기 전에 실패 이미지(invalid image)가 잠깐 보이는 이슈

💣 문제 상황

  • 스크롤링을 빠르게 하면, 이미지 다운로드에 실패했을 때 ImageView 에 나오도록 한 invalid image(X 표시가 들어간 회색의 구름 아이콘)가 잠깐 보이는 이슈가 있습니다.

  • 어떤 이유로든 이미지 다운로드가 실패하면, invalid image 를 보여주는 코드를 작성해두었는데요, 통신이 비동기(async)로 이루어지기 때문에 다운로드에 걸리는 잠깐의 시간 동안은 실패가 아니라 로딩 시간이라고 생각했습니다.

  • 즉, 존재하지 않는 URL이거나, 이미지를 다운로드 받던 도중 네트워크가 차단되는 이슈가 아니라면 invalid image 가 보이지 않을 것이라고 생각했는데, 실제 앱은 다르게 작동하고 있었습니다.

  • 아래는 해당 이슈의 분석 & 해결 과정입니다.


🧶 원인 분석

  • 저희가 구현한 setImage 메서드Kingfisher 인터페이스를 참고해서 만들었습니다.
  • URL 주소를 파라미터로 넣으면, 메모리 캐시에 동일한 URL을 가진 이미지가 있는지 체크하고, 없다면 이미지를 다운로드해서 UIImageView 에 할당하는 메서드입니다.
  • UIImageView 타입의 extension 으로 메서드를 만들고, 테이블뷰/컬렉션뷰의 cellForRowAt 메서드가 호출될 때, cell 타입 스스로가 setImage 메서드를 호출해서 비동기(async)로 이미지를 다운받아 UIImageView 를 채우는 로직을 가지고 있습니다.

image

extension UIImageView {
    
    func setImage(with url: URL, invalidImage: UIImage) -> Cancellable? {
        let cacheKey = url.absoluteString as NSString
        
        if let cachedImage = ImageCacheManager.shared.object(forKey: cacheKey) {
            self.image = cachedImage
            return nil
        }
        
        let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self = self else { return }
            
            // 통신이 성공한다면 error 는 nil 이 될 것이므로, 아래 if let 구문은 호출되지 않습니다.
            if let error = error {
                DispatchQueue.main.async {
                    self.image = invalidImage
                }
                print("\(error) 발생!") // 어떤 에러가 �잡히는지 확인하기 위해 print 삽입
                return
            } else { // 통신이 성공한다면 else 문으로 빠집니다.
                DispatchQueue.main.async {
                    guard let imageData = data,
                          let image = UIImage(data: imageData) else { return }
                    self.image = image
                    ImageCacheManager.shared.setObject(image, forKey: cacheKey)
                }
            }
        }
        task.resume()
        return task
    }
}

image

  • 원인은 cell 재사용을 위해 걸어둔 이미지 다운로드 작업 취소 로직 때문이었습니다.

  • 테이블뷰/컬렉션뷰의 cell 이 재사용될 때, prepareForReuse() 메서드가 호출되는데, 만약 완료되지 않은 통신이 걸려있다면, 그걸 취소시키는 로직입니다.

  • 즉, 통신이 취소당하는 것은 -> error를 발생시키고 -> 때문에 cell 에는 invalid image 아이콘이 잠시 보이다가 -> 새로운 이미지 다운로드가 성공하면, 그 이미지로 덮어쓰기되는 것입니다.


✨ 해결 방법

  • task가 취소되면 error가 잡히는 건 피할 수 없을 것이라 생각합니다.
  • 따라서 error.localizedDescription이 "cancelled" 가 아닌 경우에만 invalid image 를 보여주는 조건문을 하나 추가해서 문제를 해결할 수 있었습니다.
if let error = error, error.localizedDescription != "cancelled" {
    DispatchQueue.main.async {
        self.image = invalidImage
    }
    print("❌ 에러 : \(error.localizedDescription) 발생!")
    return
} else {
    DispatchQueue.main.async {
        // 정상적인 이미지 할당 코드
    }
}

TableViewCell의 Label의 위 아래가 잘리는 이슈

💣 문제 상황

작은 기기로 실행시 product price label의 위, 아래가 잘리는 현상이 포착되었습니다.
스크린샷 2022-01-20 오후 5 30 05

🥸 문제 원인 분석

productPriceLabel의 content compression resistance가 vertical이 priority가 750,
productPrice.Top >= prodcutName.Bottom + 9.5 의 priority가 1000 이기 때문에
label의 위아래가 잘리는 현상이 발생했다고 판단했습니다.
스크린샷 2022-01-20 오후 5 38 14

✅ 해결 방법

productPriceLabelproductNameLabel의 vertical content compression resistance priority를 1000으로 지정해주어서
라벨의 글자가 잘리지 않도록 수정했습니다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.