2012-02-28 1 views
3

Это совершенно непонятно для меня, заставляя меня думать, что я пропустил что-то важное. Но я пытаюсь создать контейнер контроллера представления для управления двумя панелями (аналогично SplitViewController, но с некоторыми существенными отличиями). Я только начал строить класс, так что я получил только 3 Иварс прямо сейчас:Подкласс UIViewController не может назначать переменную экземпляра

@implementation SplitViewController{ 
    BOOL _showLeftPane; 
    UIViewController *_leftController; 
    UIViewController *_rightController; 
} 

Независимо от того, что я делаю, я не могу назначить контроллер представления в _leftController Ивар. В основном, iRAar_rightController может назначаться. Это становится более странным. Если я переключу порядок iVars, то _rightController появится перед _leftController, я не могу назначить ни одного с первой попытки. Однако, если я попробую еще раз (буквально напишу назначение дважды), то возьмет _leftController. Последовательно, когда я использую консоль для запроса значения первого контроллера, указанного в объявлениях iVar сразу после назначения, значение, которое я получаю, равно (UIViewController *) $5 = 0x00000001 [no Objective-C description available]. WTF?

Из любопытства (и потому, что я могу ... Я только начал писать класс) Я сменил супер с UIViewController на NSObject. Когда я это делаю, работа выполняется. И действительно, назначение - это почти все, что сейчас делает этот класс рядом с созданием пустого представления на loadView.

Что мне не хватает?

Update Остальная часть кода:

Весь .h файл:

#import <UIKit/UIKit.h> 

@interface SplitViewController : UIViewController 

@property (strong) UIViewController *leftViewController; 
@property (strong) UIViewController *rightViewController; 
@end 

Весь .m файл (обратите внимание, я пытался синтезировать свойства, такое же поведение, за исключением сложнее отлаживать консоль):

@implementation SplitViewController{ 
    BOOL _showLeftPane; 
    UIViewController *_rightNavController; 
    UIViewController *_leftNavController; 
} 
#pragma mark - Init Methods 
- (id)init{ 
    if (self = [super initWithNibName:nil bundle:nil]){ 
     _showLeftPane = YES; 
    } 
    return self; 
} 
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 

    } 
    return self; 
} 

#pragma mark - Properties 
- (void) setLeftViewController:(UIViewController *)leftViewController{ 
    _leftNavController = leftViewController; 
} 
- (UIViewController *) leftViewController{ 
    return _leftNavController; 
} 
- (void) setRightViewController:(UIViewController *)rightViewController{ 
    _rightNavController = rightViewController; 
} 
- (UIViewController *) rightViewController{ 
    return _rightNavController; 
} 

Первоначально, у меня был весь обычный контроллер просмотра, переопределенный методы (loadView, viewDidLoad и т. д.), но я с тех пор прокомментировал их, пока не смогу устранить эту проблему. Кроме того, я использую ARC.

Update 2 Я попытался создать простой NSObject контейнерный класс, думая, может быть, это было связано с Иварс быть класса UIViewController, что постановку задачи. Но та же проблема сохраняется. Поэтому перенос UIViewController в другую переменную не работает. Я также пытался изменить тип iVar на «id», но проблема сохраняется.

Я также хотел бы отметить, что я очистил проект и использовал статический анализатор clang для проверки логических ошибок.

Update 3 Все задание в этом классе «Выключено» ... часто (но не всегда) назначение следующего Ивар в списке. Я вложил кучу фиктивных идентификаторов iVars и назначил им случайные объекты. Затем я прошел через каждое задание (которое я ставлю в INIT) и протестировал значение до и после присваивания:

if (self = [super initWithNibName:nil bundle:nil]) { 
     _showLeftPane = YES; 
     _dummy1 = [[NSObject alloc] init]; 
     _dummy2 = [[UIView alloc] init]; 
     _dummy3 = [[NSNumber alloc] init]; 
     _dummy4 = [[NSString alloc] init]; 
     _dummy5 = [[NSValue alloc] init]; 
     _dummy6 = [[UIColor alloc] init]; 
     _dummy7 = [[NSCache alloc] init]; 
     _dummy8 = [[UIButton alloc] init]; 
     _dummy9 = [[UIFont alloc] init]; 
     _rightController = [[UIViewController alloc] init]; 
     _leftController = [[UIViewController alloc] init]; 
    } 

Это то, что я получил (а не значения не изменяются после присваивания, но те, которые имеют значения часто относятся к предыдущему назначению). :

(lldb) po _showLeftPane 
(BOOL) $2 = '\0' <nil> 
(lldb) po _showLeftPane 
(BOOL) $4 = '\0' <nil> 
(lldb) po _dummy1 
(id) $6 = 0x00000001 [no Objective-C description available] 
(lldb) po _dummy1 
(id) $8 = 0x00000001 [no Objective-C description available] 
(lldb) po _dummy2 
(id) $9 = 0x0a0461e0 <NSObject: 0xa0461e0> 
(lldb) po _dummy2 
(id) $11 = 0x0a0461e0 <NSObject: 0xa0461e0> 
(lldb) po _dummy3 
(id) $12 = 0x0866f340 <UIView: 0x866f340; frame = (0 0; 0 0); layer = <CALayer: 0xa05a790>> 
(lldb) po _dummy3 
(id) $14 = 0x0866f340 <UIView: 0x866f340; frame = (0 0; 0 0); layer = <CALayer: 0xa05a790>> 
(lldb) po _dummy4 
(id) $15 = 0x00000000 <nil> 
(lldb) po _dummy4 
(id) $17 = 0x00000000 <nil> 
(lldb) po _dummy5 
(id) $18 = 0x017c5a7c <object returned empty description> 
(lldb) po _dummy5 
(id) $20 = 0x017c5a7c <object returned empty description> 
(lldb) po _dummy6 
(id) $21 = 0x00000000 <nil> 
(lldb) po _dummy6 
(id) $23 = 0x00000000 <nil> 
(lldb) po _dummy7 
(id) $24 = 0x0865d300 <UIPlaceholderColor: 0x865d300> 
(lldb) po _dummy7 
(id) $26 = 0x0865d300 <UIPlaceholderColor: 0x865d300> 
(lldb) po _dummy8 
(id) $27 = 0x0a230af0 <NSCache: 0xa230af0> 
(lldb) po _dummy8 
(id) $29 = 0x0a230af0 <NSCache: 0xa230af0> 
(lldb) po _dummy9 
(id) $30 = 0x08637350 <UIButton: 0x8637350; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x8484920>> 
(lldb) po _dummy9 
(id) $32 = 0x08637350 <UIButton: 0x8637350; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x8484920>> 
(lldb) po _rightController 
(UIViewController *) $33 = 0x00000000 <nil> 
(lldb) po _rightController 
(UIViewController *) $35 = 0x00000000 <nil> 
(lldb) po _leftController 
(UIViewController *) $36 = 0x0a065180 <UIViewController: 0xa065180> 
(lldb) po _leftController 
(UIViewController *) $38 = 0x0a065180 <UIViewController: 0xa065180> 

Итак, э-э ... это ошибка? Если да, то каким образом я могу его записать? Я даже не знаю, что происходит.

Update 4 Я получил его на работу, но только на моем устройстве. Обычно я стараюсь сначала выполнить основные изменения на симуляторе (проще/быстрее отлаживать), а затем проверить его на производительность на устройстве. Кроме того, я предпочитаю иметь рабочую версию на своем устройстве, чтобы я мог проверить ее в свое свободное время. Поэтому я установил его на свое устройство, и класс отлично работает. Кажется, что он только сломан в симуляторе. Любые идеи о том, почему это может быть? Я действительно не хочу тестировать остальную часть моей программы на устройстве в одиночку. Это немного замедлит.

+0

Можете ли вы дать нам еще один код. Ваш синтаксис выше кажется прекрасным, поэтому он должен быть чем-то другим. –

+0

Ну, не так уж много кода, чтобы добавить, но я добавлю его через минуту. –

ответ

9

Хорошо, я понял, что проблема. Я использую Xcode 4.3, который должен позволить вам использовать отладчик lldb с iOS (или, как утверждается, Apple). Моя проблема исчезла, когда я сменил отладчик на GDB. Хотя теперь у меня есть полезный отладчик, я понял, что задания действительно работают правильно. Отладчик просто плюнул обратно на неверные данные. Должен любить это.

Мой совет: Не используйте lldb на iOS. Несмотря на то, что Apple говорит, что отладчик lldb можно использовать с iOS, он все еще недостаточно стабилен, чтобы полагаться на него. Итак, прошло 6 часов моей жизни ....

Я подал ошибку с Apple: 10945570

UPDATE

Apple, похоже, закрепилась это в Xcode 4.3.1. По крайней мере, до сих пор LLDB хорошо работает для меня.

UPDATE 2

Нет, фигу, LLDB еще перепутались в тренажере.

UPDATE 3

Насколько я могу сказать, этот вопрос сейчас решается в 4.3.2. Я использую отладчик LLDB сейчас около недели, и у меня не было никаких проблем с этим, давая мне значения мусора.

+1

Хорошо на ya для обеспечения всех последующих действий. – blahdiblah

0

Возможно, по какой-то причине #import <UIKit/UIKit.h> не на ваших предварительно скомпилированных заголовках, попробуйте добавить его там или просто добавьте импорт поверх своего файла.

+0

Хорошая мысль, но нет, она есть. –

2

Этот код не кажется правильным:

@interface SplitViewController : UIViewController 

@property (strong) UIViewController *leftViewController; 
@property (strong) UIViewController *rightViewController; 
@end 

.... 

@implementation SplitViewController{ 
    BOOL _showLeftPane; 
    UIViewController *_rightNavController; 
    UIViewController *_leftNavController; 
} 

Является ли это то, что вам действительно нужно? Потому что я ожидал бы что-то подобное в .h:

@interface SplitViewController : UIViewController 
@property BOOL showLeftPane; 
@property (strong) UIViewController* leftViewController; 
@property (strong) UIViewController* rightViewController; 
@end 

И в ом

@implementation SplitViewController 
@synthesize showLeftPane; 
@synthesize leftViewController; 
@synthesize rightViewController; 
... 
@end 

Или, если вы хотите использовать явную поддержку вары

@interface SplitViewController : UIViewController 
{ 
    BOOL _showLeftPane; 
    UIViewController* _leftViewController; 
    UIViewController* _rightViewController; 
} 

@property BOOL showLeftPane; 
@property (strong) UIViewController* leftViewController; 
@property (strong) UIViewController* rightViewController; 
@end 

.... 

@implementation SplitViewController 
@synthesize showLeftPane = _showLeftPane; 
@synthesize leftViewController = _leftViewController; 
@synthesize rightViewController = _rightViewController; 
... 
@end 

из как вы смешиваете концепции между @interface и @implementation

В соответствии с Вашим комментарием, если вы хотите частных ВАР то файл .m должно быть что-то вроде:

@interface SplitViewController() 
{ 
    BOOL showLeftPane; 
    UIViewController* leftViewController; 
    UIViewController* rightViewController; 
} 
@end 

.... 

@implementation SplitViewController 
... 
@end 

На самом деле я, вероятно, принять его обратно. Не уверен, что он работает на vars .. но он делает для методов.

вы можете сделать вары частный счет использования @private в интерфейсе

редактировать

Моя ошибка. Исходный код верен, поскольку вы можете поместить iVars в файл реализации, подобный этому, начиная с XCode 4.2. В соответствии с этим вопросом SO instance-variables-declared-in-objc-implementation-file вам нужно выбрать 4.2+ и LLVM.

Так что теперь я говорю, что не знаю, о чем говорю!

+0

Ну, как я уже упоминал в своем вопросе, я попытался синтезировать свойства. Но, несмотря на это, я не использую свойства при устранении неполадок. Я напрямую назначаю их в файле инициализации. Кроме того, нет необходимости иметь iVars в файле .h. Я предпочитаю их в файле .m, так как они являются частными по своей природе. Во всяком случае, я попытался поместить их в файл .h. Такое же поведение. –

+0

@AaronHayman см. Изменения к моему ответу –

+0

Хорошо, для ударов Я попробовал. Все еще не работает. Но я не понимаю, почему вы хотели бы поставить iVars в категорию. Они отлично справляются с реализацией. Фактически, у каждого из моих 100+ классов в этом проекте есть свои iVars в реализации. Я помню, что было время, когда вы не могли этого сделать, но цель-c уже некоторое время разрешала объявления iVar в @implementation. –

 Смежные вопросы

  • Нет связанных вопросов^_^