Skip to content

Commit

Permalink
[Fix] Runnect#178 - 코스 공유 기능 추가 firebase
Browse files Browse the repository at this point in the history
  • Loading branch information
thingineeer committed Sep 6, 2023
1 parent fff9e8c commit 356d560
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 192 deletions.
1 change: 1 addition & 0 deletions Runnect-iOS/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ target 'Runnect-iOS' do
pod 'KakaoSDKUser'
pod 'KakaoSDKShare'
pod 'KakaoSDKTemplate'
pod 'FirebaseDynamicLinks'


# Pods for Runnect-iOS
Expand Down
27 changes: 26 additions & 1 deletion Runnect-iOS/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
PODS:
- Alamofire (5.7.1)
- FirebaseCore (10.14.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.14.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseDynamicLinks (10.14.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (7.11.5):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.11.5):
- GoogleUtilities/Environment
- "GoogleUtilities/NSData+zlib (7.11.5)"
- KakaoSDKAuth (2.16.0):
- KakaoSDKCommon (= 2.16.0)
- KakaoSDKCommon (2.16.0):
Expand All @@ -24,10 +37,12 @@ PODS:
- NMapsGeometry (1.0.1)
- NMapsMap (3.17.0):
- NMapsGeometry
- PromisesObjC (2.3.1)
- SnapKit (5.6.0)
- Then (3.0.0)

DEPENDENCIES:
- FirebaseDynamicLinks
- KakaoSDKAuth
- KakaoSDKCommon
- KakaoSDKShare
Expand All @@ -42,6 +57,10 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- Alamofire
- FirebaseCore
- FirebaseCoreInternal
- FirebaseDynamicLinks
- GoogleUtilities
- KakaoSDKAuth
- KakaoSDKCommon
- KakaoSDKShare
Expand All @@ -51,11 +70,16 @@ SPEC REPOS:
- Moya
- NMapsGeometry
- NMapsMap
- PromisesObjC
- SnapKit
- Then

SPEC CHECKSUMS:
Alamofire: 0123a34370cb170936ae79a8df46cc62b2edeb88
FirebaseCore: 6fc17ac9f03509d51c131298aacb3ee5698b4f02
FirebaseCoreInternal: d558159ee6cc4b823c2296ecc193de9f6d9a5bb3
FirebaseDynamicLinks: 0eaabff2d0e5d0e576c0227227b00771aa2f3aaf
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
KakaoSDKAuth: 1b85ed7c41b0517bfd1fc9dc46c292c75b8cb610
KakaoSDKCommon: d6579aa2e9d963d74e13d741cbf1cce48b8b0c17
KakaoSDKShare: efc0415c4f33274232604eeaf96fb03641facdca
Expand All @@ -65,9 +89,10 @@ SPEC CHECKSUMS:
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
NMapsGeometry: 53c573ead66466681cf123f99f698dc8071a4b83
NMapsMap: a5b909a31b6f3d27a670f6eb2ddc913c38975474
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25
Then: 844265ae87834bbe1147d91d5d41a404da2ec27d

PODFILE CHECKSUM: 77a648fc451eb8403d22fda5ccf06419d697c921
PODFILE CHECKSUM: 43e89e9e217761b44c0c7e93fb4abfab29a82ece

COCOAPODS: 1.12.1
8 changes: 7 additions & 1 deletion Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
0AEBD608F3973389E8E1C6D6 /* Pods_Runnect_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 015778D02D5CDE0838284CD7 /* Pods_Runnect_iOS.framework */; };
7110A6022AA33624009A7E99 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7110A6012AA33624009A7E99 /* GoogleService-Info.plist */; };
712F661D2A7B7BAB00D9539B /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712F661C2A7B7BAB00D9539B /* Config.swift */; };
A3305A97296EF58C000B1A10 /* GoalRewardInfoDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3305A96296EF58C000B1A10 /* GoalRewardInfoDto.swift */; };
A3BC2F2B2962C3D500198261 /* GoalRewardInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3BC2F2A2962C3D500198261 /* GoalRewardInfoVC.swift */; };
Expand Down Expand Up @@ -163,6 +164,8 @@
/* Begin PBXFileReference section */
015778D02D5CDE0838284CD7 /* Pods_Runnect_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runnect_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3C3033C911343B5C57EB68E7 /* Pods-Runnect-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runnect-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Runnect-iOS/Pods-Runnect-iOS.debug.xcconfig"; sourceTree = "<group>"; };
7110A6012AA33624009A7E99 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
7110A6032AA337DD009A7E99 /* Runnect-iOSDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Runnect-iOSDebug.entitlements"; sourceTree = "<group>"; };
712F661C2A7B7BAB00D9539B /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
A3305A96296EF58C000B1A10 /* GoalRewardInfoDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalRewardInfoDto.swift; sourceTree = "<group>"; };
A3BC2F2A2962C3D500198261 /* GoalRewardInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoalRewardInfoVC.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -792,11 +795,13 @@
CE4545C7295D7AF4003201E1 /* Runnect-iOS */ = {
isa = PBXGroup;
children = (
7110A6032AA337DD009A7E99 /* Runnect-iOSDebug.entitlements */,
A3E55BA529C8AB0A0000D85D /* Runnect-iOS.entitlements */,
CE6655AA295D7FAE00C64E12 /* Global */,
CE6655A9295D7FAA00C64E12 /* Network */,
CE6655A8295D7F7D00C64E12 /* Presentation */,
CE4545D6295D7AF5003201E1 /* Info.plist */,
7110A6012AA33624009A7E99 /* GoogleService-Info.plist */,
);
path = "Runnect-iOS";
sourceTree = "<group>";
Expand Down Expand Up @@ -1246,6 +1251,7 @@
files = (
CE665615295D989A00C64E12 /* .swiftlint.yml in Resources */,
CE17F0342961BEF800E1DED0 /* Pretendard-Bold.otf in Resources */,
7110A6022AA33624009A7E99 /* GoogleService-Info.plist in Resources */,
CE17F0352961BEF800E1DED0 /* Pretendard-SemiBold.otf in Resources */,
CE17F0332961BEF800E1DED0 /* Pretendard-Medium.otf in Resources */,
CE6655BF295D82E200C64E12 /* .gitkeep in Resources */,
Expand Down Expand Up @@ -1601,7 +1607,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOS.entitlements";
CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOSDebug.entitlements";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
Expand Down
30 changes: 8 additions & 22 deletions Runnect-iOS/Runnect-iOS/Global/Supports/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@ import UIKit
import NMapsMap
import KakaoSDKAuth
import KakaoSDKCommon
import FirebaseCore

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

print("🔥AppDelegate 의 openURLContexts 입니다 \n🔥")
if let url = URLContexts.first?.url {


if (AuthApi.isKakaoTalkLoginUrl(url)) {
_ = AuthController.handleOpenUrl(url: url)
}


}
}

Expand All @@ -31,33 +38,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

FirebaseApp.configure()
NMFAuthManager.shared().clientId = Config.naverMapClientId
KakaoSDK.initSDK(appKey: Config.kakaoNativeAppKey)

return true
}

// Handle deep linking
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let host = components.host,
let queryItems = components.queryItems {

// Handle deep link URL here
if host == "detail" {
if let courseId = queryItems.first(where: { $0.name == "courseId" })?.value {
// Now you can navigate to your desired view controller based on the courseId
if let navigationController = window?.rootViewController as? UINavigationController,
let courseDetailVC = navigationController.viewControllers.first as? CourseDetailVC {
// Call a method in your CourseDetailVC to navigate to the desired view
courseDetailVC.navigateToCourseView(with: courseId)
}
}
}
}
return false
}


// MARK: UISceneSession Lifecycle

Expand Down
154 changes: 113 additions & 41 deletions Runnect-iOS/Runnect-iOS/Global/Supports/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,102 @@
import UIKit
import KakaoSDKAuth
import KakaoSDKCommon
import FirebaseDynamicLinks
import FirebaseCore
import FirebaseCoreInternal

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

print("🔥 scene에서 willConnectTo 동작 🔥")
guard let _ = (scene as? UIWindowScene) else { return }

if let userActivity = connectionOptions.userActivities.first {
print("🔥 scene에서 userActivity 동작 🔥")
self.scene(scene, continue: userActivity)
}

print("🔥 scene에서 SplashVC() 동작 🔥")
guard let windowScene = (scene as? UIWindowScene) else { return }

let window = UIWindow(windowScene: windowScene)
let nav = UINavigationController(rootViewController: SplashVC())
window.rootViewController = nav
self.window = window
window.makeKeyAndVisible()

}

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let incomingURL = userActivity.webpageURL {
let linkHandled = DynamicLinks.dynamicLinks()
.handleUniversalLink(incomingURL) { dynamicLink, error in


if let courseId = self.handleDynamicLink(dynamicLink) {
guard let _ = (scene as? UIWindowScene) else { return }

if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)

let rootVC = CourseDetailVC()
rootVC.setPublicCourseId(publicCourseId: Int(courseId))
rootVC.getUploadedCourseDetail(courseId: Int(courseId))

// CourseDetailVC를 NavigationController로 감싸고, rootViewController로 설정합니다.
let navigationController = UINavigationController(rootViewController: rootVC)
window.rootViewController = navigationController
window.makeKeyAndVisible()
self.window = window
}
}
}
}
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
print("🔥 SceneDelegate의 openURLContexts입니다~ 🔥")

print("🔥 scene에서 뷰 동작 🔥")
print(URLContexts)
print(URLContexts.first!)

if let url = URLContexts.first?.url {

print("🔥 url : \(url)🔥 \n")

if url.scheme == "kakao27d01e20b51e5925bf386a6c5465849f" { // 앱의 URL Scheme를 확인합니다.

if let host = url.host, host == "kakaolink" {
// 딥링크 경로가 "detail"일 경우 CourseDetailView로 이동하도록 처리합니다.
if let courseIdString = url.queryParameters?["publicCourseId"], let courseId = Int(courseIdString) {
// Firebase Dynamic Links를 사용하여 딥 링크를 처리합니다.
print("🔥 SceneDelegate의 url은 : \(url) 🔥")
let linkHandled = DynamicLinks.dynamicLinks().handleUniversalLink(url) { dynamicLink, error in
if let courseId = self.handleDynamicLink(dynamicLink) {
guard let _ = (scene as? UIWindowScene) else { return }

if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.overrideUserInterfaceStyle = .light

print("🔥 url.queryParameters : \(url.queryParameters!)🔥 \n")
print("🔥 courseIdString : \(courseIdString)🔥 \n")
let courseDetailVC = CourseDetailVC() // 해당 뷰 컨트롤러 클래스를 생성합니다.
// courseDetailVC.courseId = courseId // CourseDetailView에 값을 전달합니다.

// 이제 courseDetailVC를 현재 화면에 추가하거나 모달로 표시할 수 있습니다.
// 예를 들어, 현재의 루트 뷰 컨트롤러에 추가하는 경우:
// if let rootViewController = window?.rootViewController {
// rootViewController.addChild(courseDetailVC)
// rootViewController.view.addSubview(courseDetailVC.view)
// courseDetailVC.didMove(toParent: rootViewController)
// }
// CourseDetailVC 인스턴스를 생성합니다.
let rootVC = CourseDetailVC()
rootVC.setPublicCourseId(publicCourseId: Int(courseId))

// CourseDetailVC를 NavigationController로 감싸고, rootViewController로 설정합니다.
let navigationController = UINavigationController(rootViewController: rootVC)
window.rootViewController = navigationController
window.makeKeyAndVisible()
self.window = window
}
}

}

if (AuthApi.isKakaoTalkLoginUrl(url)) {
print("🔥 바인딩 유무 ", linkHandled, "🔥")

// Kakao SDK가 처리해야 하는지 확인합니다.
if AuthApi.isKakaoTalkLoginUrl(url) {
_ = AuthController.handleOpenUrl(url: url)
}
}


}


func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
Expand Down Expand Up @@ -90,22 +131,53 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}

func handleDynamicLink(_ dynamicLink: DynamicLink?) -> String? {
if let dynamicLink = dynamicLink, let url = dynamicLink.url,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems {
for item in queryItems {
if item.name == "courseId", let courseId = item.value {
// courseId를 사용하여 특정 뷰로 이동
// 예: courseId를 기반으로 상세 화면을 열거나 특정 기능 수행
print("🔥코스아이디가 제대로 여기까지 오는가!", courseId, "🔥")
return courseId
}
}
}
return nil
}

}

extension URL {
var queryParameters: [String: String]? {
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems else {
return nil
}
extension CourseDetailVC {

var parameters = [String: String]()
for item in queryItems {
parameters[item.name] = item.value
func getUploadedCourseDetail(courseId: Int?) {
guard let publicCourseId = courseId else { return }
LoadingIndicator.showLoading()
Providers.publicCourseProvider.request(.getUploadedCourseDetail(publicCourseId: publicCourseId)) { [weak self] response in
guard let self = self else { return }
LoadingIndicator.hideLoading()
switch response {
case .success(let result):
let status = result.statusCode
if 200..<300 ~= status {
do {
let responseDto = try result.map(BaseResponse<UploadedCourseDetailResponseDto>.self)
guard let data = responseDto.data else { return }
self.setData(model: data)
} catch {
print(error.localizedDescription)
}
}
if status >= 400 {
print("400 error")
self.showNetworkFailureToast()
}
case .failure(let error):
print(error.localizedDescription)
self.showNetworkFailureToast()
}
}

return parameters
}
}

Loading

0 comments on commit 356d560

Please sign in to comment.