Upgrading Swift 3 to 4, swift extension no longer

2019-02-26 00:48发布

问题:

I just finished upgrading a mixed language project (objective-c and Swift) from Swift 3 to Swift 4.

Everything seemed to go well except all of my Swift extensions are no longer accessible in objective-c. I can't figure out how to get any Swift extension to show up in objective-c. I've tried searching, but I can't find any mention of changes to extensions in Swift 4 except for loosening up the private scope.

  • All of these extensions were accessible from Objective-c in Swift 3, so there are no incompatible types (structs or non-raw enums).
  • The extensions are marked public.
  • The extensions are part of the same target and in the same project as the objective-c files.
  • Yes, I have imported "ProjectName-Swift.h" in the relevant objective-c files.
  • Other compatible Swift classes do show up. It seems just the extensions are missing.
  • I've tried marking each func public as well.

For example, the following extension used to be available to objective-c code when I was using Swift 3:

public extension UIAlertController {

  class func alert(_ title: String? = nil, message: String? = nil) -> UIAlertController {
    return UIAlertController(title: title, message: message, preferredStyle: .alert)
  }

  @discardableResult func action(_ action: String) -> UIAlertController {
    self.addAction(UIAlertAction(title: action, style: .default, handler: nil))
    return self
  }

  @discardableResult func action(_ action: String, style: UIAlertActionStyle = .default, onSelected: ((UIAlertAction) -> Void)? = nil) -> UIAlertController {
    self.addAction(UIAlertAction(title: action, style: style, handler: onSelected))
    return self
  }

  @discardableResult func cancel(_ action: String? = "Cancel", onCancel: ((UIAlertAction) -> Void)? = nil) -> UIAlertController {
    self.addAction(UIAlertAction(title: action, style: .cancel, handler: { alert in
      onCancel?(alert)
    }))
    return self
  }

  @discardableResult func destructive(_ action: String, onDestruct: @escaping ((UIAlertAction) -> Void)) -> UIAlertController {
    self.addAction(UIAlertAction(title: action, style: .destructive, handler: { action in
      onDestruct(action)
    }))
    return self
  }

  func presentOn(_ viewController: UIViewController, animated: Bool = true) {
    viewController.present(self, animated: animated, completion: nil)
  }
}

回答1:

A super simple solution is to just add @objc public extension to the declaration of each Swift extension.