7

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

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

现在我想为我的框架中的类提供几个默认实现,它们符合PlayerControllerType和 internal _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 并收到此错误:“扩展不能被声明为公共,因为它的通用要求使用内部类型”(另见屏幕截图)。 Xcode中的错误

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

这只是 Swift 编译器中的一个错误,还是预期的行为?不幸的是,这不再起作用了,因为现在我必须将这些方法放入我所有 PlayerControllers 的新创建的基类中。

任何帮助或反馈将不胜感激。

编辑:这是协议及其扩展的简短示例:

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
    }

}
4

1 回答 1

3

_PlayerControllerType您需要将协议的访问级别声明为“公共”。

public protocol _PlayerControllerType {
   // some code
}

根据(Swift 编程语言 - 访问控制),

公共成员不能定义为具有内部或私有类型,因为该类型可能并非在使用公共变量的任何地方都可用。默认情况下,类被声明为内部的,因此您必须添加 public 关键字才能将它们公开。

成员(类/协议/函数/变量)不能具有比其参数类型和返回类型更高的访问级别,因为该函数可以在其组成类型对周围代码不可用的情况下使用。

于 2017-03-19T01:29:40.757 回答