This is utterly baffling to me, making me think I've missed something essential. But I'm trying to create a view controller container to manage two panes (similar to a SplitViewController but with some crucial differences). I've barely begun constructing the class, so I've only got 3 iVars right now:
@implementation SplitViewController{
BOOL _showLeftPane;
UIViewController *_leftController;
UIViewController *_rightController;
}
No matter what I do, I cannot assign a view controller to the _leftController iVar. Mostly, the _rightController iVar can assign. It get's weirder. If I switch the order of the iVars so _rightController appears before _leftController, I can't assign either one on the first try. However, if I try again (literally write the assignment twice) the _leftController will take. Consistently, when I use the console to request the the value of the first controller in listed in the iVar declarations immediately after assignment, the value I get is (UIViewController *) $5 = 0x00000001 [no Objective-C description available]. WTF?
Out of curiosity (and because I can...I've barely started writing the class) I changed the super from UIViewController to NSObject. When I do that, assignment works. And really, assignment is just about all this class does right now beside create a blank view on loadView.
What am I missing?
Update The rest of the code:
The entire .h file:
#import <UIKit/UIKit.h>
@interface SplitViewController : UIViewController
@property (strong) UIViewController *leftViewController;
@property (strong) UIViewController *rightViewController;
@end
The entire .m file (note, I've tried synthesizing the properties, same behavior except it's harder to debug from the console):
@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;
}
Originally, I had all the normal view controller overridden methods (loadView, viewDidLoad, etc...), but I've since commented them out until I could get this problem ironed out. Also, I'm using ARC.
Update 2 I've tried setting up a simple NSObject container class, thinking maybe it had to do with the iVars being of class UIViewController that posed the problem. But the same problem persists. So wrapping the UIViewController into another variable doesn't work. I've also tried changing the iVar type to 'id' but the problem persists.
I'd also like to note that I've cleaned the project and utilized the clang static analyzer to check for logic errors.
Update 3 All assignment in this class are 'off'...often (but not always) assigning the next iVar in the list. I put in a bunch of dummy id iVars and assigned them random objects. I then stepped through each assignment (which I put in the init) and tested the value before and after assignment:
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];
}
This is what I got (not the values don't change after assignment but those that do have values are often from the previous assignment). :
(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>
So, uh...is this a bug? If so, how in the heck would I file it? I don't even know what's going on....
Update 4 I got it to work, but only on my device. I generally tend to implement major changes on the simulator first (easier/quicker to debug) and then test it for performance on the device. Plus, I prefer to have a working version on my device so I can test it in my spare time. So I installed it on my device and the class works fine. It seems to only be broken in the simulator. Any ideas on why this might be? I really don't want to have to test the rest of my program development on the device alone. That'll slow things down a bit.