我注意到我有很多重复的代码来获取/发送 JSON 到我的应用程序的 API,但唯一不同的是正在(反)序列化的实体。所以我想出了以下设计(为简洁起见,只有 GET 方法):
HTTPClient.swift
func getEntityJSON<T: JSONSerializable>(
type: T.Type,
url: String,
completionHandler: @escaping (_ result: T?,
_ headers: [String: String]?,
_ statusCode: Int?,
_ error: Error?) -> Void) {
HttpClient.sharedInstance().getJSON(url, completionHandler: { (jsonData, headers, statusCode, error) in
if let error = error {
completionHandler(nil, headers, statusCode, error)
} else {
if let entityData = jsonData {
completionHandler(T.fromJSON(data: entityData), headers, statusCode, nil)
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
打算像这样使用它:
HTTPClient.sharedInstance().getEntity(type: Translation, url: url) { (translation, _, _, _) in
// …Run Code Online (Sandbox Code Playgroud) 是否可以使 @objc 枚举符合 @objc 协议?
下面的枚举显示错误Non-class type 'TestEnum' cannot conform to class protocol 'Testable'
@objc protocol Testable {
var isTesting: Bool { get }
}
// error: Non-class type 'TestEnum' cannot conform to class protocol 'Testable'
@objc enum TestEnum: Int, Testable {
case foo
var isTesting: Bool {
return true
}
}
Run Code Online (Sandbox Code Playgroud) 我遇到了一个情况,我想用一个委托注册2个不同的UIViewControllers,因为我的项目一次显示2个UIViewControllers.当我触发事件时,我希望两个控制器都得到通知,但不幸的是只有任何一个控制器才能接收到这两个事件.
这是示例代码:
@objc protocol DownloaderDelegate: class {
func complete()
}
class Downloader {
static let sharedInstance = Downloader()
weak var delegate: DownloaderDelegate?
private init() {
}
func downloadFile() {
self.delegate!.complete()
}
}
Run Code Online (Sandbox Code Playgroud)
我在UIViewControllers中使用它就像这样:
override viewDidLoad() {
super.viewDidLoad()
Downloader.sharedInstance.delegate = self
}
Run Code Online (Sandbox Code Playgroud)
知道如何让视图控制器从单个委托中侦听事件吗?
这就是我想要做的事情:
import Foundation
import UIKit
protocol PlayableMediaItem {
func title() -> String
func albumArt() -> UIImage
func audioFileURL() -> URL
}
struct AudioTrack : Codable, PlayableMediaItem {
var title: String
var desc:String
var albumArtDemoName:String
var audioDemoFilename:String
func albumArt() -> UIImage {
let image = UIImage(named: albumArtDemoName)
return image!
}
func audioFileURL() -> URL {
return Bundle.main.url(forResource: audioDemoFilename, withExtension: "mp3")!
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到AudioTrack不符合PlayableMediaItem协议的错误,因为该title属性不是方法,它是属性.
我怎样才能设置此让title,albumArt等可以实现为两种属性或方法,只要他们给我回到正确的类型?
我的一些实现可能只是属性,而其他的是计算.
我正在尝试为 NSXPCInterface 构建一个协议,但遇到了一个奇怪的问题。
我创建了一个协议:
public protocol AProtocol {
//functions in here
}
Run Code Online (Sandbox Code Playgroud)
当我想将其添加到 NSXPCConnection 的导出接口时,
let newConnection: NSXPCConnection
newConnection.exportedInterface = NSXPCInterface(with: AProtocol.self)
Run Code Online (Sandbox Code Playgroud)
我收到这个奇怪的错误:
Cannot convert value of type 'AProtocol.Protocol' to expected argument type 'Protocol'
Run Code Online (Sandbox Code Playgroud) 我目前对协议中的 gettable 属性有点困惑。考虑这个例子:
protocol Person {
var name: String { get }
}
Run Code Online (Sandbox Code Playgroud)
我希望该name属性是只读的,但我发现您可以在没有编译器投诉的情况下更改该值:
struct Driver: Person {
var name: String
}
var driver = Driver(name: "Ryan")
driver.name = "Changed!"
Run Code Online (Sandbox Code Playgroud)
如果我们driver用let关键字定义,那么编译器会引发错误,但如果我理解正确,它与协议无关,因为常量结构在 Swift 中设计为不可变的。
方法交互的行为与我预期的一样:
extension Person {
mutating func changeName(_ newName: String) {
self.name = newName // Error: 'name' is a get-only property
}
}
Run Code Online (Sandbox Code Playgroud)
我是 Swift 的新手,提到的细微差别可能没有任何实际用途,但是这种行为让我问自己,我是否对结构的工作方式缺乏一些基本的了解。
我有一个这样的代码(在操场上玩:
protocol ServiceProtocol {
var enabled: Bool { get set }
}
class Service: ServiceProtocol {
var enabled: Bool = false
}
class A {
let service = Service()
}
class B {
let service: ServiceProtocol = Service()
}
let a = A()
let b = B()
a.service.enabled = false
b.service.enabled = false // <-- the error is here: Cannot assign to property: 'service' is a 'let' constant
Run Code Online (Sandbox Code Playgroud)
如果我引用service为Service(class A),则一切都按预期进行。在 class 中B,service …