2

In Swift application I have a ViewController, which call a new modal. This modal have as ViewController Objective-C implementation as ViewController_obj_c.

This modal is shown from Swift code and I want to call the callback property (with UIImage parameter), when the Objective-C code is done.

My callback property "signCompleteCallback" doesn't work. How can I fill a callback property from Swift and call it inside Objective-C?

SwiftViewController.swift:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showModalSegue" {
        if let nextVC = segue.destination as? ViewController_obj_c {

            nextVC.signCompleteCallback = #selector(self.Test)
        }
    }
}

@objc func Test(image: UIImage)
{
    debugPrint("Test method was called as callback with image parameter")
}

ViewController_obj_c.h:

@interface ViewController_obj_c : UIViewController <UIPopoverPresentationControllerDelegate>


@property SEL signCompleteCallback;

- (IBAction)Done_Clicked:(id)sender;

ViewController_obj_c.m:

- (IBAction)Done_Clicked:(UIButton *)sender
{
    UIGraphicsBeginImageContext(_dV.bounds.size);
    [_dV.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

   [self signCompleteCallback]; // Here is the point when I want to call me callback and as a parameter i want to send image
}

2 Answers 2

4

Why don't you use Objective-C block ?

SwiftViewController.swift:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showModalSegue" {
        if let nextVC = segue.destination as? ViewController_obj_c {

            nextVC.signCompleteCallback = testMethod(image:) //`(image:)` is not needed when not ambiguous
        }
    }
}

func testMethod(image: UIImage) {
    debugPrint("Test method was called as callback with image parameter")
}

ViewController_obj_c.h:

@interface ViewController_obj_c : UIViewController<UIPopoverPresentationControllerDelegate>

typedef void (^signCompleteCallbackType)(UIImage * _Nonnull image); //Declare the block type

@property signCompleteCallbackType signCompleteCallback; //Declare the block property using the block type

- (IBAction)Done_Clicked:(id)sender;

@end

ViewController_obj_c.m:

- (IBAction)Done_Clicked:(UIButton *)sender
{
    UIGraphicsBeginImageContext(_dV.bounds.size);
    [_dV.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.signCompleteCallback(image);    //Use the block just like a normal function
}
Sign up to request clarification or add additional context in comments.

Comments

0

I found one solution, but I'm not satisfied with him.

If someone gives a better solution I will happy for it. At this solution I don't like creating a new protocol that I have to inherit in a Swift part (create a new class or inherit it in existing SwiftViewcontroller, doesn't matter)

One way is create @protocol inside Objective-C:

@protocol ObjC_ManagerDelegate 
-(void) signCallBack: (UIImage *)image;
@end

ViewController_obj_c.h:

@interface ViewController_obj_c : UIViewController <UIPopoverPresentationControllerDelegate>

    @property (nonatomic, strong) id <ObjC_ManagerDelegate>delegate;

    - (IBAction)Done_Clicked:(id)sender;
@end

ViewController_obj_c.m:

- (IBAction)Done_Clicked:(UIButton *)sender
{
    UIGraphicsBeginImageContext(_dV.bounds.size);
    [_dV.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self.delegate signCallBack:image];
}

And the Swift part looks like this. Create a new class and inherit it from ObjC_ManagerDelegate:

class SwiftmanagerDelegate: ObjC_ManagerDelegate {
    func signCallBack(_ image: UIImage!) {
        // do something
    } 
}

and finally fill new class as a delegate

SwiftViewController.swift:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showModalSegue" {
        if let nextVC = segue.destination as? ViewController_obj_c {

            nextVC.delegate = SwiftmanagerDelegate()
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.