I am using storyboard and xcode 5.
I am trying to use NSUserDefaults to store image data. But i have lots of image
I think this will exhaust quickly.
Is there any better way pass image data to another screen ??
Declare a property in destination view controller like this #property (nonatomic, strong) NSArray *places; Set identity name for your seque in storyboard
Then in source controller in method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"SegueName"])
{
YourDestinationVC *vc = (YourDestinationVC *)segue.destinationViewController;
vc.places = places;
}
}
Related
I have a UIViewController controlling several different views in Xcode. I want to set a label on the incoming view using information from the current view. I know labels and other UI elements get reset when the view is loaded, but my non UI #property is being set to nil as well.
Here is my property:
#property (strong, nonatomic) NSString* username;
Here is the code that sets it:
//NSLog(#"%#",dict);
if ([dict[#"login"] intValue]){
[self performSegueWithIdentifier:#"JoinSuccess" sender:sender];
self.username = dict[#"user"];
Here is the code that tries to use it:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", self.username);
self.welcomeLabel.text = [NSString stringWithFormat:#"Welcome, %#",self.username];
}
I've tried setting username both before and after performSegueWithIdentifier, but in either case when I try to reference it in viewDidLoad the value is nil. Any idea as to why it's reseting my #property? My guess is maybe it's creating a new instance of my viewController. If that's the case, how can I pass the needed variable?
As you said the viewController will be created again when ever you call performSegueWithIdentifier. You could set the value in the new instance. You can do this in
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
YourViewController *vc = [segue destinationViewController];
vc.username = dict[#"user"];
}
you have to add another method to pass value from one view controller to another view controller .
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
nextViewcontroller *nextViewcontrollerObjt = [segue
destinationViewController];
// apply setter to set value of next view
nextViewcontrollerobject.title = nextViewControllerTitleString;
nextViewcontrollerobject.variable_1= currentView_variable1;
nextViewcontrollerobject.variable_2 =currentView_variable2;
}
I have a simple push segue that goes from one UITableViewController to another. At the time of initing the other UITableViewController, I want to pass an id that will be used to perform an sqlite query and populate the table. I could use a public property and reload the table in a custom setter, but the design seems better if it is done on initing. After searching around for quite a while I haven't been able to find any clear examples. I have a seen a mentions of initWithCoder and initWithFrame but they haven't been clear enough to connect it to what I am trying to do.
Here is what the segue looks like from the first table:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowFlashcards"]) {
//pass variable to custom init somewhere around here?
FlashcardsTableViewController *flashcardsTableViewController = [segue destinationViewController];
}
}
Here is what the custom init looks like:
#property (nonatomic, strong) NSNumber *listId;
#property (nonatomic, strong) NSArray *flashcards;
- (id)initWithListId:(NSNumber *)listId {
self = [super init];
if (self ) {
self.listId = listId;
Database *db = [[Database alloc] init];
self.flashcards = [db getWordsFromList:[listId integerValue]];
}
return self;
}
You are over-thinking this, and coming to some wrong conclusions.
Adding a property to the destination VC (view controller) and setting it in prepareForSegue is exactly what you want to do.
You can't use a custom init in this situation. Invoking the segue allocates and initializes the destination VC (actually, I believe it is created using the initWithCoder method.) The destination VC's view won't have been loaded yet when prepareForSegue is called, so you can set properties and they will be set up by the time the destination VC's viewDidLoad method gets called.
#AJHacker's answer shows how to give the destination VC a pointer to the source VC, which is useful when the destination needs to be able to send data back.
You would need to add a property that contains a reference of the first view into the second view. For example:
#interface AutoRenewDrop
#property(weak, nonatomic) AddR *callerView;
#end
And then in the 'done' method of the second view you can just update the variables in the caller view like so:
-(IBAction)done:(UIStoryboardSegue *)segue {
[self.navigationController popViewControllerAnimated:YES];
callerView.renewDate.text = transferData;
}
Of course when you initiate the second view you will have to set the reference, like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Check Mark Segue"])
{
NSLog(#"Transfering Data");
AutoRenewDrop *controller = segue.destinationViewController;
controller.transferData = self.renewDate.text;
controller.callerView = self; //Here, you are passing the reference to this View
}
}
Hope that helps
I am having two view controllers 'FirstViewController' and 'SecondViewController'. From first view controller it will take input from a text field ,process it and display accordingly in the second view. But I am having a problem while setting label value directly.
#interface SecondViewController : UIViewController
{
NSString *numPlate;
IBOutlet UILabel *output;
};
#property(strong,nonatomic) NSString *numPlate;
#property(strong,nonatomic) IBOutlet UILabel *output;
#end
The main file for FirstViewController.m with prepare for segue is as
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
svc.numPlate = input.text;
NumberPlate *numPlate=[[NumberPlate alloc]init];
[numPlate setPlate:input.text];
NSInteger flag=[numPlate checkValidity];
if(flag==0)
{
svc.output.text =#"Invalid License";
}
else
if([numPlate getArea]==NULL||[numPlate getRegOffice]==NULL)
{
svc.output.text =#"Data not found";
}
else
{
svc.output.text =#"VALID License";
}
}
}
But when the action is performed its not working.The label is not changing.
When i used svc.numPlate instead of svc.output.text and in the SecondViewController viewDidLoad method and i used
- (void)viewDidLoad
{
[super viewDidLoad];
output.text=numPlate;
}
Everything is fine with this. Whats wrong in first method??
You will not be able to assign value directly to UILabel of second VC as view is not yet loaded into view hierarchy at this point.
So view cannot render the value assigned prior to it.
On the other hand, holding value in NSString and assigning same on viewDidLoad is working as now your view is in view hierarchy and loaded into memory.
At the time when you push SecondViewController, the SecondViewController's view hasn't been loaded yet, so you can't access its views. You need to create NSString properties in SecondViewController and pass a string to SecondViewController' NSString Object. Then in SecondViewController's viewDidLoad method, use those properties to populate the labels (which will have been loaded by the time viewDidLoad runs).
The initialisation of controller is different and presentation of its view is different process even if the viewController has been initialise its view will not because pushing the controller has not performed and controller dont know he need to load the view.. so we pass the data to controller and it load when view appears... like below code
#interface SecondViewController : UIViewController{
NSString *strMessage;
}
#property(nonatomic,retain) NSString *strMessage;
#end
SecondViewController.m
#synthesize strMessage;
- (void)viewDidLoad {
Nslog(#"%#",strMessage);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
NSString *message = [NSString stringWithFormat:#"Check out %#", nameLb.text];
svc.strMessage=message;
}
The relevant part of my storyboard appears as follows:
You can see the custom "Container Controller" view houses two Container Views, one which links to a Navigation Controller via embedded segue, and another that links to a custom "Master View Controller" (which implements a Table View Controller) via embedded segue. The Navigation Controller component further has a relationship with a custom "Location Filter Controller."
I need to implement delegation such that when one of the UISteppers in the Location Filter Controller is incr./decr., the table view in the Master View Controller knows to update the data it displays accordingly.
I am not unaccustomed to working with protocols/delegates, but this unique situation of talking between views housed in segues is really tricking me! For the most part I have had success following the example here: Passing Data between View Controllers. In this case however, I am not able to directly link instantiated views as he indicates to do in 'Passing Data Back' step 6.
I had considered using a singleton object from which each of these views could get/set the necessary data, but the issue here is that the table view would not necessarily know when to update its contents, despite having data with which it could/should update.
Here is a code snippet from ContainerController.m where I setup the embedded segues to function:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DataHold *data = [[DataHold alloc] init]; // <-- this actually is a singleton object
if([segue.identifier isEqualToString:#"locationEmbedSegue"])
{
}
else if([segue.identifier isEqualToString:#"tableEmbedSegue"])
{
[[segue destinationViewController] setDelegate:data.detailTableViewController];
// ^ This part actually sets up a delegate so that the table view (Master View Controller)
// delegates to the detail view controller of the overarching split view controller
// and tells it what to display when a row is pressed.
}
}
Thanks for any help!
I think you are on the right track setting the table view delegate to your Location Filter Controller.
I found that a simple way to work with embeded view controller is to add "placeholders" property for them, and set these property when the segue is "performed".
// MyContainerController.h
#property (strong, nonatomic) MyLocationFilterController *detailViewController;
#property (strong, nonatomic) UITableViewController *masterViewController;
// MyContainerController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"locationEmbedSegue"])
{
UINavigationViewController *dest = (UINavigationViewController *)segue.destinationViewController;
self.detailViewController = dest.topViewController;
}
else if([segue.identifier isEqualToString:#"tableEmbedSegue"])
{
self.masterViewController = (UITableViewController *)segue.destinationViewController;
[self.masterViewController.tableView setDelegate:self.detailViewController];
}
}
I came to this question recently and found there may be one problem with the answer above.
Move the setDelete: method out. This makes sure no controller is nil.
Then code becomes:
// MyContainerController.h
#property (strong, nonatomic) MyLocationFilterController *detailViewController;
#property (strong, nonatomic) UITableViewController *masterViewController;
// MyContainerController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"locationEmbedSegue"])
{
UINavigationViewController *dest = (UINavigationViewController *)segue.destinationViewController;
self.detailViewController = dest.topViewController;
} else if([segue.identifier isEqualToString:#"tableEmbedSegue"])
{
self.masterViewController = (UITableViewController *)segue.destinationViewController;
}
[self.masterViewController.tableView setDelegate:self.detailViewController];
}
I have a Navigation Controller and 2 Views Controllers. The first View Controller is associated with a UIViewController named ViewController. The second is connected to a UIViewController named BookVC. BookVC has a UITextField and is connected via an outlet:
#property (strong, nonatomic) IBOutlet UITextField *textFieldContent;
The connection is made with a button that uses a segue. I want to pass some data between the two and am using the following code which fails:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BookVC* nextPage = [[BookVC alloc] init];
nextPage = [segue destinationViewController];
nextPage.textFieldContent.text=#"Some content";
}
How should I pass data between the View Controllers?
I think the problem is that textFieldContent doesn't exist at that point. You'll need to add a property to BookVC that can hold the text you want to put into textFieldContent... we'll call it #property NSString *textFieldContentText. So then,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BookVC *nextPage = [segue destinationViewController];
[nextPage setTextFieldContentText:#"Some content"];
...
}
And then, in the -viewDidLoad method of BookVC:
- (void)viewDidLoad
{
[textFieldContent setText:[self textFieldContentText]];
}
You don't need this line:
BookVC* nextPage = [[BookVC alloc] init];
That creates a brand new BookVC which you then go and overwrite in the next line.
Since you are using [segue destinationViewController] you should be good to go. What's happening when you segue to nextPage?