Невозможно передать NSString между ViewControllers, в то время как другие объекты могут

#iphone #objective-c #ios #xcode

#iPhone #objective-c #iOS #xcode

Вопрос:

У меня есть два контроллера просмотра, которые один передает другому массив объектов, как и ожидалось. Однако, когда я пытаюсь передать строку, каким-то образом что-то происходит, потому что на другом ViewController она всегда возвращается как (null). Чего-то здесь не хватает?

ViewController one.h

 @class ViewControllerTwo;

@interface ViewControllerOne : UIViewController{

    ViewControllerTwo* playboard;

@property(nonatomic, retain) ViewControllerTwo* playBoard;

@end
  

ViewController One

 playBoard = [[ViewControllerTwo alloc] init];    
        [playBoard setQuickPlayFilters:[[NSMutableArray alloc] init]];
        [playboard setChallenge:[[NSString alloc] init]];


passToPlayboard = [[NSString alloc] initWithString:@"one"];                    
                    filters = [[NSMutableArray alloc] initWithObjects:
                               [NSNumber numberWithInt:5],
                               [NSNumber numberWithInt:1],
                               [NSNumber numberWithInt:1],
                               [NSNumber numberWithInt:2],
                               [NSNumber numberWithInt:9],
                               [NSNumber numberWithInt:0],
                               [NSNumber numberWithInt:0],
                               [NSNumber numberWithInt:8], nil];

  [playBoard setQuickPlayFilters:[filters mutableCopy]];
      [playboard setChallenge:[NSString stringWithString:passToPlayboard]];

Touch_TestingAppDelegate* appDelegate = [[UIApplication sharedApplication] delegate];
      [appDelegate.navController pushViewController:playBoard animated:YES];
  

ViewController Two.h

 #import <UIKit/UIKit.h>

@interface ViewControllerTwo : UIViewController {
    NSString* challenge;
NSMutableArray* quickPlayFilters;
}

@property(nonatomic, retain) NSString* challenge;
@property(nonatomic, retain) NSMutableArray* quickPlayFilters;

@end
  

ViewController Two.m

 - (void)viewDidLoad{
    [super viewDidLoad];

    cover = [[CoverView alloc] initWithFrame:CGRectMake(140.0f, 80.0f, 620.0f, 610.0f) andRemaningTiles:[quickPlayFilters lastObject]];
    cover.backgroundColor = [UIColor clearColor];
    [self.view addSubview:cover];

    NSLog(@"Quick Play : %@", quickPlayFilters);
    NSLog(@"Challenge from Load : %@", challenge);


    [[self cover] setFilters:[quickPlayFilters mutableCopy]];

    timerDisplay = [[TimerDisplay alloc] 
                    initWithFrame:CGRectMake(813.f, 120.f, 181.f, 162.f) 
                    andTimeCycle:[quickPlayFilters objectAtIndex:0] 
                    andNumberOfRows:[quickPlayFilters objectAtIndex:6]]; 
}
  

И когда я ищу quickPlayFilters в playBoard , я могу найти их сразу. Однако я не могу вернуть ничего, кроме null для challenge строки. Пожалуйста, помогите.

Комментарии:

1. Можем ли мы увидеть реализацию .h для ViewControllerOne?

2. И ваша реализация setChallenge:

3. @FelipeCypriano это то, что вы искали?

4. Действительно, это так, и смотрите ответ @ XJones ниже; он довольно красиво подводит итог.

Ответ №1:

Основная проблема заключается в опечатке в ViewControllerTwo.h . playboard iVar написан строчными буквами, но свойство находится в camelcase ( playBoard ). Это приводит к тому, что ваш класс имеет два IVAR ( playboard и playBoard ). Исправьте опечатку, чтобы все было playBoard и это сработало.

Мой первоначальный ответ ниже оставлен для справки, поскольку я все еще рекомендую вам очистить свой код, как я рекомендовал. Я пересмотрел код для использования playBoard во всех экземплярах.

= ОРИГИНАЛЬНЫЙ ОТВЕТ

На это невозможно ответить наверняка, не видя ваш код в ViewControllerTwo.m . Убедитесь, что свойство для challenge определено как:

 @property (nonatomic, copy)  NSString * challenge;
  

Если у вас есть пользовательский установщик, убедитесь, что он выполняет правильное назначение ala:

 - (void)setChallenge:(NSString *)newChallenge
{
    if (![challenge isEqualToString:newChallenge]) {
        challenge = [newChallenge copy];
        // whatever else you need to do
    }
}
  

Вы создаете кучу объектов, которые вам на самом деле не нужны. Приведенный выше код может быть:

 playBoard = [[ViewControllerOne alloc] init];    
passToPlayBoard = [[NSString alloc] initWithString:@"one"];
filters = [[NSMutableArray alloc] initWithObjects:
    [NSNumber numberWithInt:5],
    [NSNumber numberWithInt:1],
    [NSNumber numberWithInt:1],
    [NSNumber numberWithInt:2],
    [NSNumber numberWithInt:9],
    [NSNumber numberWithInt:0],
    [NSNumber numberWithInt:0],
    [NSNumber numberWithInt:8], nil];

[playBoard setQuickPlayFilters:filters];
[playBoard setChallenge:passToPlayBoard];

Touch_TestingAppDelegate* appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.navController pushViewController:playBoard animated:YES];
  

ПРИМЕЧАНИЕ: мой приведенный выше код предполагает, что ваш проект использует ARC. Если нет, вам придется соответствующим образом освободить объекты.

РЕДАКТИРОВАТЬ: найдена актуальная проблема. добавлено в начало этого ответа.

Комментарии:

1. В чем разница между этими двумя строками? passToPlayboard = [[NSString alloc] initWithString:@»one»]; passToPlayboard = @»one»;

2. В зависимости от того, используете ли вы ARC или нет, первый выделяет (и никогда не выпускает) NSString. Это вызовет утечку памяти. Второй вариант хорош для обоих, поскольку система справится с его освобождением.

3. это верно в отношении того, что делает ARC, но это не разница. Компилятор оптимизирует прямые ссылки на строку (например, @"one") so they will all be the same object. Using initWithString` вызывает создание нового объекта. Как правило, это спорный вопрос, и можно использовать строку напрямую. В конечном итоге вы замените все это, если / когда перейдете к локализации.

4. Я попытался настроить свой код, по-прежнему безуспешно. Что меня больше всего смущает, так это то, что filters передается без проблем, но challenge, похоже, не хочет уходить. Также я не использую пользовательский установщик… должен ли я быть?

5. нет, вам не нужен пользовательский установщик. post ViewControllerTwo.h и init методы viewDid... ViewControllerTwo.m и, из,,.

Ответ №2:

В методе setChallenge, пожалуйста, сохраните значение вашего объекта ..like.

  • (void)setChallenge:(NSString *)newChallenge {

     challenge = [newChallenge retain];
      

    }