[TIL] 11.16

Junyoung_Hong·2023년 11월 16일
0

TIL_11월

목록 보기
4/5
post-thumbnail

1. 이미지뷰 클릭을 통한 화면이동

소셜 관련 앱을 사용하면 다른 사람의 프로필을 누르면 해당 사용자의 프로필을 볼 수 있는 페이지로 넘어가는 것이 일반적인 경우이다. 이 기능을 이번에 구현해보고자 한다.

이 기능의 흐름은 다음과 같다.
1. 제스처 인식(GestureRecognizer) : imageView에서 탭을 감지
2. 콜백 함수(Callback Function) : 클릭이 감지될 때 호출되는 함수
3. 클로저(Closure) : imageView를 포함하는 ViewController에게 알려주어 화면 전환을 처리할 수 있게 함

1-1. 클로저 추가하기

var onImageTap: (() -> Void)?

1-2. imageView에 제스처 인식기 설정

private func addTapGestureToProfileImageView() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(profileImageTapped))
    profileImageView.isUserInteractionEnabled = true
    profileImageView.addGestureRecognizer(tapGesture)
}

@objc private func profileImageTapped() {
    onImageTap?()
}

이미지가 탭 될때마다 클로저가 호출되도록 한다.

UITapGestureRecognizer

UITapGestureRecognizer는 제스처 인식기의 한 종류로, 사용자가 화면의 특정 부분을 탭할 때, 이를 감지하는 역할을 한다.

  • 간단한 탭 감지: UITapGestureRecognizer는 한 번 또는 여러 번 연속해서 화면을 탭하는 제스처를 감지할 수 있다.

  • 커스터마이즈 가능: 탭의 횟수(예: 더블 탭), 손가락의 수 등을 설정하여 감지되는 제스처의 종류를 세밀하게 조정할 수 있다.

  • UIView에 추가: UITapGestureRecognizer는 UIView의 인스턴스에 추가될 수 있으며, 이 뷰 내에서 발생하는 탭 제스처를 감지한다.

  • 타겟-액션 메커니즘: 탭이 감지되었을 때 실행할 메소드를 지정할 수 있다. 이는 타겟(대상 객체)과 액션(실행할 메소드)을 지정하여 설정한다.

  • 다른 제스처 인식기와의 상호작용: 여러 제스처 인식기가 동일한 뷰에 추가되었을 때, 서로 영향을 주고받을 수 있다. 예를 들어, UITapGestureRecognizer와 UIPanGestureRecognizer를 동시에 사용할 때, 둘 사이의 우선순위를 설정할 수 있다.

    https://developer.apple.com/documentation/uikit/uitapgesturerecognizer

1-3. onImageTap 클로저 설정

해당 imageView를 포함하는 ViewController에서 onImageTap 클로저를 설정한다. 현재는 해당 유저의 정보를 불러와서 Profile 화면에 보여주는 코드를 넣어주면 된다. 이 코드는 다양한 화면에서 사용하기 때문에 class로 따로 만들었다.

class PresentToProfileVC {
    
    static let urlCache = FBURLCache.shared
    static let storage = Storage.storage().reference()
    
    static func presentToProfileVC(from presentingVC: UIViewController, with profile: UserSummary) {
        let profileViewController = MyProfileViewController()
        profileViewController.userProfile = profile
        
        // 이미지 로딩 로직
        if let profileImageURL = profile.profileImagePath {
            self.getUserImage(referencePath: profileImageURL, imageSize: .medium) { [weak profileViewController] downloadedImage in
                DispatchQueue.main.async {
                    if let image = downloadedImage {
                        profileViewController?.profileImage.setImage(image, for: .normal)
                    }
                }
            }
        } else {
            let defaultImage = UIImage(named: "profile") ?? UIImage(systemName: "person.fill")
            profileViewController.profileImage.setImage(defaultImage, for: .normal)
        }
        
        profileViewController.profileName.text = profile.nickName
        profileViewController.choiceEnjoyTextField.text = profile.hobbyList?.first
        profileViewController.selfInfoDetail.text = profile.description
        
        profileViewController.profileImage.isUserInteractionEnabled = true
        profileViewController.profileName.isEditable = false
        profileViewController.choicePickerView.isUserInteractionEnabled = false
        profileViewController.selfInfoDetail.isEditable = false
        profileViewController.logout.isHidden = true
        profileViewController.line.isHidden = true
        profileViewController.deleteID.isHidden = true
        
        presentingVC.present(profileViewController, animated: true, completion: nil)
    }
    
    static func getUserImage(referencePath: String?, imageSize: ImageSize, completion: @escaping(UIImage?) -> Void) {
        guard let referencePath = referencePath else { return }
        let imageRefPath = storage.child(referencePath).child(imageSize.rawValue).fullPath
        self.urlCache.downloadURL(storagePath: imageRefPath) { result in
            switch result {
            case .success(let image):
                completion(image)
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }
}

MyProfileViewController는 이미 만들어둔 상태에서 재사용하고 있고, UserSummary라는 구조체로 사용자의 데이터를 저장하고 있다.

이렇게 만든 함수들을 클로저 안에 넣어주면 된다.

func navigateToProfilePage(for indexPath: IndexPath) {
    if let userList = firebaseClubDatabaseManager.model?.userList {
        let profile = userList[indexPath.row]
        PresentToProfileVC.presentToProfileVC(from: self, with: profile)
    }
}
profile
iOS 개발자를 향해 성장 중

0개의 댓글