I’m not sure why, but I’m having trouble passing a data object (NSManagedObject) to a view controller when that view controller is being instantiated inside another one. When I log the object before it is passed, it has all of its data, but after it gets to the view controller, it is empty. It seems like this should be fairly straight-forward, but for some reason it’s just not getting there.
The code which assigns the NSManagedObject to the accepting view controller in the implementation file is: viewController.thisCard = aCard;
Any help is much appreciated. Thanks in advance.
This is the header for the view controller which scrolls:
@interface HandViewController : UIViewController
<UIScrollViewDelegate>
{
IBOutlet UIScrollView *scrollView;
IBOutlet UIPageControl *pageControl;
BOOL pageControlIsChangingPage;
NSManagedObjectContext *context;
}
@property (nonatomic, retain) UIView *scrollView;
@property (nonatomic, retain) UIPageControl *pageControl;
@property (nonatomic, retain) NSManagedObjectContext *context;
/* for pageControl */
- (IBAction)changePage:(id)sender;
@end
this is the viewDidLoad in the implementation of that object
- (void)viewDidLoad
{
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Game" inManagedObjectContext:[self context]];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *fetchedGames = [self.context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
Game *aGame = [fetchedGames objectAtIndex:0];
CGFloat cx = 0;
for (Card *aCard in aGame.turnUpcoming.hand) {
CardViewController *viewController = [[CardViewController alloc] initWithNibName:@"CardViewController" bundle:nil];
CGRect rect = self.view.frame;
rect.size.height = scrollView.frame.size.height - 50;
rect.size.width = scrollView.frame.size.width - 50;
rect.origin.x = ((scrollView.frame.size.width - rect.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - rect.size.height) / 2);
viewController.view.frame = rect;
viewController.thisCard = aCard;
[scrollView addSubview:viewController.view];
cx += scrollView.frame.size.width;
[viewController release];
}
self.pageControl.numberOfPages = [aGame.turnUpcoming.hand count];
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
UPDATE: Per request, I am adding a bit of code from the view controller
This is the header for CardViewController
@interface CardViewController : UIViewController {
UILabel IBOutlet *cardValue;
UILabel IBOutlet *cardInstruction;
UILabel IBOutlet *cardHint;
UILabel IBOutlet *cardTimer;
UIButton IBOutlet *playCardButton;
Card *thisCard;
}
@property (nonatomic, retain) UILabel IBOutlet *cardValue;
@property (nonatomic, retain) UILabel IBOutlet *cardInstruction;
@property (nonatomic, retain) UILabel IBOutlet *cardHint;
@property (nonatomic, retain) UILabel IBOutlet *cardTimer;
@property (nonatomic, retain) UIButton IBOutlet *playCardButton;
@property (nonatomic, retain) Card *thisCard;
@end
Here is the viewDidLoad from the implementation of CardViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if ([thisCard isObjectValid]) {
cardValue.text = [thisCard.value stringValue];
}
}
UPDATE: new code for card loop in viewDidLoad and new CardView code, per suggestions below
loop in viewDidLoad:
for (Card *aCard in aGame.turnUpcoming.hand) {
CGRect rect = scrollView.frame;
rect.size.height = scrollView.frame.size.height - 50;
rect.size.width = scrollView.frame.size.width - 50;
rect.origin.x = ((scrollView.frame.size.width - rect.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - rect.size.height) / 2);
tempCardView = [[CardView alloc] initWithFrame:rect];
tempCardView.thisCard = aCard;
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"CardView" owner:self options:nil];
tempCardView = [nibObjects objectAtIndex:0];
[scrollView addSubview:tempCardView];
cx += scrollView.frame.size.width;
[tempCardView release];
}
header file CardView.h
@interface CardView : UIView {
UILabel IBOutlet *cardValue;
UILabel IBOutlet *cardInstruction;
UILabel IBOutlet *cardHint;
UILabel IBOutlet *cardTimer;
UIButton IBOutlet *playCardButton;
Card *thisCard;
}
@property (nonatomic, retain) UILabel IBOutlet *cardValue;
@property (nonatomic, retain) UILabel IBOutlet *cardInstruction;
@property (nonatomic, retain) UILabel IBOutlet *cardHint;
@property (nonatomic, retain) UILabel IBOutlet *cardTimer;
@property (nonatomic, retain) UIButton IBOutlet *playCardButton;
@property (nonatomic, retain) Card *thisCard;
@end
implementation file CardView.m
@implementation CardView
@synthesize cardHint;
@synthesize cardTimer;
@synthesize cardValue;
@synthesize cardInstruction;
@synthesize playCardButton;
@synthesize thisCard;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
if ([thisCard isObjectValid]) {
cardValue.text = [thisCard.value stringValue];
cardInstruction.text = thisCard.instruction;
cardHint.text = thisCard.hint;
cardTimer.text = [thisCard.time stringValue];
}
}
return self;
}
@end
UPDATED: 6/16 – Added XIB screen shot
CardView.xib

Seems like your CardViewController should actually be a UIView. As Apple says: ” A single view controller typically manages the views associated with a single screen’s worth of content, although in iPad applications this may not always be the case.”
(After changes to UIView) in your loop, you’re creating one tempCard and then loading another. If you’ve linked tempCardView in IB (see below), then all you need is:
So, you have two XIBs, your main one that loads with your viewController, and one (CardView) that gets loaded once for each card.
Now, inside CardView, you’re trying to set up the labels too soon. During initWithFrame (which in the above case is called by loadFromNib), you don’t have access yet to thisCard. You’ll need a setter for thisCard, which will be called any time a value is assigned to thisCard property:
Now in Interface Builder,
You should be all set.