UIView not Initialized from Storyboard Segue - uiview

I am attempting to perform a Storyboard segue from a UIbutton that is a day on a calendar to a DayViewController with info on that day. The currentTitle of the sender UIbutton should be passed to a UILabel in the dayView of the DayViewController. It successfully segues to the new VC and assigns the button title to a property therein, however the dayView (and the base view) of my DayViewController is not getting initialized (their addresses in the debugger are both 0x0) and I get a blank page. How can I get these views to initialize in this segue? (I thought views linked to a VC were automatically initialized when segued to?)
Here's the prepareForSegue getting called:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(UIButton *)sender
{
if ([segue.identifier isEqualToString:#"ShowDay"]) {
DayViewController *vc = segue.destinationViewController;
[vc setCurrentDayNumber:sender.currentTitle];
}
Here is setCurrentDayNumber in the new VC
-(void)setCurrentDayNumber:(NSString *)currentDayNumber
{
_currentDayNumber = currentDayNumber;
[self.dayView setNeedsDisplay];
}
Here is my view that is linked to DayViewController in the storyboard.
#property (nonatomic, weak) IBOutlet DayView *dayView;
Thanks in advance!

When you declare a property as weak, it will not "hold on" to the value unless someone else has a reference to it as well. When the new view controller is pushed, the old button goes away, leaving currentDayNumber as the only reference, so it automatically sets itself to nil. (This is what weak is supposed to do.)
If you want to keep a reference to it no matter what, use strong instead of weak and make sure to set _currentDayNumber to nil somewhere (like viewDidUnload) so that you don't retain it forever.

Related

ViewController's private data set to nil after returning from segue

I have two views. The main view is ViewController and the next is AddItemViewController. ViewController has a tableview that lists items that you add when you go to AddItemViewController. There is a button on AddItemViewController that segues back to ViewController. The problem is, upon returning to ViewController expecting that an item be added, the private data of ViewController is suddenly set to nil. I have lost data and any chance to interact with my objects after returning from the segue.
Here is the data that's getting set to nil
#property (strong, nonatomic) costEstimator *myCost;
#property NSString *testString;
What am I doing wrong?
Here is my prepareforsegue code in the AddItemViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
ViewController *vC = [segue destinationViewController];
[vC addSomething:_selectedItem withQuantity:[_quantBox.text doubleValue]];
}
Any help is greatly appreciated. Thanks :)
You want to pop the AddItemViewController in this case. When you segued from ViewController to AddItemViewController, I am guessing you did a push. What this does effectively is it adds AddItemViewController ontop of ViewController in the memory stack. By 'segue-ing' again from AddItemViewController to ViewController, you are adding ANOTHER ViewController instance ONTOP of AddItemViewController. This is why you think you are losing your data when in actuality, you aren't. You are only seeing the wrong view controller.

iOS passing values from two level Modal view controller

I'm trying to make a form that one of the filed takes value from a two level selections' result.
The main progress will something like:
EditViewController ===> CategoryViewController (which embedded inside a NavigationController by storyboard and popped up as a modal view) ===> SubCategoryViewController (Which will be pushed to NavigationController).
Now I have a problem. After user tap to select a value in SubCategoryViewController, I'm supposed to dismiss SubCategoryViewController and return the value to EditViewController. But I don't know exactly how.
Please suggest any solution.
Thank you.
EDIT:
Every one of those view controllers should have a public property for a weak reference to a model object that represents whatever is being edited.
So every ____ViewController.h file would have:
#property (weak, nonatomic) CustomItem *item.
in its interface (assuming a strong reference is somewhere in some data store or array of all the items).
When EditViewController is preparing for the segue to show CategoryViewController modally, it should assign that same reference to CategoryViewController's item property after assigning any data entered in EditViewController's form to item:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//TODO: assign data from controls to item, for example:
//self.item.title = self.titleField.text;
CategoryViewController *vc = (CategoryViewController *)segue.destinationViewController
vc.item = self.item; //pass the data model to the next view controller
}
Likewise for the segue from CategoryViewController to SubCategoryViewController. This ensures that every ViewController is editing the same object in memory. When you dismiss SubCategoryViewController (assuming somewhere in all of this CategoryViewController was already dismissed), viewWillAppear: will be called on EditViewController- there you can refresh any changes made in the modal views to the item property, just like you would when first displaying the view (it's actually the same method that's called):
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.titleField.text = self.item.title;
self.categoryLabel.text = self.item.category;
self.subcategoryLabel.text = self.item.subcategory;
//etc....
}

Add Property View to another View Controller

Basically i am using a segue to display a modal ViewController.
I want to the modal ViewController to display a custom subclass of UIView which i have declared as a strong property in my main ViewController like this:
#property (nonatomic,strong) myView *theView;
in prepareForSegue:sender: i adjust the custom UIViews frame and add it to the modal ViewController:
-(void)prepareForSegue:(UIStoryBoardSegue*)segue sender:(id)sender{
UIViewController *destination = [segue destinationViewController];
[self.theView setFrame:destination.view.bounds];
[destination.view addSubview:self.theView];
}
Aside from the View still being the wrong size, only works the first time i invoke it. The second time it will crash with EXC_BAD_ACCESS on the
[destination.view addSubview:self.theView];
line.
Any ideas why this is happening?
Thanks in advance

performSegueWithIdentifier destinationViewController deallocs with ARC

Odd issue here:
I created a storyboard with two view controllers, connected with a custom segue(a cross disolve). I make the segue happen by:
-(void)transitionToIntro
{
[self performSegueWithIdentifier:#"ToIntro" sender:self];
}
This transitions and I see the new view controller, After the initWithCoder and AwakeFromNib it sets up the UI and I see that the properties for data source and delegates are set. THen all of a sudden dealloc is fired! and this destination view controller is dealloc'd. Then of course everything is bunked. Delegates are nil and Datasources are nil because the containing viewcontroller is invalid to the subviews that contained it...
I dont know why this is happening, is the source viewcontroller not retaining a strong hold on the destination viewcontroller?
I have made sure to make the initial view controller set in the story board to my source view controller.
Any help is appreciated
Solution:
Make sure to have your source VC have a retained strong reference to the destination VC , and set that in prepareForSegue. If not you will see your destination VC dealloc itself after running initWithCoder and AwakeFromNib.
#property (nonatomic, strong) IntroViewController *destVC;
-(void)transitionToIntro
{
[self performSegueWithIdentifier:#"ToIntro" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ToIntro"])
{
IntroViewController *dest = [segue destinationViewController];
self.destVC = dest;
}
}

segue: destination view controller weirdness

In my app, I use a storyboard and segues, and I often pass data to the destination view controller before doing the segue, as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setMyData:)]) {
[segue.destinationViewController performSelector:#selector(setMyData:)
withObject:myData];
}
}
It works everywhere except in one place. The selector gets called, the data gets set, but when the segue completes and the destination controller appears, it doesn't have the data I just set. After printing the view controller's id in both the source and destination view controllers, I found that the segue.destinationViewController in the code above is a DIFFERENT instance of the view controller than the one that gets displayed. What's going on here?
[UPDATE 1]
I looked into the lifecycle of the destination view controller, and it first gets loaded during the segue execution, but AFTER I set the property on it! This means, that when I call performSelector on it, the view controller object is not initialized! This is why the data I set doesn't stick. t don't understand why is this the case, and why this same approach works in the other parts of my app.
[UPDATE 2]
Posting the code of setMyData by request. At first I didn't have this method at all, because locationToOpen is a public property. I only added it to ensure it gets called and to print the debug info.
- (void)setMyData:(MyData *)myData
{
DLog(#"self: %#", (id)self);
_myData = myData;
}
I would do it as follows -
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"NextSegue"])
{
DestinationViewController *dest = [segue destinationViewController];
dest.myData = self.myData;
}
}
And in the DestinationViewController.h, you should create a property -
#import <UIKit/UIKit.h>
#interface DestinationViewController : UIViewController
#property (nonatomic, strong) NSObject *myData;
#end
And also, make sure to synthesize the myData property in DestinationViewController.m -
#interface DestinationViewController ()
#end
#implementation DestinationViewController
#synthesize myData = _myData;
// other methods here
#end
I had this same issue. It turned out for me that the target ViewController property I was setting in my prepareForSegue: code was declared as weak because I had copied and pasted the property from one that InterfaceBuilder auto-created, but mine was not a Storyboard object. So my property was being released and zeroed by ARC on exit from prepareForSegue:. Making it a non-weak property fixed it.
I had a similar problem where the ViewController I was doing the segue to changed at some odd point,
after a looking around a bit it seems that the segue created a new ViewController.
To solve the data passing problem I used notifications.
I know this thread is old and solution should be found. But since the final solution is not posted here, I would like to list one of the possible root cause (which is the one in my case). I had the same issue, trying to set the variable in the destination view controller of the segue. The root cause is that I forgot to instantiated ([[Class alloc]init]) the object variable. I need it in my case because I am setting the properties of the object instead of pointing to other object. Hope this help.

Resources