目前我一直在研究将代码从目标c转换为swift的任务。工作进展顺利,直到我遇到了一个在目标 c 中工作的通用可修复代码,但我不知道我应该如何在 swift 中做到这一点。
在目标 c 中工作的场景是。
我的 dataManager 类中有一个通用函数
- (void)saveRequest:(id)request forId:(NSNumber *)requestId {
WebRequest *requestData = [[WebRequest alloc] initWithEntity:[NSEntityDescription entityForName:WEB_REQUEST inManagedObjectContext:self.context] insertIntoManagedObjectContext:self.context];
requestData.data = [request toJSON];
requestData.requestId = requestId;
requestData.timestamp = [NSDate date];
[self save];
}
在我的项目中,已经创建了包含 toJSON 函数的请求类。 根据用户更改从我的控制器中,我创建了请求对象并将请求对象传递给此函数,该函数在请求类中调用 toJSON 函数,并且一切都在目标 c 中工作。
但是当我在 swift 中转换这个函数时,它不支持 id 作为函数输入变量,如果我使用 Any 代替 id,那么它会给出一个错误,即 Any 没有任何 toJSON 函数。
由于此函数很常见,因此不同的请求对象将来自不同的控制器。 我不知道我应该如何从听到更远的地方,如果有人有任何想法,请帮助我
你的类应该是这样的
class WebRequest:NSObject
{
var data :Data?
var requestId: NSNumber?
var timestamp: Date?
init(entity:String , insertIntoManagedObjectContext:NSManagedObjectContext)
{
//your code here
}
}
你的代码将如下所示
func saveRequest(request:Request, requestId:NSNumber)
{
let requestData = WebRequest(entity: "entityName", insertIntoManagedObjectContext:self.context)
requestData.data = request.toJSON();
requestData.requestId = requestId;
requestData.timestamp = Date()
}
和 toJson(( 存在的请求类
class Request: NSObject
{
//has some members
func toJSON()->Data
{
return Data()
}
}
有一个现有的 Swift 协议,Codable
(或者如果你愿意,你可以只做Encodable
,因为Codable
只是Encodable
和Decodable
(,它明确设计用于表示 JSON(或其他格式(中的对象。
然后使用JSONEncoder
(而不是JSONSerialization
,例如(将对象编码为 JSON。请参阅编码和解码自定义类型:
考虑一个存储地标名称和创始年份的
Landmark
结构:struct Landmark { var name: String var foundingYear: Int }
将
Codable
添加到继承列表中Landmark
会触发满足Encodable
和Decodable
的所有协议要求的自动一致性:struct Landmark: Codable { var name: String var foundingYear: Int }
然后您可以执行以下操作:
let landmark = Landmark(name: "Big Ben", foundingYear: 1859)
do {
let data = try JSONEncoder().encode(landmark)
print(String(data: data, encoding: .utf8)!)
} catch {
print(error)
}
这将产生这样的JSON:
{
"name": "Big Ben",
"foundingYear": 1859
}
有关详细信息,请参阅编码和解码自定义类型。
但是,如果你把你的类型Codable
/Encodable
,你可以完全停用你的toJSON
方法。无需再编写代码来对 JSON 进行编码。
如果你在将项目从 Objective-C 转换为 Swift 时正在寻找更具战术性的编辑,你可以定义你自己的协议,比如JsonRepresentable
,它有一个单一的方法要求,你的toJSON
(或者你在转换过程中重命名了这种方法的任何内容(。
protocol JsonRepresentable {
func toJSON() -> Data
}
然后,对于已实现此方法的所有类型,只需添加此一致性。
理想情况下,返回到这些单独的文件并将方法移动到该协议的扩展名中,例如,对于您的第一个对象类型:
extension RequestObject1: JsonRepresentable {
func toJSON() -> Data {
...
}
}
对于你的第二个:
extension RequestObject2: JsonRepresentable {
func toJSON() -> Data {
...
}
}
等。
没有更简单的方法而不是在整个项目中更改它
我建议以上是最好的,但是,如果您不想回到所有这些单独的类型声明,您可以在定义JsonRepresentable
的位置添加带有空扩展名的一致性:
extension RequestObject1: JsonRepresentable { }
extension RequestObject2: JsonRepresentable { }
只要这些类型实现了该方法,这些扩展就会让编译器知道它们是否符合你的协议。
无论如何,此方法可以使用此协议:
func save(_ request: JsonRepresentable, requestId: Int) {
let requestData = ...
requestData.data = request.toJSON()
requestData.requestId = requestId
requestData.timestamp = Date()
save()
}