TIL(230220)

Youth·2023년 2월 21일
0

1. Wanted PreOnboarding챌린지 iOS2차 과정

학교수업을 듣고있엇는데 애플아카데미 졸업생 톡방에 이런글이 하나 올라왔다

원티드에서 3월 ios챌린지? 강의?같은걸하는데 이번에는 신청만하면 들을수있는거같다. 어쨌든 이걸 보고 흥미가생겨서 들어가서 봤다. 그런데 사전과제가 있길래 확인을 해봤는데
https://yagomacademy.notion.site/iOS-2-3f670cc9788f4384b000bfe940447d59
여기에 있는 대로 똑같이 만들어서 git에 올린 후 제출하는게 사전과제였다

이걸 봤을때 학교에있어서 노트북도 없고 해서 계속해서 영상을 돌려봤다. 어떻게 만들어야할까를 고민을 해봤다.
우선 가장 먼저 들었던 고민은

1.view를 따로만들어서 view 5개 선언해서 만들기
2.tableView로 만들기

1번 같은 경우, 같은모양의 view가 5개 연속으로 있으니까 이걸 view로 따로 만들어서 mainVC에 view1 view2 view3 ...이런식으로 선언하기에는 조금 찜찜했다 그러면 뭔가 중복되는 코드가 많아질거같아서? 그래서 cell이 5개로 고정이긴 하지만 아무래도 tableView로 만드는게 좋을거같아서 tableView로 만들기로 결정을 했다 뭐 사실 저번 TIL에도 올리긴했지만 이미지 로드같은 경우는 viewcontroller에서 처리할게 아니라 url을 cell에 선언해놓고 cell에서 loadImage같은 함수를 만들어서 이미지를 로드하는게 좋은방법이라는걸 알게되어서 꽤나 쉽게 구현할수있겠다 싶었다.

그런데 문제는 저 Load All Images 버튼으로 모든 cell에 있는 이미지들을 한번에 load시키는 방법이 문제였다. 학교에서 집까지 오는데 한시간정도 걸려서 지하철에서 계속 방법을 생각해봤는데 당최 방법을 모르겠어서 답답하긴했다.

그래도 일단은 구현을 해봤다

    // MARK: - 이미지url을 받아와서 이미지 load는 cell에서 할수있게 코드 구성
    var imageUrl: String?
    
    let imageLoadView = UIImageView()
    
    lazy var imageLoadButton: UIButton = {
        let button = UIButton(type: .system)
        button.createCustomButton(title: "Load", cornerRadius: 10)
        button.addTarget(self, action: #selector(imageLoadButtonTapped), for: .touchUpInside)
        return button
    }()

우선 cell에 이렇게 구현을 해놓으면 이미지 로드버튼을 눌리기전에는 이미지 url만 가지고 있는 상태였다가

    @objc func imageLoadButtonTapped() {
        loadImage()
    }
    
    func loadImage() {
        self.imageLoadView.image = UIImage.makeSFImage(imageString: CustomImage.defaultImage, size: CustomImage.imageSize)
        guard let urlString = imageUrl, let url = URL(string: urlString) else { return }
        DispatchQueue.global().async {
            guard let data = try? Data(contentsOf: url) else { return }
            // 오래걸리는 작업이 일어나고 있는 동안에 url이 바뀔 가능성 제거
            guard self.imageUrl! == url.absoluteString else { return }
            DispatchQueue.main.async {
                self.imageLoadView.image = UIImage(data: data)
            }
        }
    }

버튼을 누르면 그때서야 loadImage()함수를 실행해서 이미지를 받아서 imageview에다가 넣어주는 방식을 채택했다. 뭔가 처음에 머릿속으로만 생각했을때는 이거 delegate를 써서 버튼이 눌리면 viewcontroller에서 reloadData를 해줘야하나 생각했는데 cell에 있는 imageView에 이미지를 넣으면 바로 적용이 되서 보통 데이터를 추가해서 tableView의 데이터를 다시 로드해와야할때만 이걸 사용해야하는구나를 알게되었다

문제는 이제 viewController에 있는 imageAllLoadButton인데

    private lazy var imageAllLoadButton: UIButton = {
        let button = UIButton(type: .system)
        button.createCustomButton(title: "Load All Images", cornerRadius: 10)
        button.addTarget(self, action: #selector(imageAllLoadButtonTapped), for: .touchUpInside)
        return button
    }()

만들어는 놨는데 저 대체 어떤 버튼액션을 줘야할지를 모르겠어서 고민을 정말 많이 했다... cell에 접근해서 cell.loadImage()를 해야하는데 viewController에서 cell로 delegate권한을 준다는 코드는 본적도 들어본적도 없었기 때문에 한시간정도를 고민하다가 원시적인 방법을 사용하기로 했다...

이코드는 정답이 아닌게 분명하고 말그대로 "돌아가는 코드"이기 때문에 추후에 멘토분들에게 여쭤보고 수정할예정이다. 우선 viewModel에 bool값을 하나 선언해준다

class ViewModel {
    var isLoad: Bool = false
    
    // viewModel에 접근해서 imageUrls를 바꿀수있는 가능성 때문에 private으로 선언
    private var imageUrls = [String]()
    
    func fetchImageUrls() {
        imageUrls = ["https://cdn.pixabay.com/photo/2023/01/23/09/26/cat-7738210_960_720.jpg",
                     "https://cdn.pixabay.com/photo/2022/11/20/09/06/night-view-7603847_960_720.jpg",
                     "https://cdn.pixabay.com/photo/2020/05/19/10/05/opel-5190050_960_720.jpg",
                     "https://cdn.pixabay.com/photo/2017/09/07/08/54/money-2724241_960_720.jpg",
                     "https://cdn.pixabay.com/photo/2014/10/23/10/10/dollars-499481_960_720.jpg"
        ]
    }
    
    // imageUrls를 얻고 싶다면 해당 메서드로 얻게끔 설계
    func getImageUrls() -> [String] {
        return imageUrls
    }
}

그리고 viewController에서 버튼을 누르면 isLoad를 true로 바꿔주고 tableView.reloadData()를 해준다

    @objc func imageAllLoadButtonTapped() {
        viewModel.isLoad = true
        imageLoadTableView.reloadData()
    }

그리고 해당 데이터의 속성에따라 분기처리를 해준다

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = ImageLoadTableViewCell.dequeueReusableCell(tableView: imageLoadTableView)
        cell.selectionStyle = .none
        cell.imageUrl = viewModel.getImageUrls()[indexPath.row]
        // MARK: - ViewController에서 Cell에 있는 loadImage라는 함수에 접근해서 실행하고싶은데 방법을 모르겠어서 저장속성의 값에따라 이미지를 로드할수있도록 구현(이미지 전체로드버튼)
        // 분명 더 좋은 방법이있을거같음
        if viewModel.isLoad {
            cell.loadImage()
        }
        return cell
    }

참 창피한 코드이긴하지만 이방법말고 어떤방법을 사용해야할지를 모르겠어서 조금 답답하긴하다.
깃허브에 다른 분들이 올린 코드가있어서 봤는데 한분? 정도를 제외하고는 전부 view를 만들어서 사용하셨다. 한분은 tableView로 구현하셨는데 코드를 잘 이해를 못해서 내 방식대로 구현을 해봤다

enum CustomImage {
    static let defaultImage = "photo"
    static let imageSize: CGFloat = 80
}

enum CellSize {
    static let cellHight: CGFloat = 100
}

enum ProgressSize {
    static let progressHeight: Double = 8
    static var progressRoundCorner: Double {
        return self.progressHeight / 2
    }
}

constant를 만들어서 사용해봤는데 고쳐야할때 여기부분만 수정하면 일일이 찾아서 수정하지 않아서 편해서 좋았다

profile
AppleDeveloperAcademy@POSTECH 1기 수료, SOPT 32기 iOS파트 수료

0개의 댓글