Arhn - архитектура программирования

Как изменить делегата в подклассе? Цель С

В настоящее время я ищу способы улучшить свой код. Приложение общается с сервером и получает несколько типов информации: массивы людей, массивы временных меток и т. д. Когда я начал писать код, который взаимодействует с сервером, я создал базовый класс WebService, который настраивает AFNetworking (URL, менеджер и т. д.) и имеет делегат, вызываемый в блоках.

Каждый раз, когда мне нужен был новый сервис, я создавал новый класс, наследуемый от этого класса. Каждый класс объявляет свой собственный протокол для делегата для получения данных. Около 90% методов протокола в этих классах помечены как обязательные, потому что я хочу убедиться, что делегат может получать данные.

На данный момент я занимаюсь рефакторингом кода и заметил, что около половины моих протоколов делегатов требуют «успешного» метода и «неудачного» метода. Я решил, что все функции, которым просто нужны эти два метода, должны быть реализованы в родительском классе, чтобы иметь меньше протоколов для соответствия в моих контроллерах представления. Я начал процесс, но когда я меняю объявление своего делегата с id delegate на id<WebServiceDelegate> delegate, все дочерние классы ожидают, что их делегат будет соответствовать протоколу WebServiceDelegate, и я получаю ошибки компиляции.

Моя цель состоит в том, чтобы иметь дочерние классы только для соединений, которым НЕ нужен метод успеха и неудачи, поэтому я не хочу просто расширять протокол. Наследование от NSObject вместо WebService также кажется расточительным, поскольку мне приходится снова настраивать AFNetworking во всех них (повторяющийся код).

На данный момент я не заставляю делегата соответствовать какому-либо протоколу, но я хотел бы обеспечить это. Мое единственное разумное решение — добавить еще одного делегата в дочерние классы, который соответствует только протоколу дочернего класса, но я чувствую, что должен быть лучший.

Таким образом, мой вопрос: как мне заставить делегата дочернего класса соответствовать новому протоколу вместо родительского протокола?

Пример текущего кода:

// Parent Class
@interface WebService : NSObject 

@property (weak) id delegate;

// Child Class 
//   there's a few child class protocols that just implement this 2 methods
@protocol UploadServiceDelegate <NSObject>

@required
- (void) uploadServiceSuccess;
- (void) uploadServiceFailure;
@end

@interface UploadService : WebService

// Here is a more complicated protocol
@protocol ScheduleServiceDelegate <NSObject>

@required
- (void) scheduleServiceSuccess;
- (void) scheduleServiceFailure;

@optional
- (void) receiveSchedule: (NSArray*)schedules;
- (void) receiveURLForCertificate: (NSURL*) certURL;
@end

Пример идеального кода, в этом случае все объявления протоколов *Success и *Failure больше не нужны, поскольку методы, которые их вызывают, будут реализованы в родительском классе:

@protocol WebServiceDelegate <NSObject>

@required
- (void) WebServiceSuccess;
- (void) WebServiceFailure;
@end

@interface DGWebService : NSObject 

@property (weak) id<WebServiceDelegate> delegate;

Таким образом, другие протоколы будут объявлять только те методы, которые необходимы, и делать их @required вместо необязательных. Это тот момент, когда я думаю, что мне нужно новое объявление свойства делегата:

@protocol ScheduleServiceDelegate <NSObject>

@required
- (void) receiveSchedule: (NSArray*)schedules;
- (void) receiveURLForCertificate: (NSURL*) certURL;
@end

// Delegate at this point:
@property (weak) id<WebServiceDelegate> delegate;
// Delegate I need:
@property (weak) id<ScheduleServiceDelegate> delegate;

  • Я смущен вашим объяснением, но это звучит как очень разумная проблема. Можете ли вы опубликовать код, чтобы показать пример? 05.12.2014
  • @AdamPro13 AdamPro13 Я добавил пример кода. 05.12.2014

Ответы:


1

Вы можете заставить delegate соответствовать обоим протоколам следующим образом:

@property (weak) id<ScheduleServiceDelegate, WebServiceDelegate> delegate;

или вы можете включить ScheduleServiceDelegate методы, определенные в WebServiceDelegate, определив его следующим образом:

@protocol ScheduleServiceDelegate <NSObject, WebServiceDelegate>

Затем вы можете переопределить делегата в подклассе, просто

@property (weak) id<ScheduleServiceDelegate> delegate;

Оба эти способа должны давать желаемые результаты, если только я не понял ваш вопрос ужасно неправильно.

04.12.2014
  • Первый вариант был моей первой мыслью, но у меня было бы много пустых объявлений, потому что *Success и *Failure никогда не вызывались бы. Второй снова оставляет меня с пустыми объявлениями, за исключением класса обслуживания вместо контроллера представления. Я не понимаю третьего, можете ли вы просто переопределить такое свойство? 05.12.2014
  • @gamda хм, так что плохого в том, чтобы сохранить все, что у вас есть, но переопределить делегата в подклассе как id<ScheduleServiceDelegate>? Таким образом, делегату нужно только соответствовать ScheduleServiceDelegate, чего вы и хотите? 05.12.2014
  • Это именно то, что я хочу! Я просто не представлял себе, что переопределение свойства может быть таким простым. Подводя итог, @property (weak) id<ScheduleServiceDelegate> delegate; в моем дочернем классе даст такое поведение? 05.12.2014
  • @gamda Да, переопределение означает, что тот, что в подклассе, полностью заменяет тот, что в суперклассе. Хотя в этом случае это кажется немного странным, но пока вы держите его в безопасности с проверками respondsToSelector, все должно быть в порядке! 05.12.2014
  • Я пытался переопределить, но получаю следующее предупреждение: Property type 'id'<OtherDelegate> is incompatible with the type 'id<WebServiceDelegate>' inherited from 'WebService' Я предполагаю, что с предупреждениями все в порядке, но я бы предпочел их избегать. 05.12.2014
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..