# SwiftUI and Zoom SDK

**URL:** <https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078>\
**Category:** iOS\
**Created:** [March 19, 2021, 4:15pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078 "2021-03-19T16:15:02Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [March 19, 2021, 4:15pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/1 "2021-03-19T16:15:03Z")

</div>

Hello, I was wondering if there is documentation on integrating the zoom SDK with an application using SwiftUI?

Thanks!

---

<div class="post-metadata">

**Author:** ![Michael\_Condon](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/michael_condon/32/13543_2.png) [@Michael\_Condon](https://devforum.zoom.us/u/Michael_Condon)\
**Post date:** [March 22, 2021, 9:39pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/2 "2021-03-22T21:39:07Z")

</div>

Hey @tspiresweet,

Thanks for using the dev forum!

Currently we do not have documentation or sample applications using SwiftUI, however, SwiftUI is indeed compatible with the SDK.

Thanks!  
Michael

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 1, 2021, 9:14pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/3 "2021-04-01T21:14:57Z")

</div>

@Michael_Condon , thank you for your prompt feedback! Much appreciated.

I’m getting a blank screen once a meetingID and passcode are entered. Here are my steps.

I am able to initialize the SDK and onMobileRTCAuthReturn is successfull

When I use a zoom meetingID and a zoom passcode to join a zoom call I call the following function

func joinMeeting(meetingNumber: String, meetingPassword: String) {  
// Obtain the MobileRTCMeetingService from the Zoom SDK, this service can start meetings, join meetings, leave meetings, etc.  
if let meetingService = MobileRTC.shared().getMeetingService() {  
// Create a MobileRTCMeetingJoinParam to provide the MobileRTCMeetingService with the necessary info to join a meeting.  
// In this case, we will only need to provide a meeting number and password.  
// 2. Set the ViewController to be the MobileRTCMeetingServiceDelegate  
meetingService.delegate = delegate  
let joinMeetingParameters = MobileRTCMeetingJoinParam()  
joinMeetingParameters.meetingNumber = meetingNumber  
joinMeetingParameters.password = meetingPassword  
// Call the joinMeeting function in MobileRTCMeetingService. The Zoom SDK will handle the UI for you, unless told otherwise.  
// If the meeting number and meeting password are valid, the user will be put into the meeting. A waiting room UI will be presented or the meeting UI will be presented.  
meetingService.joinMeeting(with: joinMeetingParameters)  
}  
}

once called, the delegate method onMeetingStateChange changes to is “connecting”  
the next delegate method that is called is onJoinMeetingConfirmed  
and there are no error codes from onMeetingError

Since the app is using swiftUI we are not using a UINavigationController so I changed the meetingSettings to

settings?.disableShowVideoPreview(whenJoinMeeting: true)  
settings?.enableCustomMeeting = false

Also of note, the swiftui app does not have a SceneDelegate.

I think my question may be this. How do I assign which view controller the zoom sdk should present the video feed on if I do not have a uinavigationcontroller?

Thank you

---

<div class="post-metadata">

**Author:** ![Michael\_Condon](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/michael_condon/32/13543_2.png) [@Michael\_Condon](https://devforum.zoom.us/u/Michael_Condon)\
**Post date:** [April 1, 2021, 9:46pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/4 "2021-04-01T21:46:28Z")

</div>

Hey @tspiresweet,

Good question! I am not an expert with SwiftUI, but to answer your question: The SDK hooks into your UI through the UIWindow variable of the AppDelegate. So the AppDelegate must have a UIWindow var. The other thing to double-check is that there is not scene session functions in the AppDelegate and that ApplicationSceneManifest has been removed from the info.plist.

Thanks!  
Michael

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 1, 2021, 9:58pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/5 "2021-04-01T21:58:41Z")

</div>

@Michael_Condon ,

This is good information.

The AppDelegate does have  
var window: UIWindow?

ApplicationSceneManifest is not inside the info.plist

But the driving way SwiftUI loads the first view, which in swift or objective c would be inside didFinishLaunchingWithOptions is

@main  
struct m\_CareApp: App {

```
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@State var hasLoggedIn : Bool = ConfigurationManager.userHasSignedIn()

var body: some Scene {
    WindowGroup {

```

// if hasLoggedIn {  
AppView()  
// } else {  
// LogonView(userHasSignedIn: $hasLoggedIn)  
// }  
}  
}  
}

Which is a Scene and the whole app initiates from that Scene

---

<div class="post-metadata">

**Author:** ![Michael\_Condon](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/michael_condon/32/13543_2.png) [@Michael\_Condon](https://devforum.zoom.us/u/Michael_Condon)\
**Post date:** [April 1, 2021, 10:09pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/6 "2021-04-01T22:09:18Z")

</div>

Hey @tspiresweet,

Hmm, I know I have seen a developer in the past use the SDK with default UI in SwiftUI without a navigation controller. After the SDK completes Authing, can you check what meetingView() returns in the MobileRTCMeetingService?

Thanks!  
Michael

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 1, 2021, 11:10pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/7 "2021-04-01T23:10:47Z")

</div>

@Michael_Condon ,

The meetingView is nil

```
func onJoinMeetingConfirmed() {
            print("Join meeting confirmed.")
            if let meetingService = MobileRTC.shared().getMeetingService() {
                let newView = meetingService.meetingView()
                print("what am I seeing !")
            }
}
```

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 2, 2021, 4:06am UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/8 "2021-04-02T04:06:28Z")

</div>

@Michael_Condon ,

I was able to assign a window to the AppDelegate before the Zoom SDK finalized connecting to a meeting. And I see a quick “waiting” indicator pop up on the screen then disappear once I start to enter the zoom call. From the person initiated the zoom call (laptop) from outside the app they can see video feed from the app but can’t hear anything.

From the app side of things, there is no video feed of the call or the expected zoom interface, and the app is providing no audio.

Here is a quick log what occurs in the app once the meeting ID and passcode are entered

**making the view controller**

**checking video permissions**

**finding window to provide to zoom sdk**

**onMeetingStateChange**

**Connecting**

**Join meeting confirmed.**

**onMeetingStateChange**

**Connecting**

**onMeetingStateChange**

**Connecting**

**2021-04-01 22:56:39.680014-0500 m.Care[1730:821913] \*\*\* CFMessagePort: bootstrap\_register(): failed 1100 (0x44c) ‘Permission denied’, port = 0x26b73, name = '.1862253714.rpc’**

**See /usr/include/servers/bootstrap\_defs.h for the error codes.**

**onMeetingError : MobileRTCMeetError\_Success**

**2021-04-01 22:56:40.421936-0500 m.Care[1730:821913] CreateAudioUnit use hardware aec = 1**

**2021-04-01 22:56:40.645576-0500 m.Care[1730:821913] [IOS].CreateAudioUnit g\_audioUinits.count = 1**

**onMeetingStateChange**

**in meeting**

Thank you  
Travis

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 2, 2021, 8:59pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/9 "2021-04-02T20:59:11Z")

</div>

@Michael_Condon ,

I found the solution. Thank you for helping in guiding me in the right direction.

Travis

---

<div class="post-metadata">

**Author:** ![Michael\_Condon](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/michael_condon/32/13543_2.png) [@Michael\_Condon](https://devforum.zoom.us/u/Michael_Condon)\
**Post date:** [April 2, 2021, 9:15pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/10 "2021-04-02T21:15:48Z")

</div>

Hey @tspiresweet,

Awesome! I am happy to hear 🙂 Can you share what the solution was in case someone else finds this thread?

Thanks!  
Michael

---

<div class="post-metadata">

**Author:** ![tspiresweet](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/tspiresweet/32/1191_2.png) [@tspiresweet](https://devforum.zoom.us/u/tspiresweet)\
**Post date:** [April 8, 2021, 4:39pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/11 "2021-04-08T16:39:51Z")

</div>

@Michael_Condon

SwiftUI has a unique entry point compared to the traditional AppDelegate which occurs in swift and objective c.

SwiftUI uses @main like below

```
@main
struct MyNewApp: App {
    var body: some Scene {
        WindowGroup {
                AppView()
        }
    }
}

```

In SwiftUI we can get access to the AppDelegate by creating a new class, creating a Window variable and setting up the ZoomSDK here

```
class AppDelegate: NSObject, UIApplicationDelegate {
    static let Shared = AppDelegate()
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        setupSDK(sdkKey: zoomSdkKey, sdkSecret: zoomSdkSecret)
        print("didFinishLaunchingWithOptions")

        return true
    }
        func applicationWillEnterForeground(_ application: UIApplication) {
        print("applicationWillEnterForeground")
    }
    func applicationDidBecomeActive(_ application: UIApplication) {
        print("applicationDidBecomeActive")
    }
    func setupSDK(sdkKey: String, sdkSecret: String) {
        let context = MobileRTCSDKInitContext()
        context.domain = "zoom.us"
        context.enableLog = true
        
        let sdkInitializedSuccessfully = MobileRTC.shared().initialize(context)
        
        if sdkInitializedSuccessfully == true, let authorizationService = MobileRTC.shared().getAuthService() {
            authorizationService.clientKey = sdkKey
            authorizationService.clientSecret = sdkSecret
            authorizationService.delegate = self
            authorizationService.sdkAuth()
        }
    }
}

```

To assign the AuthorizationServiceDelege to self we have to make an extension to our custom AppDelegate

```
extension AppDelegate: MobileRTCAuthDelegate {

    // Result of calling sdkAuth(). MobileRTCAuthError_Success represents a successful authorization.
    func onMobileRTCAuthReturn(_ returnValue: MobileRTCAuthError) {
        switch returnValue {
        case .success:
            print("SDK successfully initialized.")
        case .keyOrSecretEmpty:
            assertionFailure("SDK Key/Secret was not provided. Replace sdkKey and sdkSecret at the top of this file with your SDK Key/Secret.")
        case .keyOrSecretWrong, .unknown:
            assertionFailure("SDK Key/Secret is not valid.")
        default:
            assertionFailure("SDK Authorization failed with MobileRTCAuthError: \(returnValue).")
        }
    }

    // Result of calling logIn(). 0 represents a successful login attempt.
    func onMobileRTCLoginReturn(_ returnValue: Int) {
        switch returnValue {
        case 0:
            print("Successfully logged in")
            // This alerts the ViewController that login was successful. NotificationCenter.default.post(name: Notification.Name("userLoggedIn"), object: nil)
        case 1002:
            print("Password incorrect")
        default:
            print("Could not log in. Error code: \(returnValue)")
        }
    }

    // Result of calling logoutRTC(). 0 represents a successful log out attempt.
    func onMobileRTCLogoutReturn(_ returnValue: Int) {
        switch returnValue {
        case 0:
            print("Successfully logged out")
        default:
            print("Could not log out. Error code: \(returnValue)")
        }
    }
}

```

Then back at your entry point add a UIApplicationDelegateAdaptor

```
@main
struct m_CareApp: App {  
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
   ...
}

```

Then for example, in the SwiftUI view in which you want to show the conference call you can do something like this. With getMainWindowToShareWithAppDelegate being the key functions.

```
struct WelcomeToZoom: View {
    
    @State var startInstandMeeting: Bool = false
    @State var loginToMeeting: Bool = false
    @State var meetingNumber: String = ""
    @State var meetingPassword: String = ""
    
    var body: some View {
        VStack(alignment: .center, spacing: 10){
            Spacer()
            HStack{
                Spacer()
                TextField("Enter Meeting Number", text: $meetingNumber)
                Spacer()
            }.padding()
            HStack{
                Spacer()
                TextField("Enter Meeting Passcode", text: $meetingPassword)
                Spacer()
            }.padding()
            Button(action: {
                if meetingPassword.count > 0{
                    self.startInstandMeeting.toggle()
                }
            }) {
                Label("Start Meeting", systemImage: "photo")
            }
            .padding()
            
            if self.startInstandMeeting{
                StartZoomVC(delegate: StartZoomVC.Delegate(), zoomMeetingNumber: $meetingNumber, zoomPasscode: $meetingPassword)
            }
            Spacer()
        }
    }
}

struct StartZoomVC: UIViewControllerRepresentable {  
    
    @Binding var meetingNumber: String
    @Binding var passCode: String
    
    private let delegate: MobileRTCMeetingServiceDelegate
    //private let authDelegate: MobileRTCAuthDelegate
    
    init(delegate: MobileRTCMeetingServiceDelegate, zoomMeetingNumber: Binding<String>, zoomPasscode: Binding<String>) {
        self._meetingNumber = zoomMeetingNumber
        self._passCode = zoomPasscode
        
        self.delegate = delegate
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        print("making the view controller")
        let newVC = UIViewController()
        newVC.view.tag = 83838383
        newVC.view.backgroundColor = .red
        return newVC
    }
    
    func updateUIViewController(_ taskViewController: UIViewController, context: Context) {
        askPermissionsForCameraFeed()
        print("check video permissions")
      
    }
    
    func askPermissionsForCameraFeed() {
        AVCaptureDevice.requestAccess(for: AVMediaType.video) { response in
            if response {
                //access granted
                getMainWindowToShareWithAppDelegate()
            } else {
                print("wtf")
            }
        }
    }
    
    func getMainWindowToShareWithAppDelegate(){
        
        DispatchQueue.main.async {
            let scene = UIApplication.shared.connectedScenes.first
            let windowSceneDelegate = scene?.delegate as? UIWindowSceneDelegate
            let window = (windowSceneDelegate?.window)!
            UIApplication.shared.delegate = AppDelegate.Shared
            let delegate = UIApplication.shared.delegate as! AppDelegate
            delegate.window = window
            print("finding window to provide to zoom sdk")
            joinMeeting(meetingNumber: meetingNumber, meetingPassword: passCode)
        }
        
        
    }
    func startMeeting() {
        // 5. Obtain the MobileRTCMeetingService from the Zoom SDK, this service can start meetings, join meetings, leave meetings, etc.
        if let meetingService = MobileRTC.shared().getMeetingService() {
            
            //6. Set the ViewContoller to be the MobileRTCMeetingServiceDelegate
            meetingService.delegate = delegate

            /***5. Create a MobileRTCMeetingStartParam to provide the MobileRTCMeetingService with the necessary info to start an instant meeting. In this case we will use MobileRTCMeetingStartParam4LoginlUser(), since the user has logged into Zoom.***/
            let startMeetingParameters = MobileRTCMeetingStartParam4LoginlUser()

            // 6. Call the startMeeting function in MobileRTCMeetingService. The Zoom SDK will handle the UI for you, unless told otherwise.
            meetingService.startMeeting(with: startMeetingParameters)
        }
    }
    
    func logIn(email: String, password: String) {
        // 2. Obtain the MobileRTCAuthService from the Zoom SDK, this service can log in a Zoom user, log out a Zoom user, authorize the Zoom SDK etc.
        if let authorizationService = MobileRTC.shared().getAuthService() {
             // 3. Call the login function in MobileRTCAuthService. This will attempt to log in the user.
            authorizationService.login(withEmail: email, password: password, rememberMe: false)
        }else {
            print("authorization service failed")
        }
    }
    
    func joinMeeting(meetingNumber: String, meetingPassword: String) {
            // Obtain the MobileRTCMeetingService from the Zoom SDK, this service can start meetings, join meetings, leave meetings, etc.
            if let meetingService = MobileRTC.shared().getMeetingService() {

                // Create a MobileRTCMeetingJoinParam to provide the MobileRTCMeetingService with the necessary info to join a meeting.
                // In this case, we will only need to provide a meeting number and password.
                // 2. Set the ViewContoller to be the MobileRTCMeetingServiceDelegate
                meetingService.delegate = delegate
                let joinMeetingParameters = MobileRTCMeetingJoinParam()
                joinMeetingParameters.meetingNumber = meetingNumber
                joinMeetingParameters.password = meetingPassword

                // Call the joinMeeting function in MobileRTCMeetingService. The Zoom SDK will handle the UI for you, unless told otherwise.
                // If the meeting number and meeting password are valid, the user will be put into the meeting. A waiting room UI will be presented or the meeting UI will be presented.
                DispatchQueue.main.async {
                    meetingService.joinMeeting(with: joinMeetingParameters)
                }
               
            }
        }

}

 extension StartZoomVC {
    class Delegate: NSObject, MobileRTCMeetingServiceDelegate {

        func onMeetingError(_ error: MobileRTCMeetError, message: String?) {
           
            switch error {
            case .passwordError:
                print("Could not join or start meeting because the meeting password was incorrect.")
            case .success:
                print("onMeetingError : MobileRTCMeetError_Success")
            default:
                print("Could not join or start meeting with MobileRTCMeetError: \(error) \(message ?? "")")
            }
        }
        func onMeetingEndedReason(_ reason: MobileRTCMeetingEndReason) {
            print("Join meeting end reason.")
        }
        // Is called when the user joins a meeting.
        func onJoinMeetingConfirmed() {
            print("Join meeting confirmed.")
        }
        // Is called upon meeting state changes.
        func onMeetingStateChange(_ state: MobileRTCMeetingState) {
           print("onMeetingStateChange")
            switch state {
            case .connecting:
                print("Connecting")
            case .disconnecting:
                print("disconnecting")
            case .ended:
                print("ended")
            case .failed:
                print("failed")
            case .idle:
                print("idle")
            case .inMeeting:
                print("in meeting")
            case .inWaitingRoom:
                print("in waiting room")
            case .joinBO:
                print("join bo")
            case .leaveBO:
                print("leave bo")
            case .locked:
                print("locked")
            case .reconnecting:
                print("reconnecting")
            case .unknow:
                print("unknown")
            case .unlocked:
                print("unlocked")
            case .waitingExternalSessionKey:
                print("waiting external session key")
            case .waitingForHost:
                print("waiting for host")
            case .webinarDePromote:
                print("de promote")
            case .webinarPromote:
                print("promote")
            default:
                print("bad things happened")
            }
        }
     }
 }
```

---

<div class="post-metadata">

**Author:** ![Michael\_Condon](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/michael_condon/32/13543_2.png) [@Michael\_Condon](https://devforum.zoom.us/u/Michael_Condon)\
**Post date:** [April 8, 2021, 6:58pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/12 "2021-04-08T18:58:07Z")

</div>

Hey @tspiresweet,

Wow thank you so much for the detailed post!

Thanks!  
Michael

---

<div class="post-metadata">

**Author:** ![louis.lo](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/louis.lo/32/20729_2.png) [@louis.lo](https://devforum.zoom.us/u/louis.lo)\
**Post date:** [May 7, 2021, 3:29am UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/13 "2021-05-07T03:29:32Z")

</div>

Hello, do you experience app crash when leaving the meeting & rejoin?  
No any clues of why this crash

---

<div class="post-metadata">

**Author:** ![jon.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/jon.zoom/32/13495_2.png) [@jon.zoom](https://devforum.zoom.us/u/jon.zoom)\
**Post date:** [May 7, 2021, 5:26pm UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/14 "2021-05-07T17:26:16Z")

</div>

Hi @louis.lo, thanks for using the dev forum.

Can you please confirm whether you are experiencing this issue with the Zoom app or with the iOS SDK?

Thanks!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/6/1/614bdd549b610bbaa46ff934617683a02bdaa03c.png) [@system](https://devforum.zoom.us/u/system)\
**Post date:** [June 7, 2021, 3:26am UTC](https://devforum.zoom.us/t/swiftui-and-zoom-sdk/46078/15 "2021-06-07T03:26:42Z")

</div>

Closed on June 7, 2021, 3:26am UTC

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
