8

我正在尝试扩展一个用 Obj-C 编写的类,并包含一个用 Swift 编写的扩展,使其符合UIDropInteractionDelegate,如下所示:

@available(iOS 11.0, *)
extension NoteEditViewController: UIDropInteractionDelegate {
    @available(iOS 11.0, *)
    public func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
        let operation: UIDropOperation
        if session.localDragSession == nil {
            operation = .forbidden
        } else {
            // If a local drag session exists, we only want to move an
            // existing item in the pin board to a different location.
            operation = .forbidden
        }
        return UIDropProposal(operation: operation)
    }

    @objc(setupDropInteractions)
    @available(iOS 11.0, *)
    func setupDropInteractions() {
        // Add drop interaction
        self.view.addInteraction(UIDropInteraction(delegate: self))
    }
}

我的问题是该Project_Name-Swift.h文件包含以下无法编译的代码:

@class UIDropInteraction;
@protocol UIDropSession;
@class UIDropProposal;

// This line is causing the issue saying "'UIDropInteractionDelegate' is partial: introduced in iOS 11.0"
@interface NoteEditViewController (SWIFT_EXTENSION(Bloomberg_Professional)) <UIDropInteractionDelegate>
- (UIDropProposal * _Nonnull)dropInteraction:(UIDropInteraction * _Nonnull)interaction sessionDidUpdate:(id <UIDropSession> _Nonnull)session SWIFT_WARN_UNUSED_RESULT SWIFT_AVAILABILITY(ios,introduced=11.0);
- (void)setupDropInteractions SWIFT_AVAILABILITY(ios,introduced=11.0);
@end

编译器抱怨该文件中的接口是部分的。

'UIDropInteractionDelegate' 是部分的:在 iOS 11.0 中引入

我认为包含@available(iOS 11.0, *)会生成一个SWIFT_AVAILABILITY(ios,introduced=11.0)封装整个接口的,但我错了。

有没有办法来解决这个问题?

更新


我实现了一个玩具示例。

这是玩具 ViewController:

在此处输入图像描述

这是快速扩展:

在此处输入图像描述

这是生成的 dnd_toy-Swift.h 文件。

在此处输入图像描述

您说得对,这只是一个警告,但我的问题是我们必须将所有警告视为项目中的错误。

关于如何从这里摆脱这个警告的任何想法?

4

3 回答 3

8

你做的一切都是正确的,即使不是非常迟钝,投诉也是准确的。

基本上,由于您已(正确地)将该功能标记为在 iOS 11 中可用,编译器将警告您在任何针对 < iOS 11 的代码中使用它。

因此,您可以通过将部署目标设置为 iOS 11 来消除投诉,这意味着根本不允许 iOS 10 的用户安装它。或者,您可以使用 new (to obj-c)@available构造来防范 API 的使用。

if (@available(iOS 11, *)) {
    [self setupDropInteractions];
}

Xcode 8 不支持此构造,因为它是 Swift 提供的 #available 构造的最新反向移植。

更新

我正在澄清我来自哪里。似乎我无法重现提问者所经历的情况,所以我正在展示我能够做到的事情。

我可以产生 2 个不同的编译器警告,它们相似但似乎与原始问题不同。

这是我生成的 objc 接口my_project-Swift.h

@interface NoteEditViewController (SWIFT_EXTENSION(conditional_class_declaration)) <UIDropInteractionDelegate>
    - (UIDropProposal * _Nonnull)dropInteraction:(UIDropInteraction * _Nonnull)interaction sessionDidUpdate:(id <UIDropSession> _Nonnull)session SWIFT_WARN_UNUSED_RESULT SWIFT_AVAILABILITY(ios,introduced=11.0);
    - (void)setupDropInteractions SWIFT_AVAILABILITY(ios,introduced=11.0);
@end

问题 1:声明和 objc 属性以符合协议

在此处输入图像描述

问题 2:使用扩展中声明的方法

在此处输入图像描述

有了更多信息来重现编译错误,我将能够提供更多帮助。

更新 2:希望是最后一个

我发现我们之间的行为差​​异是由于我的项目是用 Xcode 8.3 创建的,然后迁移到 9。在这些事情发生后,构建设置似乎有所不同。有问题的设置是CLANG_WARN_UNGUARDED_AVAILABILITY,我认为这是 Xcode 9 的新设置。

在迁移期间,项目最终如下所示:

  • 这映射到文件 YES中的术语.pbxproject在此处输入图像描述

创建新项目后:

  • 这映射到术语YES_AGGRESSIVE.pbxproject文件 在此处输入图像描述

此设置在WWDC2017 - What's new in LLVM中进行了讨论,但他们所说的任何内容都不会暗示这种微小的行为差异。我猜这是clang的错误以及它如何处理两种设置之间的差异(但我欢迎其他输入)。我相信您已经知道,此代码在 iOS 10 上运行良好。此外,如果您将设置更改为简单的“是”,您仍然会收到有关 iOS 11 API 的正确警告。

于 2017-07-10T19:02:40.787 回答
8

在 ObjC 中,添加API_AVAILABLE(ios(11.0))到函数定义的末尾将抑制警告。像这样:

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0))
{
     ... function implementation ...
}
于 2017-10-10T06:25:10.870 回答
4

Xcode 9 beta 4 将构建,如果 @available 添加到每个方法。如果仅在扩展级别添加 @available,构建仍然会失败。

于 2017-07-28T00:18:53.850 回答