为什么这个Swift代码没有编译?
protocol P { }
struct S: P { }
let arr:[P] = [ S() ]
extension Array where Element : P {
func test<T>() -> [T] {
return []
}
}
let result : [S] = arr.test()
Run Code Online (Sandbox Code Playgroud)
编译器说:"类型P不符合协议P"(或者,在Swift的更高版本中,"不支持使用'P'作为符合协议'P'的具体类型.").
为什么不?不知怎的,这感觉就像语言中的漏洞.我意识到问题源于将数组声明arr为协议类型的数组,但这是不合理的事情吗?我认为协议正是为了帮助提供类似层次结构的结构?
我的应用程序具有本地缓存,并从/向服务器发送/接收模型.所以我决定构建一个map [String:Codable.Type],基本上能够解码我在本地创建或从服务器接收的通用缓存上的任何内容.
let encoder = JSONEncoder()
let decoder = JSONDecoder()
var modelNameToType = [String : Codable.Type]()
modelNameToType = ["ContactModel": ContactModel.Self, "AnythingModel" : AnythingModel.Self, ...]
Run Code Online (Sandbox Code Playgroud)
无论我在App上创建什么,我都可以成功编码并存储在缓存中,如下所示:
let contact = ContactModel(name: "John")
let data = try! encoder.encode(contact)
CRUD.shared.storekey(key: "ContactModel$10", contact)
Run Code Online (Sandbox Code Playgroud)
我想像这样解码:
let result = try! decoder.decode(modelNameToType["ContactModel"]!, from: data)
Run Code Online (Sandbox Code Playgroud)
但我得到错误:
无法使用类型的参数列表(Codable.Type,from:Data)调用'decode'
我究竟做错了什么?任何帮助表示赞赏
修复类型有效,并解决任何本地请求,但不能解决远程请求.
let result = try! decoder.decode(ContactModel.self, from: data)
Run Code Online (Sandbox Code Playgroud)
联系型号:
struct ContactModel: Codable {
var name : String
}
Run Code Online (Sandbox Code Playgroud)
对于远程请求,我会有这样的函数:
func buildAnswer(keys: [String]) -> Data {
var result = [String:Codable]()
for key …Run Code Online (Sandbox Code Playgroud) 我在获取声明为的变量的大小时遇到问题 Any.Type
请参阅以下游乐场代码:
我有这个功能:
func genericSizeMe<T> (_ : T.Type) -> Int
{
return MemoryLayout<T>.size
}
Run Code Online (Sandbox Code Playgroud)
我是这样运行的:
let size1 = genericSizeMe(UInt32.self) // 4
let size2 = genericSizeMe(UInt16.self) // 2
var type1: UInt32.Type = UInt32.self
let size3 = genericSizeMe(type1) // 4
var type2: UInt16.Type = UInt16.self
let size4 = genericSizeMe(type2) // 2
var type3: Any.Type = UInt32.self
let size5 = genericSizeMe(type3) //ERROR
Run Code Online (Sandbox Code Playgroud)
这给出了错误:
/*
Playground execution failed:
error: MyPlayground.playground:14:13: error: cannot invoke 'genericSizeMe' with an argument list of type '(Any.Type)'
let size5 …Run Code Online (Sandbox Code Playgroud) 以一个非常接近在下面看一下:
// Note that this protocol can only be applied to reference types.
protocol Ref: class {
var zibbles: Int { get set }
}
class Reference: Ref {
var zibbles: Int = 42
}
// Note very carefully that we are NOT passing an
// instance, but a type itself.
func thwip<T: AnyObject>(into target: T.Type) {
}
// This compiles.
thwip(into: Reference.self)
// This fails to compile.
thwip(into: Ref.self)
Run Code Online (Sandbox Code Playgroud)
无论情况多么罕见,这是语言应该能够完成的事情.编译器知道Ref必须符合的任何实例AnyObject,因此类型约束thwip应该可以工作,但事实并非如此.
请注意,如果我们 …
我们已经为我们的s实现了一个协议,Reusable以简化UITableView注册/出队实现UITableViewCell。
protocol Reusable: class {
static var defaultIdentifier: String { get }
}
extension Reusable where Self: UITableViewCell {
static var defaultIdentifier: String {
return String(describing: self)
}
}
class TestTableViewCell: UITableViewCell, Reusable { }
class AnotherTestTableViewCell: UITableViewCell, Reusable { }
Run Code Online (Sandbox Code Playgroud)
然后,有一个扩展UITableView喜欢:
extension UITableView {
func register<T: UITableViewCell & Reusable>(_: T.Type) {
register(UINib(nibName: T.defaultIdentifier, bundle: nil), forCellReuseIdentifier: T.defaultIdentifier)
}
}
Run Code Online (Sandbox Code Playgroud)
以及它的用法:
let tableView: UITableView = UITableView()
tableView.register(TestTableViewCell.self)
tableView.register(AnotherTableViewCell.self)
Run Code Online (Sandbox Code Playgroud)
一切正常,但我们想将这些类型移动到数组中,以便进行排序。这就是我们卡住的地方,这不起作用:
let viewCells = …Run Code Online (Sandbox Code Playgroud)