Я создал NSMutableArray в реализации моего класса loginController. Изменчивый массив содержит набор строк. Я хочу передать измененный массив с его объектами в другие классы в моем проекте какао. Каков наилучший способ передать массив?Передача NSMutableArray в другие классы
ответ
Самый простой случай - ваш контроллер входа, просто передающий моментальный снимок массива другому контроллеру. В этом случае ваш контроллер входа должен иметь ссылки на экземпляры других классов, и он установит некоторое свойство этих экземпляров в массив. Не забудьте объявить свойства с атрибутом copy
, чтобы получатели не удержались в вашем частном изменяемом массиве.
Если вы хотите, чтобы другие контроллеры могли модифицировать массив, не нужно, пусть они имеют ваш изменяемый массив - это приглашение к труднодоступным ошибкам.
Вместо этого вам нужно будет реализовать одно свойство в контроллере входа, а не одно свойство на каждом из других контроллеров. Свойство контроллера входа должно иметь по крайней мере геттер и сеттер (который вы можете @synthesize
), но вы можете реализовать more specific accessor methods для эффективности.
Как только у вас есть это свойство, другие контроллеры должны получить доступ к свойству с помощью KVO-совместимого способа. Если вы реализуете специальные устройства доступа, они могут просто использовать их. В противном случае им нужно будет отправить mutableArrayValueForKey:
в контроллер входа. Когда они получают доступ к содержимому этого прокси-массива, они действительно получают доступ к массиву контроллера входа; когда они мутируют массив прокси, они, в свою очередь, мутируют массив логического контроллера.
Далее идет фактическая часть KVO. Вы хотите, чтобы другие контроллеры знали, когда один из них (или контроллер входа) изменяет свойство. Пусть каждый контроллер (кроме контроллера входа) добавляет себя в качестве наблюдателя свойства контроллера входа. Не забудьте удалить их в своих методах -dealloc
(или -finalize
).
Для получения правильных уведомлений для публикации необходимо использовать либо аксессоры, либо mutableArrayValueForKey:
. Это также относится к самому контроллеру входа - он должен использовать свои собственные аксессоры при мутировании массива, а не напрямую передавать массив. Исключение составляют только init
и dealloc
(потому что сообщения о доступе были бы сообщением с половинным ed/dealloc
ked-объектом, что будет проблемой, если вы когда-либо сделаете аксессуаров фантастическими *).
Кстати, похоже, что у вас может быть слишком много контроллеров. Посмотрите, не можете ли вы переместить часть своей логики в объекты модели. Это значительно упрощает ваш код, поскольку Cocoa предназначен для работы с модельным слоем. Тяжелость контроллера - это борьба с каркасом, что делает больше работы для вас.
* Под «фантазией» я имею в виду делать что-то другое, кроме или в дополнение к нормальному поведению данного метода доступа. Например, insertObject:in<Foo>AtIndex:
обычно только хвостовые звонки [<foo> insertObject:atIndex:]
; если вы вставляете или храните объект где-то иначе, чем в массиве в переменной экземпляра, или если вы делаете что-то еще в одном и том же методе (например, сообщать представление, которое оно должно отображать), тогда ваш метод доступа является причудливым.
короткий ответ, что не может быть лучшей практикой:
[otherObject giveArray:[NSArray arrayWithArray:theMutableArray]];
вопрос является хорошим, но не полный ... не нужно просто передать массив строк или делает класс вы переход к необходимости изменения массива?
В общем, это не проблема просто передать NSMutableArray *, однако вам нужно быть осторожным, потому что вы просто передаете указатель (поэтому, если вы его где-то сохраняете, вам нужно знать, что владелец или другой класс может изменить массив). обычно говорил, что вы хотели бы использовать NSMutableArray для динамического создания массива объектов, а когда вам нужно их разделить, сделайте неперемещаемую копию и передайте это.
NSMutableArray* myArr = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"four",nil];
// maybe modify the array here...
NSArray* nonMut = [[myArr copy] autorelease];
[someObject doWork:nonMut];
| K <
Я думаю, что модель, которая лучше для вашей ситуации является делегирование. Ваш LoginController
не должен знать, к какому классу он отправляет эти данные. Вместо этого, вы можете реализовать протокол LoginControllerDelegate
@protocol LoginControllerDelegate <NSObject>
@optional
- (void)loginController:(LoginController *)loginController didReceiveLoginIDs:(NSArray *)ids;
@end
Тогда в вашем LoginController
классе вы бы реализовать delegate
свойство как это:
@property (nonatomic, assign) id <LoginControllerDelegate> delegate;
Затем, когда вы на самом деле есть что-то общаться с делегат, вы бы написали:
if ([self.delegate respondsToSelector:@selector(loginController:didReceiveLoginIDs:])
[self.delegate loginController:self didReceiveLoginIDs:[NSArray arrayWithArray:loginIDs]];
Объект, который должен получить идентификаторы входа, будет включать LoginControllerDelegate
протокол, как это:
@interface SomeOtherClass : NSObject <LoginControllerDelegate>
И вы бы реализовать метод loginController:didReceiveIDs:
в SomeOtherClass
.
Таким образом, вместо того, чтобы ваш LoginController
должен иметь глубокое знание других классов в вашем проекте, вы просто устанавливаете механизм для отправки этих данных любому интересующему объекту, когда он становится доступным. Если позже вы измените, какой объект должен получить идентификаторы входа, вам нужно будет выбрать другой делегат.