iOS/UIKIT

API를 통해 받아온 데이터를 배열로 저장하고, 이를 갖고 다른 메서드에서는 어떻게 사용할 수 있나?

밤새는 탐험가89 2024. 8. 20. 00:38
override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        
        contentView.addSubview(recommendedDestinationLabel)
        contentView.addSubview(recommendedDestinationImageView)
        contentView.addSubview(destinationLabel)
        contentView.addSubview(homeFeedTable)
        
        configureConstraints()
        homeFeedTableDelegate()
        configureNavi()
        
        getAttractionData()
        getRandomAttraction()
    }
    
    private func homeFeedTableDelegate() {
        homeFeedTable.delegate = self
        homeFeedTable.dataSource = self
    }
    
    private func getAttractionData() {
        NetworkManager.shared.getAttractionData { [weak self] results in
            switch results {
            case .success(let items):
                                
                // 이미지가 있는 항목과 없는 항목을 분리
                self?.attractionsWithImages = items.filter { $0.firstimage?.count != 0 || $0.firstimage2?.count != 0 }
                self?.attractionsWithoutImages = items.filter { $0.firstimage?.count == 0 && $0.firstimage2?.count == 0 }
                
                // 메인 스레드에서 테이블 뷰 갱신
                DispatchQueue.main.async {
                    self?.homeFeedTable.reloadData()
                }
                
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }
    
    private func getRandomAttraction() {
        let selectedItem = attractionsWithImages.randomElement()
        let selectedTitle = selectedItem?.title
        let selectedAddress = selectedItem?.addr1
        let selectedPosterURL = selectedItem?.firstimage ?? selectedItem?.firstimage2 ?? ""
        
        self.recommendedDestinationImageView.configureWithImage(title: selectedTitle ?? "", address: selectedAddress ?? "", posterPath: selectedPosterURL)
    }

 

 

위의 코드에서 getAttractionData() 에서 이미지 유무에 따라 각각의 배열에 저장하도록 했습니다. 

그리고 getRandomAttraction() 메서드에서는 위의 배열 중에서 이미지를 갖고 있는 배열에 대해서 무작위로 데이터를 갖고오도록 했습니다.  위의 코드로 실행할 경우에 실행 결과는 아무것도 나오지 않습니다. 즉, attractionWithImages 배열이 빈배열로 나옵니다. 

 

 

이 문제는 getRandomAttraction() 메서드가 getAttractionData() 메서드에서 데이터를 받아온 이후에 호출되지 않기 때문에 발생합니다. getAttractionData() 메서드는 비동기적으로 데이터를 가져오므로, 데이터를 가져오기 전에 getRandomAttraction()이 실행되면 attractionsWithImages 배열은 아직 비어 있습니다.

 

 

해결 방법

getRandomAttraction() 메서드를 getAttractionData() 메서드의 성공적인 데이터 가져오기(.success 케이스) 이후에 호출해야 합니다. 이렇게 하면 데이터를 받아온 후에 랜덤으로 항목을 선택할 수 있습니다.

 

다음과 같이 수정할 수 있습니다:

private func getAttractionData() {
    NetworkManager.shared.getAttractionData { [weak self] results in
        switch results {
        case .success(let items):
            // 이미지가 있는 항목과 없는 항목을 분리
            self?.attractionsWithImages = items.filter { $0.firstimage?.count != 0 || $0.firstimage2?.count != 0 }
            self?.attractionsWithoutImages = items.filter { $0.firstimage?.count == 0 && $0.firstimage2?.count == 0 }

            // 메인 스레드에서 테이블 뷰 갱신 및 랜덤 선택된 항목 업데이트
            DispatchQueue.main.async {
                self?.homeFeedTable.reloadData()
                self?.getRandomAttraction()  // 데이터를 가져온 후에 호출
            }

        case .failure(let error):
            print(error.localizedDescription)
        }
    }
}

private func getRandomAttraction() {
    let selectedItem = attractionsWithImages.randomElement()
    let selectedTitle = selectedItem?.title
    let selectedAddress = selectedItem?.addr1
    let selectedPosterURL = selectedItem?.firstimage ?? selectedItem?.firstimage2 ?? ""

    self.recommendedDestinationImageView.configureWithImage(title: selectedTitle ?? "", address: selectedAddress ?? "", posterPath: selectedPosterURL)
}

 

 

이렇게 하면 getAttractionData() 메서드가 데이터를 성공적으로 가져오고 나서 getRandomAttraction()이 호출되어, attractionsWithImages 배열에서 랜덤하게 항목을 선택할 수 있습니다.