투케이2K

77. (ios/swift) url scheme host 스키마 호스트 데이터 전송 및 받은 데이터 확인 본문

IOS

77. (ios/swift) url scheme host 스키마 호스트 데이터 전송 및 받은 데이터 확인

투케이2K 2021. 12. 13. 09:23

[개발 환경 설정]

개발 툴 : XCODE

개발 언어 : SWIFT

 

[손님 : 접속하는 쪽]

 
// [호스트 명칭 사용 안함]
testui://?name=twok&age=28




// [호스트 명칭 사용]
testui://call?name=twok&age=28
 

[주인 : 접속을 받아서 데이터 처리하는 쪽 : 프로젝트 설정 부분]

 

[주인 : 소스코드 : SceneDelegate]

 
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    // 전역 변수 선언 [스키마 데이터를 전송할 컨트롤러]
    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        print("")
        print("===============================")
        print("[SceneDelegate >> willConnectTo]")
        print("[설명 : UI창 선택적 구성 및 제공된 UI창에 Scene 연결]")
        print("===============================")
        print("")

        guard let _ = (scene as? UIWindowScene) else { return }
        
        
        // [스키마 접속 여부 확인 실시]
        // 호스트 명 지정 없음 : 스키마 접속 형태 : [testui://?name=twok&age=28]
        // 호스트 명 지정 사용 : 스키마 접속 형태 : [testui://call?name=twok&age=28]
        if let _url = connectionOptions.urlContexts.first?.url {
            schemeHandleURL(url: _url)
        }
    }
    
    
    
    
    
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        print("")
        print("===============================")
        print("[SceneDelegate >> openURLContexts]")
        print("[설명 : url 접속 체크 실시]")
        print("===============================")
        print("")
        // [스키마 접속 여부 확인 실시]
        // 호스트 명 지정 없음 : 스키마 접속 형태 : [testui://?name=twok&age=28]
        // 호스트 명 지정 사용 : 스키마 접속 형태 : [testui://call?name=twok&age=28]
        if let _url = URLContexts.first?.url {
            schemeHandleURL(url: _url)
        }
    }
    
    
    
    
    
    func schemeHandleURL (url: URL){
        print("")
        print("==============================")
        print("SceneDelegate > schemeHandleURL() : 스키마 접속 핸들러 수행 실시")
        print("==============================")
        print("")
        
        // [Main 스토리보드 지정 실시]
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        
        // [Main 스토리보드에 포함된 개별 스토리보드 id 및 컨트롤러 지정]
        guard let rootVC = storyboard.instantiateViewController(identifier: "MainVC") as? MainController
        else {
            print("")
            print("==============================")
            print("SceneDelegate > schemeHandleURL() : 뷰 컨트롤러 확인 실패")
            print("==============================")
            print("")
            return
        }
        print("")
        print("==============================")
        print("SceneDelegate > schemeHandleURL() : 뷰 컨트롤러 연결 실시")
        print("뷰 컨트롤러 : ", "MainController")
        print("==============================")
        print("")
        let rootNC = UINavigationController(rootViewController: rootVC)
        self.window?.rootViewController = rootNC
        self.window?.makeKeyAndVisible()
        
        
        
        
        // 호스트명 없음 : 스키마 접속 형태 : [testui://?name=twok&age=28]
        // 호스트명 사용 : 스키마 접속 형태 : [testui://call?name=twok&age=28]
        // 참고 : 스키마 형태를 testui://? 물음표를 넣으면 주소 형식으로 데이터 파싱을 쉽게 수행
        let urlStr = url.absoluteString // [스키마 주소값 가지고 온다]
        let components = URLComponents(string: urlStr) // 전체 주소
        //let pathData = components?.path ?? "" // http url path 경로
        let schemeData = components?.scheme ?? "" // 스키마
        let hostData = components?.host ?? "" // 호스트
        let parameter = components?.query ?? "" // 파라미터
        
        print("")
        print("==============================")
        print("[SceneDelegate > schemeHandleURL() : 스키마 접속 확인 및 파라미터 값 확인 실시]")
        print("urlStr : ", urlStr)
        print("scheme : ", schemeData)
        print("host : ", hostData)
        print("query : ", parameter)
        print("==============================")
        print("")
        
        if parameter.count > 0 && parameter != "" { // 파라미터 값이 널이 아닌 경우
            let items = components?.queryItems ?? []
            
            // name, age 파라미터 값을 저장하기 위한 변수
            var param_name = ""
            var param_age = ""
            
            for item in items { // for 문을 돌면서 데이터 확인 실시
                print("==============================")
                print("[SceneDelegate > schemeHandleURL() : 스키마 파라미터 파싱 수행]")
                print("name : \(item.name)  /  value : \(item.value ?? "")")
                //print("name :", item.name)
                //print("value :", item.value ?? "")
                print("==============================")
                
                if item.name == "name" { //파라미터 명칭이 name 인 경우
                    param_name = item.value ?? "" // value 저장
                }
                if item.name == "age" { //파라미터 명칭이 name 인 경우
                    param_age = item.value ?? "" // value 저장
                }
            }
            
            
            
            
            // [뷰 컨트롤러 데이터 지정 실시]
            if param_name.count > 0 && param_name != "" &&
                param_age.count > 0 && param_age != "" { // 저장된 파라미터가 널값이 아닐 경우
                let topViewController = self.window?.rootViewController as? UINavigationController
                let currentVC = topViewController?.topViewController as? MainController
                
                // 뷰 컨트롤러 : url 스키마로 접속을 체크하는 곳으로 데이터 전송
                currentVC?.urlSchemeCheck(_name: param_name, _age: param_age)
            }
        }
    }



    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.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // 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.

        // Save changes in the application's managed object context when the application transitions to the background.
        (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
    }

}
 

[주인 : 소스코드 : MainController]

import UIKit

class MainController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        print("")
        print("==============================")
        print("[MainController > viewDidLoad : 액티비티 시작 수행]")
        print("==============================")
        print("")
    }
    
    
    func urlSchemeCheck(_name : String, _age : String){
        print("")
        print("===============================")
        print("[MainController > urlSchemeCheck() : 스키마 접속 체크 및 파라미터 정보 확인 실시]")
        print("_name : ", _name)
        print("_age : ", _age)
        print("===============================")
        print("")
        
        // 팝업창 호출 실시 [필요 시 데이터를 받아서 다른 로직 처리 가능]
        self.showAlert(tittle: "[스키마 정보]", content: "이름 : \(_name)  /  나이 : \(_age)", okBtb: "확인", noBtn: "")
    }
    
    
    // [alert 팝업창 호출 메소드 정의 실시 : 이벤트 호출 시]
    // 호출 방법 : showAlert(tittle: "title", content: "content", okBtb: "확인", noBtn: "취소")
    func showAlert(tittle:String, content:String, okBtb:String, noBtn:String) {
        // [UIAlertController 객체 정의 실시]
        let alert = UIAlertController(title: tittle, message: content, preferredStyle: UIAlertController.Style.alert)
        
        // [인풋으로 들어온 확인 버튼이 nil 아닌 경우]
        if(okBtb != "" && okBtb.count>0){
            let okAction = UIAlertAction(title: okBtb, style: .default) { (action) in
                // [확인 버튼 클릭 이벤트 내용 정의 실시]
                return
            }
            alert.addAction(okAction) // 버튼 클릭 이벤트 객체 연결
        }
        
        // [인풋으로 들어온 취소 버튼이 nil 아닌 경우]
        if(noBtn != "" && noBtn.count>0){
            let noAction = UIAlertAction(title: noBtn, style: .default) { (action) in
                // [취소 버튼 클릭 이벤트 내용 정의 실시]
                return
            }
            alert.addAction(noAction) // 버튼 클릭 이벤트 객체 연결
        }
        
        // [alert 팝업창 활성 실시]
        present(alert, animated: false, completion: nil)
    }

}
 

[결과 출력]

 

반응형
Comments