仅当 iOS11 可用时才包含 class 的扩展名
Include an extension for a class only if iOS11 is available
我正在尝试扩展用 Obj-C 编写的 class,并包含一个用 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' is partial: introduced in iOS 11.0
我假设包含 @available(iOS 11.0, *)
会生成一个 SWIFT_AVAILABILITY(ios,introduced=11.0)
来封装整个接口,但我错了。
有办法解决这个问题吗?
更新
我实现了一个玩具示例。
这是玩具ViewController:
这是 swift 扩展名:
这里是生成的 dnd_toy-Swift.h 文件。
你是对的,这只是一个警告,但我的问题是我们必须将所有警告视为我们项目中的错误。
关于如何从此处消除此警告的任何想法?
您所做的一切都是正确的,即使不是非常迟钝,投诉也是准确的。
基本上,由于您已经(正确地)将该函数标记为在 iOS 11 中可用,编译器将警告您在任何针对< iOS 的代码中使用它11.
因此,您可以通过将部署目标设置为 iOS 11 来消除投诉,这意味着 iOS 10 的用户根本不允许安装它。或者,您可以使用新的(对 obj-c)@available
构造来防止使用 API.
if (@available(iOS 11, *)) {
[self setupDropInteractions];
}
此构造不受 Xcode 8 支持,因为它是 Swift.
提供的#available 构造的最新反向端口
更新
我正在澄清我的来历。看来我无法重现提问者所遇到的情况,所以我正在演示我能够做什么。
我可以生成 2 个不同的编译器警告,它们很相似,但似乎与原始问题不一样。
这是我从 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 属性 以符合协议
问题 2:使用扩展中声明的方法
有了更多重现编译错误的信息,我就能提供更多帮助。
更新 2:希望是最后一次
我发现我们之间的行为差异是由于我的项目是使用 Xcode 8.3 创建的,然后迁移到 9。发生这些事情后,构建设置似乎有所不同。有问题的设置是 CLANG_WARN_UNGUARDED_AVAILABILITY
,我认为这是 Xcode 9.
的新设置
在迁移过程中,项目最终是这样的:
- 这映射到
.pbxproject
文件中的术语 YES
创建新项目后:
- 这映射到术语
YES_AGGRESSIVE
是 .pbxproject
文件
此设置在 WWDC2017 - What's new in LLVM 中进行了讨论,但他们所说的任何内容都不会暗示这种细微的行为差异。我猜这是 clang 的错误以及它如何处理两个设置之间的差异(但我欢迎其他输入)。我相信您已经知道,此代码在 iOS 10 上运行良好。此外,如果您将设置更改为简单的 "Yes",您仍然会收到有关 [=71= 的正确警告] 11 APIs.
Xcode 如果将@available 添加到每个方法,将构建 9 beta 4。如果仅在扩展级别添加@available,构建仍然会失败。
在 ObjC 中,将 API_AVAILABLE(ios(11.0))
添加到函数定义的末尾将抑制警告。像这样:
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0))
{
... function implementation ...
}
我正在尝试扩展用 Obj-C 编写的 class,并包含一个用 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' is partial: introduced in iOS 11.0
我假设包含 @available(iOS 11.0, *)
会生成一个 SWIFT_AVAILABILITY(ios,introduced=11.0)
来封装整个接口,但我错了。
有办法解决这个问题吗?
更新
我实现了一个玩具示例。
这是玩具ViewController:
这是 swift 扩展名:
这里是生成的 dnd_toy-Swift.h 文件。
你是对的,这只是一个警告,但我的问题是我们必须将所有警告视为我们项目中的错误。
关于如何从此处消除此警告的任何想法?
您所做的一切都是正确的,即使不是非常迟钝,投诉也是准确的。
基本上,由于您已经(正确地)将该函数标记为在 iOS 11 中可用,编译器将警告您在任何针对< iOS 的代码中使用它11.
因此,您可以通过将部署目标设置为 iOS 11 来消除投诉,这意味着 iOS 10 的用户根本不允许安装它。或者,您可以使用新的(对 obj-c)@available
构造来防止使用 API.
if (@available(iOS 11, *)) {
[self setupDropInteractions];
}
此构造不受 Xcode 8 支持,因为它是 Swift.
提供的#available 构造的最新反向端口更新
我正在澄清我的来历。看来我无法重现提问者所遇到的情况,所以我正在演示我能够做什么。
我可以生成 2 个不同的编译器警告,它们很相似,但似乎与原始问题不一样。
这是我从 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.
在迁移过程中,项目最终是这样的:
- 这映射到
.pbxproject
文件中的术语YES
创建新项目后:
- 这映射到术语
YES_AGGRESSIVE
是.pbxproject
文件
此设置在 WWDC2017 - What's new in LLVM 中进行了讨论,但他们所说的任何内容都不会暗示这种细微的行为差异。我猜这是 clang 的错误以及它如何处理两个设置之间的差异(但我欢迎其他输入)。我相信您已经知道,此代码在 iOS 10 上运行良好。此外,如果您将设置更改为简单的 "Yes",您仍然会收到有关 [=71= 的正确警告] 11 APIs.
Xcode 如果将@available 添加到每个方法,将构建 9 beta 4。如果仅在扩展级别添加@available,构建仍然会失败。
在 ObjC 中,将 API_AVAILABLE(ios(11.0))
添加到函数定义的末尾将抑制警告。像这样:
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0))
{
... function implementation ...
}