2015-04-22 3 views
0

Я создаю приложение для iOS в Swift, и я пытаюсь сохранить логику API API за пределами моих ViewControllers. Я последовал за this tutorial за 1 вызов API, о котором я расскажу ниже.Реализация нескольких вызовов API (запросы сервера) с использованием протоколов

Я создаю протокол «APIControllerProtocol», который будет реализовывать ViewController, а затем я создаю класс APIController, который будет содержать свойство «делегат» для хранения экземпляра типа APIControllerProtocol. Протокол просто определяется как

protocol APIControllerProtocol { 
    func didReceiveAPIResults(result: SwiftyJSON.JSON) 
} 

И ViewController будет осуществлять didReceiveAPIResults функцию, которая будет вызвана после вызова API возвращает данные в формате JSON. ViewController будет содержать экземпляр APIController, а также вызвать функцию, которая вызывает вызов API.

На данный момент я хочу, чтобы больше ViewControllers выполняло вызовы API, и если мне нужно всего лишь сделать 1 вызов API на ViewController, я могу просто добавить еще одну функцию в APIController, и я могу использовать новый ViewController тот же протокол , Однако эта логика ошибочна, если есть ViewController, что нужно будет сделать 2 или более API вызовов, потому что

  1. Я не могу назвать didReceiveAPIResults в ViewController 2 различными способами,
  2. Я не думаю, добавление нескольких свойств «делегата» в класс APIController для хранения различных типов протоколов - путь.

  3. Определение нескольких функций в протоколе означало бы, что я должен был бы реализовать все эти функции в ViewControllers, которые должны выполнять только 1 вызов API.

Мои идеи для решения этой проблемы являются

  1. сделать класс APIController и APIControllerProtocol для каждого ViewController

  2. использования дополнительных функций в APIControllerProtocol так не каждый ViewController бы реализовать все (я не знаю, как это действительно работает)

Любые другие идеи будут оценены.

ответ

0

Ваше использование термина «API» запутанно. Это похоже на то, что вы имеете в виду серверный запрос, так что я его и буду называть.

Я бы предложил использовать конструкцию блока блокировки/закрытия, а не на основе протокола.

Сделайте свои вызовы классу сетевого запроса, завершите закрытие и вызовите это завершение закрытия после завершения запроса сервера.

Вы можете написать класс сетевого запроса, чтобы поддерживать список запросов и закрытие завершения для каждого ожидающего запроса и вызывать закрытие каждого запроса после его завершения или сбоя.

+0

Да, вызов API здесь означает запрос сервера. Какая польза от конструкции закрытия над дизайном протокола? Я не понимаю, что важно поддерживать список запросов? Не могли бы вы предоставить код или ссылку на учебник, чтобы показать мне, как закрытие будет использоваться для запросов сервера? – hoffware

+0

Похоже, вы хотите иметь класс, который управляет несколькими запросами сервера. Делегаты - это отношения «один к одному». Каждый объект диспетчера сервера может иметь только один и только один делегат. Таким образом, вы не можете обрабатывать ожидающие запросы от 3 разных контроллеров. С блоками завершения вы можете. –

+0

Вместо того, чтобы изобретать колесо, вы можете взглянуть на такие библиотеки, как AFNetworking. Этот, в частности, очень богатый и зрелый, с множеством отличных функций, и тысячи разработчиков используют его. Он делает то, что мы говорим очень хорошо. –

0

Определение нескольких функций в протоколе будет означать, я бы реализовать все эти функции в ViewControllers, что нужно только сделать вызов 1 API.

Это неверное описание. Создайте дополнительные функции, и вы, вероятно, получите ответ.

@objc protocol APIControllerProtocol { 
    func didReceiveAPIResults(result: SwiftyJSON.JSON) 
    optional func someAwesomeMethod() 
} 

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

Дополнительные требования протокола

Вы можете определить дополнительные требования к протоколам Эти требования не должны быть реализованы по типам, которые соответствуют протоколу. Необязательные требования предваряются дополнительным модификатором как часть определения .

Дополнительное требование к протоколу может быть вызвано с необязательной цепочкой, , чтобы учесть, что требование не было , реализованное по типу, соответствующему протоколу. Для получения информации о дополнительной цепочке см. Дополнительное соединение.

Вы проверяете для реализации факультативного требования в письменной форме знак вопроса после имени требования, когда его называют, , такие как someOptionalMethod? (SomeArgument). Необязательное свойство требований и необязательные требования к методам, которые возвращают значение, всегда будет возвращать необязательное значение соответствующего типа, когда к ним обращаются или вызывают , чтобы отразить тот факт, что необязательное требование может быть не реализовано.

+0

я получаю ошибку «„необязательно“может быть только применяется к членам протокола '@ objc', который, я думаю, означает, что мне нужно выполнить' @objc-протокол APIControllerProtocol'. Однако, проверяя исходный код для UITableViewDelegate, который использует дополнительные функции, я замечаю, что он не имеет тега '@ objc'. Нужно ли добавлять тег '@ objc'? – hoffware

+0

Это обсуждается в документе, который я опубликовал. @objc protocol APIControllerProtocol –

+0

Когда я добавляю '@ objc' к протоколу, я получаю еще одну ошибку.« Метод не может быть помечен '@ obc', потому что тип aprameter не может быть представлен в Objective-C». Я мог бы вернуть другое представление JSON или разобрать JSON перед вызовом делегата, есть ли другие варианты? – hoffware

0

Учебник, в котором вы основываете свою логику, не выглядит нормально для меня. Что он делает, он реализует стандартный шаблон делегирования, усиленный до макс. DetailsViewController имеет экземпляр APIViewController, которому он присваивает себя как делегат - довольно стандартный. Но затем DetailsViewController вызывает методы на этом экземпляре APIViewController, чтобы получить запущенные методы делегатов, которые реализованы в DetailsViewController. Это слишком круто для моего вкуса.

Более разумным шаблоном было бы создание объекта singleton (shared instance), который обрабатывал бы ваши вызовы API, и любой контроллер вида мог бы получить к нему доступ. Там вы можете реализовать свои методы, которые принимают ваши параметры, одним из которых является закрытие, которое можно было бы вызвать, когда ваш запрос завершит передачу результата в контроллер вида.

Так что в вашем контроллере представления вы назвали бы что-то вроде этого:

APIController.sharedInstance.doSomethingWith(someParameter, completion: { (result) -> Void in 
    // Do something with the result 
}) 

Вашего APIController бы реализовать это что-то вроде этого

func doSomethingWith(param: String, completion: (AnyObject) -> Void) { 
    // do your data fetching here... 
    // pass the result to the closure when the data is retrieved 
    completion(result) 
} 
Смежные вопросы