如果仅当iOS11可用时,才为类添加一个扩展。

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:

enter image description here

这是 Swift 扩展:

enter image description here

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

enter image description here

你说得对,这只是一个警告,但我的问题是我们必须将所有警告视为错误来处理我们的项目。
有没有什么办法可以从这里消除这个警告?
3个回答

8
在ObjC中,将API_AVAILABLE(ios(11.0))添加到函数定义的末尾将会抑制警告。就像这样:
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0))
{
     ... function implementation ...
}

1
有没有一种方法可以检查iOS 11不可用? - SAHM

8
您已经做得很正确了,投诉是准确的,但可能有些晦涩难懂。基本上,由于您(正确地)将该函数标记为 iOS 11 可用,因此编译器会警告您在针对某些低于 iOS 11 的代码中使用它。因此,您可以通过将部署目标设置为 iOS 11 来消除投诉,这意味着 iOS 10 的用户将无法安装它。或者,您可以使用新的(对于 obj-c 来说还比较新的)@available 构造来防止使用该 API。
if (@available(iOS 11, *)) {
    [self setupDropInteractions];
}

由于它是Swift提供的最近的回退构造,因此Xcode 8不支持此构造。

更新

我想澄清一下我的立场。似乎我无法复现提问者所经历的情况,因此我展示了我能够做到的内容。

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

这是从my_project-Swift.h生成的Objc接口:

@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属性以符合协议

enter image description here

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

enter image description here

如果提供更多复制编译错误的信息,我可以提供更多帮助。

更新2:希望这是最后一次

我发现我们之间行为上的差异是因为我的项目是用Xcode 8.3创建的,然后迁移到了9。这些事情发生后,构建设置似乎有所不同。涉及到的设置是 CLANG_WARN_UNGUARDED_AVAILABILITY,我认为这是Xcode 9的新功能。

迁移期间,项目变成了这样:

  • 这映射到.pbxproject文件中的YES术语 enter image description here

新项目创建后:

  • 这映射到.pbxproject文件中的YES_AGGRESSIVE术语 enter image description here

这个设置在WWDC2017 - What's new in LLVM中有讨论,但他们所说的并没有暗示这个微小的行为差异。我猜这是clang和它如何处理两个设置之间的差异的错误(但我欢迎其他意见)。正如你已经发现的那样,这段代码在iOS 10上运行良好。此外,如果将设置更改为简单的“是”,则仍将获得有关iOS 11 API的正确警告。


我正在保护我的 obj-c 代码中的 API,但错误仍然存在。如上所述,扩展生成的接口在 Project_Name-Swift.h 文件中没有防范版本,因此项目将无法编译。我需要构建与 iOS 10 兼容,因此您的第一个解决方案不可行。 - Makaronodentro
@Makaronodentro 你使用了什么机制来防止使用? 你说这是一个'错误', 你是收到运行时错误还是只有编译器的警告? 我提供了两个解决方法来消除警告, 其中1个(使用 if(@available(iOS 11, *))) 完全兼容iOS 10, 但需要Xcode 9。如果你需要用Xcode 8编译,那就是另外一回事了。 - allenh
嗨,非常感谢您的耐心研究!目前我正在使用Xcode 9 Beta-2。 由于我在接口中包含了@available保护和可用性宏定义,因此在我的ViewController中没有收到任何警告。在编译过程中,我遇到了一个“语义问题”。当另一个文件导入“-Swift.h”文件时,我将在界面中获得您可能会遇到的警告作为错误,并且它指向“-Swift.h”中自动生成的obj-c接口。 - Makaronodentro
@Makaronodentro 如果您能在示例项目中重现完全相同的问题或提供更多有关错误的详细信息,我可能能够提供帮助。此外,为确保问题解决,请升级到 beta 3 版本。 - allenh
@Makaronodentro 不用了,我已经能够重现它了,正在检查中。 - allenh

4

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接