проблемы с общими функциями при преобразовании кода из цели c в swift - PullRequest
2 голосов
/ 07 октября 2019

В настоящее время я работаю над задачей преобразования кода из цели c в swift. Работа шла гладко до тех пор, пока у меня не появилось общего кода с возможностью повторного использования, который работает в задаче c, но я не представляю, как мне это сделать в быстром темпе.

Сценарий, работающий в задаче 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.

Так как эта функция является общим другим запросомобъекты будут приходить с разных контроллеров. Я понятия не имею, как мне идти дальше от слышать, Если у кого-то есть идеи, пожалуйста, помогите мне

Ответы [ 2 ]

0 голосов
/ 07 октября 2019

Существует существующий протокол 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()
}
0 голосов
/ 07 октября 2019

Ваш класс должен быть похож на

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()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...