From a8f6088a321a5a27f35de351d7075063e24abe77 Mon Sep 17 00:00:00 2001 From: LeeMyeongJin Date: Thu, 16 Nov 2023 21:13:57 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[Refactor]=20#209=20-=20=EA=B3=B5=EC=9C=A0?= =?UTF-8?q?=20=EB=B6=80=EB=B6=84=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 재사용이 가능한 부분을 재사용 하였습니다. 짧은 동적링크 처리도 조금 다르게 수정하였습니다. --- .../CourseDetail/VC/CourseDetailVC.swift | 76 +++++++++++-------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift index 8da6bae5..ed4f7e97 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift @@ -151,41 +151,53 @@ extension CourseDetailVC { guard let model = self.uploadedCourseDetailModel else { return } - - let title = model.publicCourse.title - let courseId = model.publicCourse.id // primaryKey - let description = model.publicCourse.description - let courseImage = model.publicCourse.image - + + let publicCourse = model.publicCourse + let title = publicCourse.title + let courseId = publicCourse.id // primaryKey + let description = publicCourse.description + let courseImage = publicCourse.image + let dynamicLinksDomainURIPrefix = "https://runnect.page.link" - guard let link = URL(string: "\(dynamicLinksDomainURIPrefix)/?courseId=\(courseId)") else { return } - let linkBuilder = DynamicLinkComponents(link: link, domainURIPrefix: dynamicLinksDomainURIPrefix) - linkBuilder!.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.runnect.Runnect-iOS") - linkBuilder!.iOSParameters?.appStoreID = "1663884202" - linkBuilder!.iOSParameters?.minimumAppVersion = "1.0.4" + guard let link = URL(string: "\(dynamicLinksDomainURIPrefix)/?courseId=\(courseId)") else { + return + } - linkBuilder!.socialMetaTagParameters = DynamicLinkSocialMetaTagParameters() - linkBuilder!.socialMetaTagParameters?.imageURL = URL(string: courseImage) - linkBuilder!.socialMetaTagParameters?.title = title - linkBuilder!.socialMetaTagParameters?.descriptionText = description - - guard let longDynamicLink = linkBuilder!.url else { return } + guard let linkBuilder = DynamicLinkComponents(link: link, domainURIPrefix: dynamicLinksDomainURIPrefix) else { + return + } + + linkBuilder.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.runnect.Runnect-iOS") + linkBuilder.iOSParameters?.appStoreID = "1663884202" + linkBuilder.iOSParameters?.minimumAppVersion = "1.0.4" + + linkBuilder.socialMetaTagParameters = DynamicLinkSocialMetaTagParameters() + linkBuilder.socialMetaTagParameters?.imageURL = URL(string: courseImage) + linkBuilder.socialMetaTagParameters?.title = title + linkBuilder.socialMetaTagParameters?.descriptionText = description + + guard let longDynamicLink = linkBuilder.url else { + return + } print("The long URL is: \(longDynamicLink)") - - /// 짧은 Dynamic Link로 변환 - linkBuilder?.shorten(completion: { url, _, _ in - guard let shortDynamicLink = url else { return } - print("The short URL is: \(shortDynamicLink)") - let activityVC = UIActivityViewController(activityItems: [shortDynamicLink.absoluteString], applicationActivities: nil) - activityVC.popoverPresentationController?.sourceView = self.view - self.present(activityVC, animated: true, completion: nil) - - }) - -// let activityVC = UIActivityViewController(activityItems: [longDynamicLink.absoluteString], applicationActivities: nil) -// activityVC.popoverPresentationController?.sourceView = self.view -// self.present(activityVC, animated: true, completion: nil) - + + /// 짧은 Dynamic Link로 변환하는 부분 입니다. + linkBuilder.shorten { [weak self] url, warnings, error in + guard let shortDynamicLink = url else { + if let error = error { + print("❌Error shortening dynamic link: \(error)") + } + return + } + + print("🔥The short URL is: \(shortDynamicLink)") + + DispatchQueue.main.async { + let activityVC = UIActivityViewController(activityItems: [shortDynamicLink.absoluteString], applicationActivities: nil) + activityVC.popoverPresentationController?.sourceView = self?.view + self?.present(activityVC, animated: true, completion: nil) + } + } } @objc func startButtonDidTap() { From a948def1cb1f996c389c1b6705e34968f81dbfe4 Mon Sep 17 00:00:00 2001 From: LeeMyeongJin Date: Thu, 16 Nov 2023 21:25:40 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[Refactor]=20#209=20-=20=EB=B0=94=ED=85=80?= =?UTF-8?q?=20=EC=8B=9C=ED=8A=B8=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 필요없는 주석 삭제, 네이밍, 상수값 변경을 알맞게 하였습니다. --- .../Runnect-iOS.xcodeproj/project.pbxproj | 6 +- .../UIComponents/CustomBottomSheetVC.swift | 94 +++++++------------ .../CourseDrawing/VC/CourseDrawingVC.swift | 2 +- 3 files changed, 36 insertions(+), 66 deletions(-) diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index 6e8707da..cfc91627 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 0AEBD608F3973389E8E1C6D6 /* Pods_Runnect_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 015778D02D5CDE0838284CD7 /* Pods_Runnect_iOS.framework */; }; - 2349CD532B026EA500EE7C4A /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2349CD512B024E5B00EE7C4A /* GoogleService-Info.plist */; }; 23EE06C12AC1AD5200CB3FF8 /* LocationSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C02AC1AD5200CB3FF8 /* LocationSelectView.swift */; }; 23EE06C52AC1AE1900CB3FF8 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C42AC1AE1900CB3FF8 /* BaseView.swift */; }; 23EE06C92AC1DED100CB3FF8 /* GesturePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C82AC1DED100CB3FF8 /* GesturePublisher.swift */; }; @@ -16,6 +15,7 @@ 23EE06D12AC2F44E00CB3FF8 /* TmapAddressSearchingResponseDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06D02AC2F44E00CB3FF8 /* TmapAddressSearchingResponseDto.swift */; }; 712F661D2A7B7BAB00D9539B /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712F661C2A7B7BAB00D9539B /* Config.swift */; }; 7136BF8A2AF921A900679364 /* CustomBottomSheetVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7136BF892AF921A900679364 /* CustomBottomSheetVC.swift */; }; + 71717B072B063E14004EA8DA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 71DBF23D2ABB255A0013415B /* GoogleService-Info.plist */; }; A3305A97296EF58C000B1A10 /* GoalRewardInfoDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3305A96296EF58C000B1A10 /* GoalRewardInfoDto.swift */; }; A3BC2F2B2962C3D500198261 /* GoalRewardInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3BC2F2A2962C3D500198261 /* GoalRewardInfoVC.swift */; }; A3BC2F2D2962C3F200198261 /* ActivityRecordInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3BC2F2C2962C3F200198261 /* ActivityRecordInfoVC.swift */; }; @@ -168,7 +168,6 @@ /* Begin PBXFileReference section */ 015778D02D5CDE0838284CD7 /* Pods_Runnect_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runnect_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2349CD512B024E5B00EE7C4A /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runnect-iOS/GoogleService-Info.plist"; sourceTree = ""; }; 23EE06C02AC1AD5200CB3FF8 /* LocationSelectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSelectView.swift; sourceTree = ""; }; 23EE06C42AC1AE1900CB3FF8 /* BaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = ""; }; 23EE06C82AC1DED100CB3FF8 /* GesturePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GesturePublisher.swift; sourceTree = ""; }; @@ -798,7 +797,6 @@ CE4545BC295D7AF4003201E1 = { isa = PBXGroup; children = ( - 2349CD512B024E5B00EE7C4A /* GoogleService-Info.plist */, CE665614295D989A00C64E12 /* .swiftlint.yml */, CE4545C7295D7AF4003201E1 /* Runnect-iOS */, CE4545C6295D7AF4003201E1 /* Products */, @@ -1274,9 +1272,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2349CD532B026EA500EE7C4A /* GoogleService-Info.plist in Resources */, CE665615295D989A00C64E12 /* .swiftlint.yml in Resources */, CE17F0342961BEF800E1DED0 /* Pretendard-Bold.otf in Resources */, + 71717B072B063E14004EA8DA /* GoogleService-Info.plist in Resources */, CE17F0352961BEF800E1DED0 /* Pretendard-SemiBold.otf in Resources */, CE17F0332961BEF800E1DED0 /* Pretendard-Medium.otf in Resources */, CE6655BF295D82E200C64E12 /* .gitkeep in Resources */, diff --git a/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomBottomSheetVC.swift b/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomBottomSheetVC.swift index 82659e39..b0e461ac 100644 --- a/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomBottomSheetVC.swift +++ b/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomBottomSheetVC.swift @@ -11,20 +11,17 @@ import CombineCocoa @frozen enum SheetType { - case Image // 가운에 이미지가 있는 시트 - case TextField // 가운데 텍스트필드가 있는 시트 + case image // 가운에 이미지가 있는 시트 + case textField // 가운데 텍스트필드가 있는 시트 } final class CustomBottomSheetVC: UIViewController { - // MARK: - Properties - private let backgroundView = UIView().then { $0.backgroundColor = .black.withAlphaComponent(0.65) } private let titleNameMaxLength = 20 - private var BottomsheetType: SheetType! - + private var bottomSheetType: SheetType! var backgroundTapAction: (() -> Void)? var completeButtonTapAction: ((String) -> Void)? @@ -33,34 +30,31 @@ final class CustomBottomSheetVC: UIViewController { private var cancelBag = CancelBag() // MARK: - UI Components - private let bottomSheetView = UIView().then { $0.backgroundColor = .w1 $0.layer.cornerRadius = 20 $0.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] } - private let contentsLabel = UILabel().then { $0.text = "코스 이름" $0.font = .h5 $0.textColor = .g1 } - private let dismissIndicatorView = UIView().then { - $0.backgroundColor = .g3 + $0.backgroundColor = .g4 $0.layer.cornerRadius = 3 } - private let completeButton = CustomButton(title: "완료").setColor(bgColor: .m1, disableColor: .g3).setEnabled(false) - private let mainImageView = UIImageView().then { $0.image = ImageLiterals.imgSpaceship } - private lazy var bottomSheetTextField = UITextField().then { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .center - $0.attributedPlaceholder = NSAttributedString(string: "코스의 이름을 입력해 주세요", attributes: [.font: UIFont.h5, .foregroundColor: UIColor.g3, .paragraphStyle: paragraphStyle]) + $0.attributedPlaceholder = NSAttributedString( + string: "코스의 이름을 입력해 주세요", + attributes: [.font: UIFont.h5, .foregroundColor: UIColor.g3, .paragraphStyle: paragraphStyle] + ) $0.font = .h5 $0.textColor = .g1 $0.textAlignment = .center @@ -70,56 +64,47 @@ final class CustomBottomSheetVC: UIViewController { $0.addTarget(self, action: #selector(textFieldTextDidChange), for: .editingChanged) } - // MARK: - initializtion + // MARK: - Initialization init(type: SheetType) { super.init(nibName: nil, bundle: nil) - self.BottomsheetType = type + self.bottomSheetType = type } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - View Life Cycle - override func viewDidLoad() { super.viewDidLoad() self.setUI() - self.setLayout(BottomsheetType) + self.setLayout(bottomSheetType) self.setDelegate() self.setTapGesture() self.setAddTarget() self.setBinding() - if BottomsheetType == .TextField { + if bottomSheetType == .textField { showBottomSheet() setupGestureRecognizer() } } - -} - -// MARK: - Methods - -extension CustomBottomSheetVC { - /// 바텀 시트의 라벨에 들어갈 텍스트 설정 + // MARK: - Methods @discardableResult func setContentsText(text: String) -> Self { - self.contentsLabel.text = text + contentsLabel.text = text return self } - /// 하단 버튼의 텍스트 변경 @discardableResult - public func setBottomButtonTitle(_ title: NSAttributedString) -> Self { - self.completeButton.changeTitle(attributedString: title) + func setBottomButtonTitle(_ title: NSAttributedString) -> Self { + completeButton.changeTitle(attributedString: title) return self } - /// 이미지 교체 @discardableResult - public func setImage(_ image: UIImage) -> Self { - self.mainImageView.image = image + func setImage(_ image: UIImage) -> Self { + mainImageView.image = image return self } @@ -133,7 +118,6 @@ extension CustomBottomSheetVC { }, completion: nil) } - // 중복 작업 통일 필요 (1. 배경화면 누를시, 2.스와이프 할시) private func setTapGesture() { let tap = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing)) tap.cancelsTouchesInView = false @@ -148,17 +132,18 @@ extension CustomBottomSheetVC { self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, - object: nil) + object: nil + ) NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, - object: nil) + object: nil + ) } } // MARK: - UI & Layout - extension CustomBottomSheetVC { private func setUI() { view.addSubview(backgroundView) @@ -169,9 +154,9 @@ extension CustomBottomSheetVC { private func setLayout(_ type: SheetType) { switch type { - case .TextField: + case .textField: setTextFieldLayout() - case .Image: + case .image: setImageLayout() } } @@ -203,7 +188,7 @@ extension CustomBottomSheetVC { make.leading.trailing.equalToSuperview().inset(16) } } - + private func setTextFieldLayout() { view.addSubviews(bottomSheetView) @@ -218,9 +203,9 @@ extension CustomBottomSheetVC { } dismissIndicatorView.snp.makeConstraints { make in - make.width.equalTo(102) - make.height.equalTo(7) - make.top.equalTo(bottomSheetView.snp.top).inset(12) + make.width.equalTo(42) + make.height.equalTo(4) + make.top.equalTo(bottomSheetView.snp.top).inset(16) make.centerX.equalToSuperview() } @@ -252,7 +237,6 @@ extension CustomBottomSheetVC { } private func showBottomSheet() { - let safeAreaHeight: CGFloat = view.safeAreaLayoutGuide.layoutFrame.height let bottomPadding: CGFloat = view.safeAreaInsets.bottom @@ -268,10 +252,8 @@ extension CustomBottomSheetVC { self.backgroundView.alpha = 0.65 self.view.layoutIfNeeded() }, completion: nil) - } - // 바텀 시트 사라지는 애니메이션 private func hideBottomSheetAndGoBack() { let safeAreaHeight = view.safeAreaLayoutGuide.layoutFrame.height let bottomPadding = view.safeAreaInsets.bottom @@ -283,7 +265,7 @@ extension CustomBottomSheetVC { make.top.equalTo(view.snp.top).offset(topConst) make.height.equalTo(bottomHeight) } - + UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseIn, animations: { self.backgroundView.alpha = 0.0 self.view.layoutIfNeeded() @@ -294,14 +276,11 @@ extension CustomBottomSheetVC { } } - // GestureRecognizer 세팅 작업 private func setupGestureRecognizer() { - // 흐린 부분 탭할 때, 바텀시트를 내리는 TapGesture let dimmedTap = UITapGestureRecognizer(target: self, action: #selector(dimmedViewTapped(_:))) backgroundView.addGestureRecognizer(dimmedTap) backgroundView.isUserInteractionEnabled = true - // 스와이프 했을 때, 바텀시트를 내리는 swipeGesture let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(panGesture)) swipeGesture.direction = .down view.addGestureRecognizer(swipeGesture) @@ -309,18 +288,16 @@ extension CustomBottomSheetVC { } // MARK: - @objc Function - extension CustomBottomSheetVC { - @objc private func keyboardWillShow(_ sender: Notification) { - self.view.frame.origin.y = -341 + self.view.frame.origin.y = -291 } - + @objc private func keyboardWillHide(_ sender: Notification) { self.view.frame.origin.y = 0 } - @objc private func endEditing() { /// return 누를시 키보드 종료 + @objc private func endEditing() { bottomSheetTextField.resignFirstResponder() } @@ -342,12 +319,10 @@ extension CustomBottomSheetVC { } } - // UITapGestureRecognizer 연결 함수 부분 @objc private func dimmedViewTapped(_ tapRecognizer: UITapGestureRecognizer) { hideBottomSheetAndGoBack() } - // UISwipeGestureRecognizer 연결 함수 부분 @objc func panGesture(_ recognizer: UISwipeGestureRecognizer) { if recognizer.state == .ended { switch recognizer.direction { @@ -358,13 +333,10 @@ extension CustomBottomSheetVC { } } } - } // MARK: - UITextFieldDelegate - extension CustomBottomSheetVC: UITextFieldDelegate { - func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift index 48aff37b..98166a01 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift @@ -252,7 +252,7 @@ extension CourseDrawingVC { } @objc private func completeButtonDidTap() { - let bottomSheetVC = CustomBottomSheetVC(type: .TextField) + let bottomSheetVC = CustomBottomSheetVC(type: .textField) bottomSheetVC.modalPresentationStyle = .overFullScreen bottomSheetVC.completeButtonTapAction = { [weak self] text in guard let self = self else { return }