Отправка данных между классами в Какао Цель C - PullRequest
5 голосов
/ 18 ноября 2010

Я начал программировать для iPhone около месяца назад и нашел сайт очень полезным.Поэтому я думаю, что кто-то может мне помочь.

Я думаю, что понимаю основы работы @property и @synthesise и использования сеттеров и геттеров, но у меня есть проблема.

Скажите, яесть 3 класса: Функции, Class1 и Class2.

Функции - это класс, который содержит все данные, а Class1 и Class2 считывают эти данные из него и записывают в них новые данные (изменяют данные).Однако и Class1, и Class2 создадут собственный экземпляр функций, так как это всего лишь план для данных.

Таким образом, если Class1 записывает или «устанавливает» некоторые данные (скажем, 5) в функции, а Class2 «получает» их, Class2 вернет 0, поскольку Class1 записал только 5 в свой экземпляр функций, что Class2 может «не вижу.

Полагаю, в первую очередь, так?Во-вторых, как мне это сделать, чтобы Class1 и Class2 могли видеть одни и те же данные для получения и установки.

Спасибо за помощь.Я понимаю, что это может включать тему, которую я еще не изучил, но если это так, я бы хотел знать, что это такое, поэтому я могу выучить это.

Ответы [ 4 ]

6 голосов
/ 18 ноября 2010

У вас есть несколько опций, которые сводятся к тому, чтобы Class1 и Class2 использовали один и тот же экземпляр «общего объекта».

  1. Явно передавайте один и тот же экземпляр Class1 и Class2 извневместо того, чтобы позволить Class1 и Class2 самим создавать экземпляр;или
  2. Предоставьте одноэлементный инициализатор для класса Functions, затем убедитесь, что Class1 и Class2 используют это;или
  3. Используйте шаблон проектирования, известный как шаблон реестра, и убедитесь, что Class1 и Class2 получают свои экземпляры класса функций из реестра;или
  4. Использовать внедрение зависимостей (сложное).

Сценарий (1) проще всего понять, поскольку он выглядит именно так:

Functions *funcs = [[Functions alloc] init];

Class1 *obj1 = [[Class1 alloc] initWithFunctions:funcs];
Class2 *obj2 = [[Class2 alloc] initWithFunctions:funcs];
/* or alternatively use setters after initialization */

Сценарий (2) является следующим самым простым и очень распространенным.Какао предоставляет одноэлементные инициализаторы для многих своих классов.Всякий раз, когда вы видите +shared... в качестве префикса для инициализатора, он, вероятно, возвращает синглтон.

@implementation Functions

+(id)sharedFunctions {
  static Functions *sharedFunctions = nil;

  @synchronized(self) {
    if (sharedFunctions == nil) {
      sharedFunctions = [[self alloc] init];
    }

    return sharedFunctions;
  }
}

@end

Статическая переменная инициализируется только один раз, что означает, что вы можете лениво загрузить в нее экземпляр объекта, используяпроверьте его начальное значение (что происходит только один раз).Каждый последующий вызов метода возвращает один и тот же экземпляр.

Functions *f1 = [Functions sharedFunctions];
Functions *f2 = [Functions sharedFunctions];

/* f1 == f2; */ // always

Опция (3) не очень хорошо видна в target-C по сравнению с другими языками и достигает тех же целей, что и singleton.Идея в том, что у вас есть словарь объектов, которые можно искать по ключу.Все, что требует доступа к элементам в реестре, просто запрашивает у реестра собственный экземпляр.Обычно сам реестр представляет собой одноэлементный.

Опция (4), внедрение зависимостей, на самом деле является очень элегантным решением с рядом преимуществ за счет дополнительной сложности.Преимущества заключаются в том, что вы гарантировали, что зависимости всегда слабо связаны (что делает замену реализаций и независимое тестирование зависимостей гораздо проще).Сложность проистекает из нестандартных механизмов получения нужных вам экземпляров.

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

В простейшем случаеВнедрение зависимостей - именно то, что я продемонстрировал в варианте (1).Вам даже не нужен контейнер для внедрения зависимостей.

Повышая уровень сложности, внедрение зависимостей вводит концепцию DI-контейнера, который инкапсулирует ряд существующих шаблонов проектирования (реестрКак видно в варианте (3), синглтон (вероятно, но не строго) и фабрика (чтобы знать, как создавать новые экземпляры объектов, которыми он управляет).

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

DIContainer *container = [DIContainer sharedContainer];

[container registerClass:[ClassA class]];
[container registerClass:[ClassB class]];
[container registerDependentProperty:@selector(setClassA:)
                      withInstanceOf:[ClassA class]
                            forClass:[ClassB class]];

ClassB *obj = [container makeInstanceOfClass:[ClassB class]];
NSLog(@"ClassB's -classA type = %@", [[obj classA] class]);

Я просто набрал это в верхней части головы в середине этогоpost, так что не думайте, что он на 100% точен, но вы поняли концепцию. Контейнеру было поручено, что, когда он инициализирует экземпляры ClassB, он должен затем вызвать -setClassA:, используя экземпляр ClassA, который онтакже инициализируется в соответствии с правилами, определенными в контейнере (в этом случае нет никаких зависимостей ClassA так что он просто возвращает простой экземпляр.

Если вы больше ничего не забираете из этого ответа, просто запомните опции (1) и (2);)

1 голос
/ 18 ноября 2010

Вам необходимо прочитать Руководство по основам какао.Раздел, относящийся к вашему вопросу, называется Общение с объектами .

0 голосов
/ 18 ноября 2010

Есть много онлайн-ссылок, но я нашел эту книгу очень полезной. Программирование в Objective-C 2.0 (2-е изд.). Автор Stephen G. Kochan. Это отличная отправная точка.

0 голосов
/ 18 ноября 2010

Это действительно больше вопрос об объектно-ориентированном программировании в целом, но решение относится и к Objective-C.То, что вы хотите сделать, это создать один экземпляр функций.Этот экземпляр должен совместно использоваться экземплярами Class1 и Class2.

Functions *f = [[Functions alloc] init];
Class1 *c1 = [[Class1 alloc] init];
Class2 *c2 = [[Class2 alloc] init];
// set the value of a instance variable of f to the value of aValue from c1
[f setSomeValue:[c1 aValue]];
// now change it to c2's aValue
[f setSomeValue:[c2 aValue]];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...