Доступ к NSArray из каждого контроллера представления

#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 to MyViewController , но это не работает.

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 ?