0
votes

I'm using a Swift CocoaPod in my Objective-C project. Originally it was a Swift 3 project and I simply had to add the #import "<Project Name>-Swift.h" into my .m or .h file. I've since updated to the latest version of the CocoaPod which I believe is now Swift 5. Therefore this is no longer working as none of the properties can be found.

I've looked at a number of different resources online including Apple's documentation and the procedure is unclear here what to do. It seems I have to go in and edit the .swift file and add @objc in front of each property or method I wish to access? This seems to go against what CocoaPods is about as the next time I update all my changes will be blown away.

I tried looking at the generated header but when I highlight the #import "<Project Name>-Swift.h" line I just get taken to the NSObject declaration. Obviously it is just a build time item I'm guessing.

According to the Apple documentation (https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c) the Swift declarations must be marked with the public or open modifier and when I checked the swift file I found that they indeed are.

The pod I'm using is HGCircularSlider. An example of what I'm trying to access is in the RangeCircularSlider class is here:

    open var startPointValue: CGFloat = 0.0 {
        didSet {
            guard oldValue != startPointValue else { return }

            if startPointValue < minimumValue {
                startPointValue = minimumValue
            }

            if distance > 0 {
                endPointValue = startPointValue + distance
            }

            setNeedsDisplay()
        }
    }

As we can see here the declaration is public. I'm assuming I need to set some sort of build setting?

In addition I have set use_frameworks! in my Podfile. I've also checked that the build target within the pod project and Objective-C Generated Interface Header Name is HGCircularSlider-Swift.h. This is exactly what I'm using in my Objc .m file.

Welcome any thoughts or comments where else I should look?

Update 1

One other thing of note. In my .h and .m I have a @property of type RangeCircularSlider which it can see fine. No error there. It's accessing the properties and methods within the object that is causing the errors.

Property 'startPointValue' not found on object of type 'RangeCircularSlider *'

So it sees the swift file but as originally stated, no properties can be found.

Update 2

So I've discovered that if I add @objc to the front of the individual properties I'm trying to access in the Swift file the generated header file then see's them and I can therefore access them. So for the example function above it would then be

@objc open var startPointValue: CGFloat = 0.0 {

But these seems to be a bit of a hack as for when I want to install an updated version of this CocoaPod, then those changes I made to the pod's file would be blown away.

Any suggestions how to do this without having to edit the swift files in the CocoaPod?

1

1 Answers

0
votes

For anyone else that runs across this. The online resources I found were helpful but didn't detail this specific case.

  1. First off. Leave the CocoaPod code as it is. This will allow you to update it without having to worry about modifying it each time.

  2. Next create a Swift file within your Objective C Project. xCode will ask if you want a header generated for it, say yes. This file will be called -Swift.h.

  3. In this Swift file subclass the Swift file from the CocoaPod you are interested in accessing.

For example :

import Foundation
import HGCircularSlider

class CircularSliderObjc: RangeCircularSlider {
}
  1. Next add in the properties you wish to access with getter and setters.
    @objc override open var startPointValue: CGFloat {

        get {
            return super.startPointValue;
        }

        set {
            super.startPointValue = newValue;
        }
    }
  1. Then finally change the import in your Objective-C file to your project's generated header file that I mentioned above (#import "-Swift.h" ). If you have a property pointing to the class in the CocoaPod change it to your new Swift Class. For example :
@property (weak, nonatomic) IBOutlet CircularSliderObjc *rangeSlider;

In this example I have it setup as an Outlet for InterfaceBuilder.

After that, you're done. It seems like a lot of work but it's quite easy and simple. Not quite as fast as just importing the header but since Swift 4 and 5 you can no longer just access open vars in Swift as properties in objc. They need the @objc declaration to make that work. Added security to the language I'm guessing.

Hope this helps someone.