web-dev-qa-db-ja.com

iOS11が利用可能な場合にのみ、クラスの拡張機能を含める

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」は部分的です:iOS11.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

単なる警告であるというのは正しかったのですが、私の問題は、すべての警告をプロジェクトのエラーとして扱わなければならないということです。

ここからこの警告を取り除く方法についてのアイデアはありますか?

8
Makaronodentro

@availableが各メソッドに追加されると、Xcode9ベータ4がビルドされます。 @availableが拡張レベルでのみ追加された場合でも、ビルドは失敗します。

4
Eric

ObjCでは、関数定義の最後にAPI_AVAILABLE(ios(11.0))を追加すると、警告が抑制されます。このような:

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0))
{
     ... function implementation ...
}
8

あなたはすべてを正しく行いました、そして苦情は極端に鈍感ではないにしても正確です。

基本的に、その関数をiOS 11で使用可能として(正しく)マークしたので、コンパイラーは、iOS11未満のものを対象とするコードでの使用について警告します。

そのため、展開ターゲットをiOS 11に設定することで、苦情を解消できます。つまり、iOS10のユーザーは単にインストールを許可されません。または、新しい(obj-cへの)@available構造を使用して、APIの使用を防ぐことができます。

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

このコンストラクトは、Swiftが提供する#availableコンストラクトの最近のバックポートであるため、Xcode8ではサポートされていません。

更新

私はどこから来たのかを明確にしています。アスカーが経験している状況を再現できていないようですので、何ができたかをデモンストレーションしています。

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プロパティ

enter image description here

問題2:拡張機能で宣言されたメソッドを使用する

enter image description here

コンパイルエラーを再現するための詳細情報があれば、さらにサポートできるようになります。

更新2:うまくいけば最後

私たちの間の振る舞いの不一致は、私のプロジェクトがXcode 8.3で作成され、その後9に移行されたという事実によるものであることがわかりました。問題の設定はCLANG_WARN_UNGUARDED_AVAILABILITYで、これはXcode9の新機能だと思います。

移行中、プロジェクトは次のようになります。

  • これは、.pbxprojectファイルの用語YESにマップされます enter image description here

新しいプロジェクトの作成後:

  • これは、YES_AGGRESSIVE.pbxprojectファイルであるという用語にマップされます enter image description here

この設定については WWDC2017-LLVMの新機能 で説明されていますが、この小さな動作の違いを示唆するものは何もありません。これはclangのバグであり、2つの設定の違いをどのように処理するかを推測しています(ただし、他の入力を歓迎します)。ご存知のとおり、このコードはiOS 10で正常に実行されます。また、設定を単に「はい」に変更しても、iOS 11APIに関する正しい警告が表示されます。

8
allenh