Etep
Etep

Reputation: 543

Swift CocoaPods Library in Objective-C Project

I have found several online resources on how to include an Objective-C library into a Swift project and a few limited resources on how to do the reverse (which is what I'm after).

I have managed to get my project to compile and run based on the work I did here in this question: Swift CocoaPod Library in Objective-C Project Migration from Swift 3 to 4/5

However whenever I try to access anything from the Swift library in my ObjC project my app crashes with the following...

2020-01-29 14:42:09.756352-0700 Hyperion[13547:2723315] -[HGCircularSlider.RangeCircularSlider setStartPointValue:]: unrecognized selector sent to instance 0x1074088c0
2020-01-29 14:42:09.763045-0700 Hyperion[13547:2723315] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[HGCircularSlider.RangeCircularSlider setStartPointValue:]: unrecognized selector sent to instance 0x1074088c0'
*** First throw call stack:
(0x18e32ea48 0x18e055fa4 0x18e2325a8 0x1923cf86c 0x18e332af4 0x18e334a7c 0x10208f554 0x10208d4d4 0x192d15dec 0x192be580c 0x10208d388 0x10208b570 0x191d8cab8 0x191d8d160 0x191d11b40 0x191d11c6c 0x191d192c0 0x191d23b84 0x191d23f70 0x191d1716c 0x191d119a0 0x191d87134 0x191d87838 0x1924f3d74 0x1924f7224 0x1924f70d0 0x1924f739c 0x191d87290 0x191d87838 0x1924f3d74 0x1924f7224 0x1924f70d0 0x1924f739c 0x191d87290 0x191d87838 0x191cceaec 0x191ccdf08 0x191cca9c8 0x191cca7e0 0x191ccde54 0x1923a2e50 0x191b3e148 0x1923a2e50 0x191dd9494 0x191dd97f8 0x191b40b58 0x1923a2e50 0x191dd9494 0x191dd97f8 0x191dd8814 0x1923dc3d4 0x1923dd714 0x1923b9e2c 0x192431fa4 0x192434500 0x19242d374 0x18e2aca00 0x18e2ac958 0x18e2ac0f0 0x18e2a723c 0x18e2a6adc 0x19822c328 0x1923a1ae0 0x1020de520 0x18e130360)
libc++abi.dylib: terminating with uncaught exception of type NSException

As I state in the answer of my question linked above I have written a Swift class that exposes the CocoaPod's library functions I need which allows my project to compile...

import Foundation
import HGCircularSlider

@objc public class CircularSliderObjc: RangeCircularSlider
{
    @objc override open var startPointValue: CGFloat {

        get {
            return super.startPointValue;
        }

        set {
            super.startPointValue = newValue;
        }
    }

    @objc override open var endPointValue: CGFloat {

        get {
            return super.endPointValue;
        }

        set {
            super.endPointValue = newValue;
        }
    }

    @objc override open var endThumbImage: UIImage? {

        get {
            return super.endThumbImage;
        }

        set {
            super.endThumbImage = newValue;
        }
    }

    @objc override open var startThumbImage: UIImage? {

        get {
            return super.startThumbImage;
        }

        set {
            super.startThumbImage = newValue;
        }
    }
}

As you can see in the project I have exposed startPointValue as both a set and a get. However invoking this function at runtime causes the crash.

Here is the calling class's header...

#import "BaseViewController.h"
#import "Hyperion-Swift.h"

@interface TemperatureDeviceViewController : BaseViewController

@property (weak, nonatomic) IBOutlet CircularSliderObjc *rangeSlider;

And the call in my .m file...

[self.rangeSlider setStartPointValue:[self getSliderValueForTemp:startValue]];

I'm assuming I'm missing one critical step here?

UPDATE #1

I've tried the answer suggested by Max which makes a lot of sense. However because this is an IBOutlet it in my ViewController his solution really doesn't work for my use case here.

I did some further debugging and put breakpoints all over my startPointValue function in order to see what the "super" was referencing. However none of the breakpoints are triggered before the crash happens. Therefore I'm not sure that the call to "super" is the actual cause? Verdict is still out on this one I think.

Upvotes: 1

Views: 81

Answers (1)

Max
Max

Reputation: 22375

Try redesigning your wrapper class to encapsulate rather than inherit from the framework class. For example:

@objc public class CircularSliderObjc
{
    let slider: RangeCircularSlider // NOT @objc!
    @objc var startPointValue: CGFloat {
        get {
            return slider.startPointValue;
        }
        set {
            slider.startPointValue = newValue;
        }
    }

That way Objective-C doesn't even need to know that the Swift class exists at all. My guess is that this is crashing on the super, where something Swift-specific is being accessed from Objective-C.

Upvotes: 1

Related Questions