#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];
}