ios - 无法声明具有内部要求的公共(public)协议(protocol)扩展

标签 ios swift xcode swift-protocols swift-extensions

我正在编写一个媒体播放器应用程序,并创建了我自己的框架来管理所有播放器功能。在这个框架中,我有一个名为 PlayerControllerType 的公共(public)协议(protocol)和一个内部协议(protocol) _PlayerControllerType。在 PlayerControllerType 中,我声明了所有方法和属性,它们应该可以从框架外部访问。在 _PlayerControllerType 中,我定义了几个属性,框架内实现 PlayerControllerType 的具体类型使用这些属性。其中一种类型是 PlayerController。其声明如下:

public class PlayerController<Item: Equatable>: NSObject, PlayerControllerType, 
_PlayerControllerType, QueueDelegate

现在我想为我的框架中的类提供几个默认实现,它们符合 PlayerControllerType 和内部 _PlayerControllerType,例如:

import Foundation  
import MediaPlayer  

public extension PlayerControllerType where Self: _PlayerControllerType, Item == MPMediaItem, Self.QueueT == Queue<Item>, Self: QueueDelegate {  

    public func setQueue(query query: MPMediaQuery) {  
        queue.items = query.items ?? []  
    }  

}  

这在 Xcode 7 Beta 4 中按预期工作。昨天我更新到 Beta 6 并收到此错误: “扩展不能公开,因为它的通用要求使用内部类型”(另请参见屏幕截图)。 The error in Xcode

我觉得这个错误很烦人。当然,我的框架之外的任何类型都不会受益于此扩展,因为它无法访问内部协议(protocol) _PlayerControllerType,但它对于我的框架内同时实现 PlayerControllerType 的类型非常有用和 _PlayerControllerType

这只是 Swift 编译器中的错误还是预期的行为? 非常不幸的是,这不再有效,因为现在我必须将这些方法放入新创建的基类中,用于我所有的 PlayerController。

如有任何帮助或反馈,我们将不胜感激。

编辑: 以下是协议(protocol)及其扩展的简短示例:

public protocol PlayerControllerType {
    typealias Item
    var nowPlayingItem: Item {get}
    func play()
}

protocol _PlayerControllerType {
    var nowPlayingItem: Item {get set}
}

public extension PlayerControllerType where Self: _PlayerControllerType {

    /* 
    I want to provide a default implementation of play() for
    all my PlayerControllers in my framework (there is more than one).
    This method needs to be declared public, because it implements a
    requirement of the public protocol PlayerControllerType. 
    But it cannot be implemented here, because this extension 
    has the requirement _PlayerControllerType. It needs this requirement,
    because otherwise it cannot set the nowPlayingItem. I don't want to
    expose the setter of nowPlayingItem.
    I could make a base class for all PlayerControllers, but then I'm
    restricted to this base class because Swift does not support
    multiple inheritance.
    */
    public func play() {
        if nowPlayingItem == nil {
            nowPlayingItem = queue.first
        }
        // Other stuff
    }

}

最佳答案

您需要将 _PlayerControllerType 协议(protocol)的访问级别声明为“public”。

public protocol _PlayerControllerType {
   // some code
}

根据(The Swift Programming Language - Access Control),

A public members cannot be defined as having an internal or private type, because the type might not be available everywhere that the public variable is used. Classes are declared as internal by default, so you have to add the public keyword to make them public.

A member (class/protocol/function/variable) cannot have a higher access level than its parameter types and return type, because the function could be used in situations where its constituent types are not available to the surrounding code.

关于ios - 无法声明具有内部要求的公共(public)协议(protocol)扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32444828/

相关文章:

ios - 单点触摸错误: mtouch exited with code 1

ios - Xcode 构建错误 - 缺少所需的体系结构 i386

ios - 如何在 tvOS 上显示 GameCenter 排行榜?

ios - 如何将十六进制字符串提供给 Hmac SHA256 Objective-C ?

ios - 是否可以在 iOS 6/7 上自定义数字键盘中的左下角按钮?

macos - NSMenuItem 未快速启用

ios - 调用 dequeueReusableCell(withIdentifier :for:) swift 时内存泄漏

ios - 可用于 goto swift 的其他替代方法

ios - Xcode 4.6 和 Xcode 5 安装在一起

ios - XCode 6.3.1 启动图像源不适用于 Assets 目录