加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ios – 无法声明具有内部要求的公共协议扩展

发布时间:2020-12-14 19:09:04 所属栏目:百科 来源:网络整理
导读:我正在编写媒体播放器应用程序,并创建了自己的框架来管理所有播放器功能.在这个框架中,我有一个名为PlayerControllerType的公共协议和一个内部协议_PlayerControllerType.在PlayerControllerType中,我已经声明了所有方法和属性,这些方法和属性应该可以从框架
我正在编写媒体播放器应用程序,并创建了自己的框架来管理所有播放器功能.在这个框架中,我有一个名为PlayerControllerType的公共协议和一个内部协议_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

我发现这个错误很刺激.当然,我的框架之外的类型没有这个扩展的好处,因为它无法访问内部协议_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
    }

}

解决方法

您需要将_PlayerControllerType协议的访问级别声明为“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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读