Harshal Wani
Harshal Wani

Reputation: 2349

Access delegate protocol from Swift framework into Objective C

I've created the Swift framework and integrated into ObjC project.

Now, I want to pass/access delegate handler in ObjC.

Swift Framework contains UIViewController with close and submit button.

ListViewController.swift SwiftFramework

public protocol ListHandler {
    func submit(options: String)
    func close()
}

public class ListViewController: UIViewController {

    public var handler: ListHandler?

    @objc func dismiss(_ sender: UIButton) {
        handler?.close()
    }

    @objc func submit(_ sender: UIButton) {
        handler?.submit(options: "Done")
    }
}

Created MyApp-Bridginh-Header.h And SwiftWrapper.swift to show ListViewController

import SwiftFramework

@objc public class SwiftWrapper: NSObject {

    @objc public var controller: ListViewController?

    override init() {
        print("Working")
    }

    @objc public func showListScreen() -> UIViewController {

        self.controller = ListViewController(title: "List")

        /*
          IMPORTANT: How I can pass this to ObjC called controller?
        */
        // self.controller?.handler =
        return self.controller!
    }
}

Finally in objC view controller, able to show List screen but can't pass delegate and handle submit/close button actions.

ProductListViewController.m

#import "MyApp-Swift.h"

SwiftWrapper *wrapper = [[SwiftWrapper  alloc] init];

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:[wrapper showListScreen]];
[self presentViewController:navController animated:YES completion:nil];

How to access here?

Example project repository: Swift Framework: https://github.com/harshal-wani/SwiftListFramework ObjC project: https://github.com/harshal-wani/SwiftFrameworkDelegateExample

Appreciate your help and suggestions.

Thanks

Upvotes: 2

Views: 1112

Answers (2)

Mehul Patel
Mehul Patel

Reputation: 23053

The wrapper class do the work for you. Let's add all the functions in wrapper class which can manage the internal framework class features.

After viewing your source code, you required to do lot of changes in all the classes. Let's start with ListViewController.

  1. Provide protocol class type to protocol definition. You can use NSObject.

So your protocol will be like:

public protocol ListHandler: NSObject {
    func submit(options: String)
    func close()
}
  1. SwiftWrapper class: Using this class you can not directly pass handler to Objective-C classes, so you need to create one delegate or protocol in this class which can communicate with the Objective-C classes.

So create one delegate in this class:

@objc protocol SwiftWrapperDelgate {
    func submit(options: String)
    func close()
}

Now, the protocol methods of ListViewController must be declared in this class so that we can pass it to Objective-C from here. Create an extension to listen for the protocol methods.

extension SwiftWrapper : ListHandler {
    public func submit(options: String) {
        self.delegate?.submit(options: options)
    }

    public func close() {
        self.delegate?.close()
    }
}

And, don't forgot to assign delegate in showListscreen() function otherwise this method won't invoke.

@objc public func showListscreen() -> UIViewController {
    self.controller = ListViewController(title: "Demo List")
    self.controller?.handler = self
    return self.controller!
}
  1. Now in Objective-C ViewController.m file assign delegate of SwiftWrapper class

    @interface ViewController () <SwiftWrapperDelgate>
    
    @property (nonatomic, strong) SwiftWrapper *wrapper;
    @property (nonatomic, strong) ListViewController *controller;
    
    @end
    

Here I have created global variables for SwiftWrapper & ListViewController

In viewDidLoad() create object of SwiftWrapper class and assign it's delegate to self.

- (void)viewDidLoad {
    [super viewDidLoad];

    self.wrapper = [SwiftWrapper new];
    self.wrapper.delegate = self;
}

And, finally create delegate methods which will be called on action of ListViewController class.

- (void)submitWithOptions:(NSString *)options {
    NSLog(@"Submit button tapped");
}

- (void) close {
    NSLog(@"Close button tapped");
}

Follow these steps to achieve your requirement.

Upvotes: 1

Lu_
Lu_

Reputation: 2685

Continuing from comments, you should make protocol to work with objective-c Start by:

@objc public protocol ListHandler {
    func submit(options: String)
    func close()
}

Then you will be able to make

@objc public var handler: ListHandler?

Upvotes: 0

Related Questions