I have a drawing app with begins with choosing a category. Every category has his own drawing template. How do I get the secondViewController, to load the correct template? The category is chosen true a button from the firstViewController.
I have managed to give each segue a own identifier. And then what?
I only find examples of ways to parse data or images. But I don't want it to parse. I want it to load the image only on the secondViewController.
SecondViewController.h File
#property (strong, nonatomic) UIImage *theCatImage;
SecondViewController.m File
#interface secondViewController()
#property (weak, nonatomic) IBOutlet UIImageView *image;
#end
#implementation secondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.image.image = self.theCatImage;
}
ViewController.h File
#import <UIKit/UIKit.h>
#import "cat01ViewController.h"
#interface ikzieikzieAppViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *newImage;
#end
ViewController.m File
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"vervoer"]) {
cat01ViewController *secondView = (cat01ViewController *)segue.destinationViewController;
// dont know what to send here... i tried to hide and show a image like this;
secondView.theCatImage = self.newImage;
}
}
EDIT
Above code doesn't work, ALSO i don't want to send a image from one to another viewcontroller.
This is what i want;
On the firstViewController, a user can choose from four different categories. Each categorie will show his own drawing template and also, gives his own ID when the drawing is send to a parse database at the end.
So, what is the best way to set this up?
***SOLUTION***
Eventually, this is the way i solved it.
ViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"vervoer"]) {
UIImage *image = [UIImage imageNamed:#"vervoer.png"];
cat01ViewController *vc = [segue destinationViewController];
vc.showImage = image;
}
else if ([segue.identifier isEqualToString:#"huis"]) {
UIImage *image = [UIImage imageNamed:#"huis.png"];
cat01ViewController *vc = [segue destinationViewController];
vc.showImage = image;
}
else if ([segue.identifier isEqualToString:#"mode"]) {
UIImage *image = [UIImage imageNamed:#"vinkje.png"];
cat01ViewController *vc = [segue destinationViewController];
vc.showImage = image;
}
else if ([segue.identifier isEqualToString:#"eten"]) {
UIImage *image = [UIImage imageNamed:#"bord.png"];
cat01ViewController *vc = [segue destinationViewController];
vc.showImage = image;
}
}
SecondViewController
#synthesize catImage, showImage;
- (void)viewDidLoad
{
[catImage setImage:showImage];
[super viewDidLoad];
}
What you want to do is to add a property on SecondViewController:
#property (nonatomic) int category;
Then inside FirstViewController
Add property
#property (nonatomic) int chosenCategory;
Set this to the category that the user selected.
Then inside your seque code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
cat01ViewController *secondView = (cat01ViewController *)segue.destinationViewController;
[secondView setCategory:self.chosenCategory];
}
This will tell the VC which image it will need to draw. Then you call your parse library method to retrieve the image based on the ID (Category) chosen inside the viewDidLoad method in SecondViewController:
SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.image.image = [ParseLibrary getImageForCategory:self.chosenCategory];
}
Related
I am at a loss as to how to pass a selected image in one view controller to a tab bar controller using a segue, i keep on getting "unrecognized selector sent to instance ...". Here is my prepare for segue in a ViewController3 :
if ([[segue identifier]isEqualToString:#"tabbarGo"]) {
UITabBarController *tabar=segue.destinationViewController;
UINavigationController *navController = [tabar.viewControllers objectAtIndex:1];
ViewController5 *fifthView=[navController.viewControllers objectAtIndex:0];
fifthView.theImage = selectedImage.image;
[tabar setSelectedIndex:1];
}
i have imported ViewController5 into ViewController3 as 5 is the tab bar controller and the m file for viewcontroller5 is as follows :
#import <UIKit/UIKit.h>
#import "ViewController5.h"
#import "ViewController3.h"
#interface ViewController5 ()
#end
#implementation ViewController5
#synthesize theImage;
-(void)setImage:(UIImage *)image
{
}
- (void)viewDidLoad {
[super viewDidLoad];
[_imageView setImage:theImage];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I do not understand what i am doing wrong and have gone through most of the posts, or should i go through a "NSUserDefaults *prefs" approach to this ?
Any help appreciated and thanks.
ok got it to work to send an image to a tab bar with navigation controller by adding one line of code, i was forgetting to specify the NSString value of the segue so here is the final full code for "prepare for segue" :
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueIdentifier = [segue identifier];
UITabBarController *tabar=segue.destinationViewController;
UINavigationController *navController = [tabar.viewControllers objectAtIndex:1];
ViewController5 *fifthView=[navController.viewControllers objectAtIndex:0];
fifthView.theImage = selectedImage.image;
[tabar setSelectedIndex:1];
}
I have a CollectionView and in the didSelectItemAtIndexPath method I have instantiating a new ViewController, setting the String property on the ViewController to hold the image's name. And then in the viewDidLoad OR the viewDidAppear method in the new ViewController I am trying to set the image using the vc.imageName property.
Here is the code:
// collection.m
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
ViewController *vc = [[ViewController alloc] init];
NSString *imageName = [colouringPhotos objectAtIndex:indexPath.row];
vc.imageName = imageName;
[self presentViewController:vc animated:YES completion:nil];
}
// ViewController.h
#property (nonatomic, strong) NSString * imageName;
//ViewController.m
#property (strong, nonatomic) IBOutlet UIImageView *lineImageView;
-(void) viewDidAppear:(BOOL)animated{
self.lineImageView.image = [UIImage imageNamed:self.imageName];
}
But the image doesn't show. I have set the background colour on the ImageView to check that it is being displayed in the new ViewController and I can see it but the image never displays within the UIImageView.
You could use a Segue to show the next view controller. Assuming you use "ShowNextViewController" as the identifier for your Segue, you could use prepareForSegue:sender: to set the imageName property of the destination view controller:
- (void)prepareForSegue:(nonnull UIStoryboardSegue *)segue sender:(nullable id)sender {
if ([segue.identifier isEqualToString:#"ShowNextViewController"]) {
ViewController *destination = (ViewController *)segue.destinationViewController;
NSIndexPath *selectedIndex = [[self.collectionView indexPathsForSelectedItems] firstObject];
destination.imageName = self.colouringPhotos[selectedIndex.row];
}
}
If you have trouble setting up the segue, see this iOS Developer Library document for more information.
Also, see the UIViewController Class Reference for more information on the prepareForSegue:sender: method.
I tried many custom delegate examples in my code to send data from view B back to parent view A. Why am I getting NULL? There should be something I am missing. Please help. How can I call setupDate to receive (NSDate *)setAlarmDate in Parent view?
Parent view
#import "SetupViewController.h"
#interface ViewController : UIViewController <SetupViewControllerDelegate> {
NSTimer *timer;
}
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"setupview"]) {
NSLog(#"prepare for segue");
SetupViewController *svc = [[SetupViewController alloc] init];
svc.delegate = self;
-(void)setupDate:(NSDate *)setAlarmDate{
NSLog(#"Hey Hey");
NSLog(#"%#", setAlarmDate);
}
#end
View B
#protocol SetupViewControllerDelegate <NSObject>
#required
-(void)setupDate:(NSDate *)setAlarmDate;
#end
#interface SetupViewController : UIViewController
#property (nonatomic, strong) id <SetupViewControllerDelegate> delegate;
//IB
#property (weak, nonatomic) IBOutlet UIDatePicker *pDatePicker;
#end
.m
#import "SetupViewController.h"
#import "ViewController.h"
#implementation SetupViewController
-(void)viewWillDisappear:(BOOL)animated{
NSDate *date = [self.pDatePicker date];
[[self delegate] setupDate:date];
}
#end
You should access the UIViewController using the segue's destinationViewController property instead of allocating an instance of your own, which is why your alarmDate = NULL.
E.g.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"setupview"])
{
NSLog(#"prepare for segue");
SetupViewController *svc = [segue destinationViewController];
svc.delegate = self;
}
}
Also, as #Neru mentioned your delegate should be qualified as weak and not strong. The reason for this is because you will cause a retain cycle if you do not explicitly set the delegate = nil in the dealloc method.
I have three navigation buttons in a view controller, two of which I process locally and one which launches an edit view controller. I have created a segue from the body of the first UITableView to the Navigation Controller of the destination view controller (the edit view controller).
The button works fine (i.e. launches the edit view) but it doesn't receive the string I send to it. Could someone please help. I have tried all of the suggestions given to other related questions but cannot seem to fix this. Following is the related code.
Source controller.h:
#import <UIKit/UIKit.h>
#import "EQHorseAddViewController.h"
#import "EQDatabase.h"
#interface EQHorseDetailViewController : UITableViewController
#property (strong, nonatomic) EQHorseAddViewController *addViewController;
Source controller.m:
#import "EQHorseDetailViewController.h"
#interface EQHorseDetailViewController ()
#end
#implementation EQHorseDetailViewController
#synthesize addViewController;
-(void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *deleteItem= [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
target:self
action:#selector(deleteHorse:)];
UIBarButtonItem *editItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self
action:#selector(editHorse:)];
NSArray *actionButtonItems = [[NSArray alloc] initWithObjects:deleteItem, editItem,
nil];
self.navigationItem.rightBarButtonItems = actionButtonItems;
}
-(void)editHorse:(id)sender
{
NSLog(#"EditingHorse");
self.addViewController= [[EQHorseAddViewController alloc] init];
addViewController.resultSegue = #"Edit Horse Details";
[self performSegueWithIdentifier:#"EditHorseDetails" sender: self];
}
Destination View Controller.h:
#import <UIKit/UIKit.h>
#import "EQHorseDetailsInfo.h"
#import "EQDatabase.h"
#class EQHorseAddViewController;
#protocol EQHorseAddViewControllerDelegate <NSObject>
- (void) eqHorseAddViewControllerDidCancel:(EQHorseAddViewController *)controller;
- (void)eqHorseAddViewControllerDidSave: (EQHorseAddViewController *)controller;
#end
#interface EQHorseAddViewController : UITableViewController
<EQHorseAddViewControllerDelegate>
#property (strong, nonatomic) EQHorseAddViewController *addViewController;
#property (nonatomic, weak) id <EQHorseAddViewControllerDelegate> delegate;
#property (strong,nonatomic) NSString *resultSegue;
Destination View Controller.m
#import "EQHorseAddViewController.h"
#import "EQDatabase.h"
#import "EQHorseDetailsInfo.h"
#interface EQHorseAddViewController ()
#end
#implementation EQHorseAddViewController
#synthesize resultSegue;
- (void)viewDidLoad
{
NSLog(#"resultSegue %#",resultSegue);
}
Thanking you in advance.
It looks like you're referring to the code in editHorse:, which allocates an EQHorseAddViewController and sets a property on it. The problem with that code is that the view controller it allocates bears no relation to the vc destination of the segue. That method simply creates a vc and then instantly discards it.
Remove the allocation and instead implement prepareForSegue:. The segue object passed to that method will have a property called destinationViewController. That's the view controller that's about to be pushed onto the navigation. That's the one on which you should set the resultSegue property.
-(void)editHorse:(id)sender
{
NSLog(#"EditingHorse");
[self performSegueWithIdentifier:#"EditHorseDetails" sender: self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"EditHorseDetails"]) {
EQHorseAddViewController *vc = segue.destinationViewController;
vc.resultSegue = #"Edit Horse Details";
}
}
You need to define the new controller as follows:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
EQHorseAddViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"EditHorseDetails"];
ivc.resultSegue = #"Edit Horse Details";
Perhaps you'll need this method too
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"EditHorseDetails"]) {
// Get destination view
EQHorseAddViewController *vc = [segue destinationViewController];
vc.resultSegue = #"Edit Horse Details";
}
}
-(void)editHorse:(id)sender
{
NSLog(#"EditingHorse");
resultSegue = #"Edit Horse Details";
[self performSegueWithIdentifier:#"EditHorseDetails" sender: self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navigationController = segue.destinationViewController;
EQHorseAddViewController *addViewController = [navigationController viewControllers]
[0];
// Get destination view
NSLog(#"ResultSegue in Prepare - %#",resultSegue);
addViewController.resultSegue = #"Edit Horse Details";
}
I'm trying to learn more about Objective C blocks and how they work. I've set up a simple project with two UIViewControllers embedded in a UINavigationController in Storyboard. I'm attempting to change the background color of the first ViewController's view from the second view controller. Here's some code:
ViewController.m
#implementation ViewController{
ColorBlock _colorBlock;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.colorBlock = _colorBlock;
}
}
- (IBAction)moveToSecondViewController:(id)sender {
__weak id weakSelf = self;
_colorBlock = ^{
[[weakSelf view] setBackgroundColor:[UIColor redColor]];
};
}
SecondViewController.h
typedef void (^ColorBlock)(void);
#interface SecondViewController : UIViewController
#property (readwrite, copy) ColorBlock colorBlock;
#end
SecondViewController.m
- (IBAction)buttonTapped:(id)sender {
if(self.colorBlock){
self.colorBlock();
}
}
The first ViewController's background color isn't being changed because in the buttonTapped: method of SecondViewController.m, self.colorBlock is nil, causing the block invocation not to be called. I thought I had successfully set the block in prepareForSegue:sender:. Why is my block property nil?
In your prepareForSegue, the destination has already been instantiated. So assuming that SecondViewController is the destination, you can do:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = segue.destinationViewController;
NSAssert([vc isKindOfClass:[SecondViewController class]], #"destination is not SecondViewController class");
vc.colorBlock = _colorBlock;
}
}