3

Problem:

The declared static let sharedInstance is not accessible from Objective-C code when building the main app target.

Code:

    @objc public protocol ManagedObjectContextProvider {
          var context: NSManagedObjectContext { get }
    }

@objc public final class ManagedObjectContextProviderImpl: NSObject, ManagedObjectContextProvider {
    public static let sharedInstance: ManagedObjectContextProvider = ManagedObjectContextProviderImpl()
    
    override private init() {}
    
    public var context: NSManagedObjectContext {
        return NSManagedObjectContext.mr_default()
    }
}

Context:

  • This file is contained in 2 targets [main iOS App and Share extension]

  • In the swift to objc generated header of the main app the interface of the swift class is generated as follows:

      @class NSManagedObjectContext;
    
      SWIFT_PROTOCOL("_TtP4<#MyAppName#>28ManagedObjectContextProvider_")
      @protocol ManagedObjectContextProvider
      @property (nonatomic, readonly, strong) NSManagedObjectContext * _Nonnull context;
      @end
    
    
      SWIFT_CLASS("_TtC4<#MyAppName>32ManagedObjectContextProviderImpl")
      @interface ManagedObjectContextProviderImpl : NSObject <ManagedObjectContextProvider>
      - (nonnull instancetype)init SWIFT_UNAVAILABLE;
      @property (nonatomic, readonly, strong) NSManagedObjectContext * _Nonnull context;
      @end
    
  • In the swift to objc generated header of the share extension the interface of the swift class is generated correctly and is:

      @class NSManagedObjectContext;
    
      SWIFT_PROTOCOL("_TtP4<MyAppName>28ManagedObjectContextProvider_")
      @protocol ManagedObjectContextProvider
      @property (nonatomic, readonly, strong) NSManagedObjectContext * _Nonnull context;
      @end
    
    
      SWIFT_CLASS("_TtC4<MyAppName>32ManagedObjectContextProviderImpl")
      @interface ManagedObjectContextProviderImpl : NSObject <ManagedObjectContextProvider>
      SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong)       id <ManagedObjectContextProvider> _Nonnull sharedInstance;)
      + (id <ManagedObjectContextProvider> _Nonnull)sharedInstance SWIFT_WARN_UNUSED_RESULT;
      - (nonnull instancetype)init SWIFT_UNAVAILABLE;
      @property (nonatomic, readonly, strong) NSManagedObjectContext * _Nonnull context;
       @end
    
  • MyAppName specified above is the module name used when generating the Swift to Obj-C header and is the same for both main target and share extension

What I've tried:

  1. Copy the same class declaration in both headers [tricks the compiler but fails at runtime with "unrecognized selector"]
  2. Modify the module name of the extension so that it would have a diff module name than the target

What not to propose as a solution:

  1. To use a different module instead of files belonging to 2 targets
7
  • 1
    did you try to use @objcMembers on the class? Commented Feb 27, 2018 at 10:20
  • or @objc directly on the sharedInstance? Commented Feb 27, 2018 at 10:21
  • stackoverflow.com/questions/24489075/… Commented Feb 27, 2018 at 10:23
  • @PPL, I don't think the scope of that answer is valid anymore with latest swift. I can reach the shared instance when working with my shared extension target even if it is declared as a static let. My problem is I cannot reach it when building the main target. Commented Feb 27, 2018 at 10:37
  • @MilanNosáľ, works with objcMembers. Please propose it as a solution and would be nice if you include a short explanation or direct link to Apple docs regarding usage of objcMembers. Thank you! Commented Feb 27, 2018 at 10:43

1 Answer 1

6

To make members (also static) accessible to ObjC code, you need to add @objc modifier to them, or @objcMembers modifier to class (which is a syntactic sugar to marking all the members with @objc). Read more in documentation.

Sign up to request clarification or add additional context in comments.

1 Comment

I guess the extension module swift version is "3" thus this works for the extension while the main target's swift version is "4" and it no longer generates the interface for all the members of the class if objcMembers is not added. Thank you for the answer.

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.