#ios #objective-c #uiviewcontroller #nsarray
#iOS #objective-c #uiviewcontroller #nsarray
Вопрос:
У меня довольно большой NSArray
, который я должен использовать в нескольких контроллерах представления. Я получаю данные с сервера и не хочу загружать их всегда, когда пользователь открывает новое представление.
Итак, как я могу определить его как «глобальную переменную»?
Я могу сделать это с помощью переходов, но без них это не работает. Я пытался объявить массив, вызываемый dataToDestinationView
в DestinationViewController
, затем импортировал его в представление, где self.arrayToExport
находится, и добавил строки выше, но это не сработало. Я что-то пропустил?
DestinationViewController *dataToNew = [DestinationViewController alloc]init];
dataToNew.dataToDestinationView = self.arrayToExport;
ОБНОВЛЕНО с моей попыткой в AppDelegate:
AppDelegate.h
@property (nonatomic, strong) PNChannel *myChannel;
AppDelegate.m
[PubNub requestHistoryForChannel:self.myChannel from:nil to:nil limit:100 reverseHistory:NO withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
(NSArray *)mySharedArray
{
static NSArray *sharedArray = nil;
if (sharedArray)
return sharedArray;
sharedArray = contentArray;
return sharedArray;
}
}];
В этом случае я получаю две ошибки: Use of undeclared identifier 'self'
и Expected identifier or '('
. Я этого не понимаю, потому что self.myChannel объявлен в файле .h, и я использую тот же блок в другом месте без проблем с идентификатором.
ВТОРОЕ ОБНОВЛЕНИЕ
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// [self.window makeKeyAndVisible];
[PubNub setDelegate:self];
PFUser *currentChannel = [PFUser currentUser];
self.myChannel = [PNChannel channelWithName:currentChannel.username
shouldObservePresence:YES];
}
- (void)getMessage {
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
(NSArray *)mySharedArray
{
static NSArray *sharedArray = nil;
if (sharedArray)
return sharedArray;
sharedArray = contentArray;
return sharedArray;
}
NSLog(@"mokus katona %@", contactArray);
}];
}
Комментарии:
1. Взгляните на синглеты: developer.apple.com/library/ios/documentation/general /…
2. «Глобальная переменная» — это просто переменная, к которой можно обращаться из большинства мест в вашей программе. Для NSArray это означает, что вы должны каким-то образом сделать указатель на NSArray доступным для каждого из ваших контроллеров представления, которым необходимо ссылаться на него. Один из способов сделать это — предоставить каждому контроллеру представления свойство, которое его создатель устанавливает с адресом массива. Другой способ — поместить указатель в ваш AppDelegate и получить доступ к этому указателю, когда это необходимо. Другой способ — использовать «одноэлементный». Все дело в том, чтобы каким-то образом сделать адрес доступным.
3. Синглтоны используются чрезмерно и злоупотребляются. Насколько я понимаю, я редко нахожу примеры, когда они действительно необходимы. Почему бы вам не посмотреть, может ли статический класс соответствовать вашим потребностям? Если все, что вам нужно, это доступ к дате, то одноэлементный элемент является излишним.
4. @Literphor существует множество очень хороших применений для одиночек, но я согласен, что это не одно из них.
Ответ №1:
Внутри вашего делегата приложения объявите статическую переменную и метод для ее чтения:
static NSArray *_message = nil;
@implementation AppDelegate
(NSArray *)message
{
if (_message)
return _message;
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate getMessage];
return nil;
}
- (void)getMessage {
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
NSLog(@"mokus katona %@", contactArray);
_message = contactArray;
}];
}
@end
Комментарии:
1. Могу ли я поместить это в блок? Потому что я извлекаю данные с помощью блочного метода.
2. Я не смог реализовать блок внутри делегата приложения, он не распознал переменные экземпляра, которые я объявил в
AppDelegate.h
. Возможно ли сделать то же самое в контроллере представления вместо делегата приложения? Я пытался скопировать ваш код в свой контроллер и изменить значениеMyAppDelegate
toMyViewController
, но это не работает.3. @vv88 пожалуйста, отредактируйте свой вопрос, чтобы включить код, который вы пытались использовать, который не работает? Я покажу вам, что вы сделали неправильно. Это определенно возможно и легко сделать то, что вы пытаетесь сделать.
4. @vv88 да, это потребует некоторых изменений, но не могли бы вы опубликовать больше кода? Например, в каком методе находится этот код?
5.
self.exampleArray = [AppDelegate message]
прочитает его из другого представления.
Ответ №2:
Возможно, это может вам помочь.
В вашем pch-файле (#project-Prefix.pch) вы можете создать свою глобальную переменную, доступную из всех пробелов. Посмотрите ниже
#ifdef __OBJC__
NSArray *myArray;
#endif
и в вашем делегате приложения, в вашем - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
, вы можете заполнить свой массив данными сервера следующим образом
[PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {
NSLog(@"mokus katona %@", contactArray);
myArray = contactArray;
}];
Теперь это только однократная загрузка, и myArray
она будет доступна во всех контроллерах, моделях, представлениях и т.д.
Дайте мне знать, если это поможет.
Комментарии:
1. Кажется, это работает. Я много читал об этой теме в последние дни, но не видел такого решения. Как вы думаете, есть ли у него какие-либо недостатки? Когда я вызываю myArray в случайном контроллере представления (а затем он получает новые данные в фоновом режиме), он будет обновляться при перезагрузке текущего представления?
2. Теперь я протестировал его еще немного, и проблема в том, что он хранит первое значение массива и не обновляется, когда клиент получает новое сообщение. Я перезагрузил представление 5 раз за одну секунду, и массив остался прежним.
3. Волшебным образом ничего не происходит. Зависит от того, как вы его перезагружаете. Вы программировали раньше?
4. Я только что перезагрузил контроллер представления, в котором использовался массив. Что бы вы порекомендовали для этого?
5. Что вы подразумеваете под перезагрузкой контроллера представления? Вы устанавливаете свои значения или изображения в своем
viewDidLoad
?