๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/๐Ÿ”ฅ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

[iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 3. openURL, ์•ฑ์ด suspended์ผ ๋•Œ, query Parameter์— ํ•œ๊ธ€์ด ์žˆ์„ ๋•Œ

by MINT09 2024. 7. 5.

2024.07.05 - [iOS/ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…] - [iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 1.์ด๋ฏธ์ง€ URL ์„ค์ • + FileManager์— UIImage ์ €์žฅ

 

[iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 1.์ด๋ฏธ์ง€ URL ์„ค์ • + FileManager์— UIImage ์ €์žฅ

์šฐ๋ฆฌ ์„œ๋น„์Šค roome๋Š” ๋ฐฉํƒˆ์ถœ ํ”„๋กœํ•„์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ฃผ๋œ ๊ธฐ๋Šฅ์ด๋‹ค. ๋•Œ๋ฌธ์— ์ด ํ”„๋กœํ•„์„ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์˜€๋‹ค. ๋„ค์ด๋ฒ„, ์ธ์Šคํƒ€ ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋งค์ฒด๋ฅผ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ ํ”„๋กœํ•„

mintraum.tistory.com

2024.07.05 - [iOS/ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…] - [iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 2. ์‚ฌ์šฉ์ž ์ •์˜ ํ…œํ”Œ๋ฆฟ ์‚ฌ์šฉ

 

[iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 2. ์‚ฌ์šฉ์ž ์ •์˜ ํ…œํ”Œ๋ฆฟ ์‚ฌ์šฉ

2024.07.05 - [iOS/ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…] - [iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 1.์ด๋ฏธ์ง€ URL ์„ค์ • + FileManager์— UIImage ์ €์žฅ [iOS/Swift]์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ ๊ตฌํ˜„ 1.์ด๋ฏธ์ง€ URL ์„ค์ • + FileManager์— UIImage ์ €์žฅ์šฐ๋ฆฌ ์„œ๋น„์Šค roo

mintraum.tistory.com

์•ž์„  ๋‘๊ฐœ์˜ ํฌ์ŠคํŠธ์—์„œ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ์˜ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์—ˆ๋‹ค. ์ด์ œ๋Š” ์ •๋ง ์ด ๋กœ์ง๋Œ€๋กœ ๋ฐ›์•„์„œ ์–ด๋””๋กœ ๊ฐˆ ๊ฒƒ์ธ์ง€๋ฅผ ๊ฒฐ์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์•ฑ์ด ๋ฏธ์„ค์น˜๋œ ๊ฒฝ์šฐ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•ด์ค„ ๊ฒƒ์€ ์—†๋‹ค. Kakao Developers > ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ > ํ”Œ๋žซํผ ์œผ๋กœ ๋“ค์–ด๊ฐ€ ๋งˆ์ผ“ ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค. id๋งŒ ์ž…๋ ฅํ•˜๋ฉด url์€ ์ž๋™์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค. 

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ ์•ฑ์ด ์„ค์น˜๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์•ฑ์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. ์นด์นด์˜คํ†ก์„ ๋ณด๊ณ  ์žˆ์—ˆ์œผ๋‹ˆ ์•ฑ์€ Background ํ˜น์€ Suspended ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ์ผ ๊ฒƒ์ด๋‹ค. 

Background

- ์•ฑ์ด ์—ด๋ ธ๋˜ ์ ์ด ์žˆ๊ณ  Foreground์—๋Š” ์—†์œผ๋‚˜ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š” ์ƒํƒœ.

- ๊ณต์œ ๋ฐ›์€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด SceneDelegate์˜ openURLContexts๊ฐ€ ์‹คํ–‰๋œ๋‹ค. 

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else {
        return
    }
        
    if (AuthApi.isKakaoTalkLoginUrl(url)) {
        _ = AuthController.handleOpenUrl(url: url)
    }
    
    //url์˜ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ๋”•์…”๋„ˆ๋ฆฌ๋กœ ๋ณ€๊ฒฝ
    let params = self.queryParams(url: url)
    let nickname = params["value"]
    if params["type"] == "profile" {
    	//๊ณต์œ ๋ฐ›์€ ์œ ์ €์˜ ๋‹‰๋„ค์ž„์œผ๋กœ SharingContainer ๊ฐ์ฒด ์ƒ์„ฑ
        let sharingContainer = SharingContainer(nickname: nickname ?? "๋‹‰๋„ค์ž„")
        Task {
            do {
            	//SharingContainer์— ํ”„๋กœํ•„ ์—…๋ฐ์ดํŠธ
                try await sharingContainer.updateSharingUserProfile(nickname: nickname ?? "๋‹‰๋„ค์ž„")
                //์•ฑ์— ๋กœ๊ทธ์ธํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด, ์œ ์ €์˜ ํ”„๋กœํ•„๋„ ์—…๋ฐ์ดํŠธ -> ์ถ”ํ›„์— ์œ ์ € ํ”„๋กœํ•„ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๊ณต์œ ๋ฐ›์€ ํ”„๋กœํ•„ ๋ฐ‘ ๋ฒ„ํŠผ ํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋จ.
                if KeyChain.read(key: .hasToken) == "true" {
                    try await UserContainer.shared.updateUserProfile()
                }
                //๊ณต์œ ๋ฐ›์€ ํ”„๋กœํ•„๋กœ ํŽ˜์ด์ง€ ๋งŒ๋“ค์–ด์„œ ๋„์šฐ๊ธฐ
                let sharedViewController = SharingViewController(sharingContainer: sharingContainer)
                changeRootViewController(sharedViewController, animated: true)
            } catch {
                print(error)
            }
        }
    } else {
        changeRootViewController(SplashView(), animated: false)
    }
}

Suspended

- ๋ฉ”๋ชจ๋ฆฌ์—๋งŒ ์žˆ๊ณ  ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ์žˆ๋Š” ์ƒํƒœ

- ๊ณต์œ ๋ฐ›์€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฒ˜์Œ๋ถ€ํ„ฐ ์‹คํ–‰๋˜๋ฏ€๋กœ SceneDelegate์˜ willConnectTo์—์„œ openURLContexts๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ํ˜ธ์ถœํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์•„๋‹ˆ๋ผ๋ฉด ์•ฑ์„ ์ข…๋ฃŒํ•œ ์ƒํƒœ์—์„œ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ๊นŒ๋งŒ ํ™”๋ฉด๋งŒ ๋œจ๊ณ  ์ œ๋Œ€๋กœ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
        
    window = UIWindow(windowScene: windowScene)
        
    DIManager.shared.registerAll()
    //urlContexts๊ฐ€ ๋“ค์–ด์™”๋Š”์ง€ ์•„๋‹Œ์ง€ ํ™•์ธ. ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ.
    if connectionOptions.urlContexts.isEmpty {
        window?.rootViewController = SplashView()
    } else {
        self.scene(scene, openURLContexts: connectionOptions.urlContexts)
    }
    window?.makeKeyAndVisible()
}

openURL์— ํ•œ๊ธ€์ด ์žˆ๋‹ค๋ฉด

url๋กœ ์ „๋‹ฌํ•œ parameter์— ํ•œ๊ธ€์ด ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์˜ค๊ฒŒ ๋ ๊นŒ? 

์ด๋ ‡๊ฒŒ ์นด์นด์˜ค ์„œ๋ฒ„์—์„œ ์•Œ์•„์„œ ์ธ์ฝ”๋”ฉ ํ›„ ๋ณด๋‚ด์ค€๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ์ด๊ฑธ ๋””์ฝ”๋”ฉํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. (์•ˆ๋“œ๋กœ์ด๋“œ๋Š” ์ž๋™์œผ๋กœ ๋””์ฝ”๋”ฉํ•˜๋˜๋ฐ) ์ฒ˜์Œ์—๋Š” ๊ทธ๋ƒฅ ์‚ฌ์šฉํ–ˆ๋‹ค๊ฐ€ 2000 ์‚ฌ์šฉ์ž๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ๋ผ๋Š” ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ›์•˜๋‹ค. 

private func queryParams(url: URL) -> Dictionary<String, String> {
    var parameters = Dictionary<String, String>()
    
    //query๋Š” &๋กœ ๊ตฌ๋ถ„๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋‚˜๋ˆ ์ค€๋‹ค. 
    if let queryComponents = url.query?.components(separatedBy: "&") {
        for queryComponent in queryComponents {
        	//key1=value1์˜ ํ˜•์‹์ด๋ฏ€๋กœ =๋กœ๋„ ๋‚˜๋ˆ ์ค€๋‹ค.
            let paramComponents = queryComponent.components(separatedBy: "=")
            var object: String? = nil
            if paramComponents.count > 1 {
            	//String ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด ๋”•์…”๋„ˆ๋ฆฌ์— key์™€ value๋ฅผ ์ €์žฅํ•ด์ฃผ๋Š”๋ฐ removingPercentEncoding์„ ํ†ตํ•ด ๋””์ฝ”๋”ฉํ•ด์ค€๋‹ค. 
                object = paramComponents[1].removingPercentEncoding
            }
            let key = paramComponents[0]
            parameters[key] = object
        }
    }
    return parameters
}

๊ทธ๋ž˜์„œ removingPercentEncoding๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋””์ฝ”๋”ฉํ•œ ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ ๋”•์…”๋„ˆ๋ฆฌ์— ์ €์žฅํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜์˜€๋”๋‹ˆ, ์ œ๋Œ€๋กœ ๋œ ๊ฐ’์ด ๋“ค์–ด์™”๋‹ค!

https://developer.apple.com/documentation/foundation/nsstring/1409569-removingpercentencoding 

 

removingPercentEncoding | Apple Developer Documentation

Returns a new string made from the receiver by replacing all percent encoded sequences with the matching UTF-8 characters.

developer.apple.com

 

https://apps.apple.com/kr/app/roome/id6503616766

 

‎roome

‎๋ฐฉ ํƒˆ์ถœ ํ”„๋กœํ•„ ์ œ์ž‘ ์„œ๋น„์Šค ๋ฃจ๋ฏธ๋ฅผ ํ†ตํ•ด ๋‚˜์˜ ์„ฑํ–ฅ์„ ๋น ๋ฅด๊ฒŒ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด ๋ณด์„ธ์š”. ๋ฃจ๋ฏธ๋Š” ๋ฐฉ ํƒˆ์ถœ์„ ์ข‹์•„ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ๋‚˜์˜ ์ทจํ–ฅ์„ ๋‹ด์€ ํ”„๋กœํ•„์„ ์ด๋ฏธ์ง€ 1์žฅ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค

apps.apple.com