Skip to content

Conversation

@thingineeer
Copy link
Collaborator

@thingineeer thingineeer commented Sep 7, 2023

🌱 작업한 내용

  • 현재 기능에 쓸모 없는 코드들을 삭제 했습니다 ( 기능 구현 안된 팔로잉, 팔로워 버튼 ) -> 하지만 assets에는 존재
  • firebase 라이브러리 사용으로 dynamicLinks를 생성
    • Signing & Capabilities -> Associated Domains 에 앱링크 추가
    • URL Types 에 DynamicLink URL Schemes 추가
    • GoogleService-Info.plist 추가
  • 공유 버튼 추가
  • 공유 기능 추가
    • 앱 없으면 -> 앱스토어
    • 앱 있는데 로그인 되어 있으면 -> 그대로 원하는 뷰로
    • 앱 있는데 로그인 안되어있으면 -> 방문자 모드로 뷰 접근(미완)
  • SceneDelegate.swift 에 뷰 이동을 위해 작업한 부분이 있습니다

🌱 PR Point

피드백

  • shareButtonTapped() 함수의 구조 (일단 정리 안하고 다 때려 박음)
  • SceneDelegate의 scene(_ scene: , continue userActivity: )courseId 를 통해 원하는 뷰로 들어오는 로직을 짤때,
    데이터 불러오는 부분을 어떻게 처리해야 괜찮을지..? 현재는 익스텐션으로 복붙하여 가져옴
  • SceneDelegate 의 scene(_ scene: , openURLContexts : ) 의 로직은 위 부분과 동일
  • SceneDelegate 의 scene(_ scene: , willConnectTo session: , options connectionOptions: ) 이 부분도 컨펌 받아야하는 부분!

공유할내용

  • 동적링크가 25년8월5일에 소멸이 되는데, 이 부분은 코드리뷰 반영후 pr날릴때 구체적으로 공유 하겠음

📸 스크린샷

구현 내용 스크린샷
공유기능 image image

📮 관련 이슈

@gitguardian
Copy link

gitguardian bot commented Sep 7, 2023

⚠️ GitGuardian has uncovered 4 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id Secret Commit Filename
- Google API Key 5a2ba9e Runnect-iOS/Runnect-iOS/GoogleService-Info.plist View secret
- Google API Key ed13ffc Runnect-iOS/Runnect-iOS/GoogleService-Info.plist View secret
- Google API Key 917876b Runnect-iOS/Runnect-iOS/GoogleService-Info.plist View secret
- Google API Key dfc5042 Runnect-iOS/Runnect-iOS/GoogleService-Info.plist View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Our GitHub checks need improvements? Share your feedbacks!

Copy link
Collaborator

@513sojin 513sojin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

딥링크로 앱이 실행된 경우 밑의 코드가 실행돼서

if let userActivity = connectionOptions.userActivities.first {
            self.scene(scene, continue: userActivity)
        }

scene함수가 호출되는 것 같은데

  • func scene(_ scene: UIScene, continue userActivity: NSUserActivity) -> 웹에서 앱이 호출된 경우
  • func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
    -> URL 여는 요청 후 실행
    이렇게 분기 처리가 되는게 맞나요 ? 사실 두 개의 차이가 크게 와닿지는 않는데 정확히 어떤 차이인지도 궁금합니다 ! (Just Question)

그리고 이 두 함수 내의 코드가 거의 동일해보이는데
밑에 처럼 (ex. executeUserActivity(userActivity))함수로 따로 빼두고 매개변수만 다르게 주는 방향으로 가는게 더욱 깔끔할 것 같다는 의견입니당

extension SceneDelegate {
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        executeUserActivity(userActivity)
    }

    // MARK: Other Private Methods

    private func executeUserActivity(_ userActivity: NSUserActivity) {
        switch userActivity.activityType {
        case CSSearchableItemActionType:
            executeSpotlightActivity(userActivity)
        default:
            return
        }
    }

    private func executeSpotlightActivity(_ userActivity: NSUserActivity) {
        guard let key = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String,
              let monsterEntity = UserDefaultsClient.shared.monster(key: key),
              let nav = window?.rootViewController as? UINavigationController else {
            return
        }

        nav.dismiss(animated: false)
        nav.popToRootViewController(animated: false)

        let vc = MonsterDetailRouter.assembleModule(monster: MonsterItem(entity: monsterEntity))
        nav.pushViewController(vc, animated: true)
    }
}

참고한 페이지 입니다~

Comment on lines +162 to +172
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"

linkBuilder!.socialMetaTagParameters = DynamicLinkSocialMetaTagParameters()
linkBuilder!.socialMetaTagParameters?.imageURL = URL(string: courseImage)
linkBuilder!.socialMetaTagParameters?.title = title
linkBuilder!.socialMetaTagParameters?.descriptionText = description

guard let longDynamicLink = linkBuilder!.url else { return }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

강제 언래핑을 사용한 이유가 있을까용 ?

Copy link
Collaborator Author

@thingineeer thingineeer Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

강제 언래핑을 사용한 이유가 있을까용 ?

받아오는 값이 확실히 있다고 판단했습니다!

linkBuilder?.iOSParameters =

이런식으로 사용해도 되지만 다른 코드를 참조한 결과 대부분 저렇게 짜는 경우가 있었습니다.

https://firebase.google.com/docs/dynamic-links/ios/create?hl=ko

템플릿은 공식홈페이지 참고 했는데, 나중에 코드 리뷰 반영하고 머지 할때 pr에 참고한 링크 추가 하겠습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 제가 구현할 부분의 아이콘인 것 같은데 아이콘만 추가하고 '지도에서 선택하기' 부분은 라벨로 넣고 싶어서 ,,, 머지 전에 삭제해주시면 감사하겠습니당~

Copy link
Collaborator Author

@thingineeer thingineeer Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 merge 하기 전에 소진님 기능 구현 부분은 전부 다 삭제 하겠습니다!

Copy link
Collaborator Author

@thingineeer thingineeer Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가로 공통되는 부분은 묶는게 적극 공감합니다.

하지만 SceneDelegate.swift 부분인 scene(_:openURLContexts:) 이 부분은 URL 작업에 필요없다고 판단되어 원래 있던 카카오 api 코드만 냅겨두고 삭제할 예정입니다.


추가로 궁금하신 부분인 Scene에서 세 개의 함수를 다뤘는데, 간단하게 설명하겠습니다.


scene(_:willConnectTo:options:)

• 앱에 scene 을 추가할 때 즉, 앱을 런치할 때에 해당 메서드로 delegate 에게 알립니다.

즉 앱을 실행시켜서 foreground 로 진입 (앱 런치 중일때 URL 핸들링)


scene(_:continue:)

• delegate 에게 지정된 Handoff-related activity 를 처리하도록 알립니다.

여기서는 user Activity와 관련된 데이터를 scene에서 사용하여 작업을 이어갑니다.

userActivity : activity-related data 가 포함된 객체입니다. (like UserDefaults ? )


scene(_:openURLContexts:)

background 에서 foreground 로 진입 (즉 앱을 런치하지 않을때 URL 핸들링) 인줄 알았는데, URLContext가 없어도
scene(_:continue:) 에서 처리 가능 했습니다.

근데 다 willConnectTo 에서 작동을 하더라고요.. 그래서 여기에 있는 코드는 지워도 된다 판단을 하였습니다.

결론

background 에서 foreground 로 진입 시 scene(_:openURLContexts:) 메서드를 사용하여 URL을 확인하고 특정 화면으로 이동할 수 있으며,
QR 코드 를 찍거나, 외부링크 를 사용해 동적 링크로 앱을 실행하는 경우에는 scene(_:continue:) 메서드를 사용합니다.

구체적인 정보는
https://developer.apple.com/documentation/uikit/uiscenedelegate/3238056-scene
https://developer.apple.com/documentation/uikit/uiscenedelegate/3238060-scene
등등..
공홈 참고 부탁드립니다.

Comment on lines +150 to +161
@objc func shareButtonTapped() {
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 dynamicLinksDomainURIPrefix = "https://runnect.page.link"
guard let link = URL(string: "\(dynamicLinksDomainURIPrefix)/?courseId=\(courseId)") else { return }
Copy link
Collaborator

@513sojin 513sojin Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 다 때려박았다는 이 부분 좀 찾아봤슴다
함수화 하신 분도 있도 있었는데 지금 코드처럼 작성한 경우가 더 많은 것 같네요

공유 기능이 여러 군데에서 사용되면 따로 빼둬도 좋을 것 같은데 그게 아니라서 지금처럼 둬도 될 것 같다는 의견입니다 ~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 곳에서 사용된다면 템플릿은 재사용화해도 된다고 생각합니다!

@513sojin
Copy link
Collaborator

513sojin commented Sep 13, 2023

깔끔한 정리까지 .. 덕분에 저도 알아가요 진짜 최고 ! 기능 구현도 많이 어려웠을텐데 너무 고생하셨습니당 ~
코드 리뷰 반영된거 푸시하면 바로 어푸룹하겠습니다 (꾸벅 꾸벅)

Copy link
Collaborator

@lee-yeonwoo lee-yeonwoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿굿!!!체고

@thingineeer thingineeer merged commit 84c5f59 into Runnect:develop Sep 20, 2023
@thingineeer thingineeer deleted the Feat]-#178---CourseDetailVC-UI-수정 branch September 20, 2023 13:12
@thingineeer thingineeer self-assigned this Sep 25, 2023
@thingineeer thingineeer changed the title [Feat] #178 - 공유 기능 추가 [Feat] #178 - 외부 SNS 공유 기능 구현 하였습니다. Oct 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants