Sending information from a view controller to another - ios

The question is, I have 9 buttons on viewcontroller (ViewController), and i have an outlet collection for storing all these buttons outlet.
Then i have an action method for handling click event of these buttons.
What I want is send the button image background (as an UIImage * img)of the CLICKED button, segue to another viewcontroller (vc2),
here are my code :
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardBtns;
- (IBAction)cardAction:(id)sender;
#end
#import "ViewController.h"
#import "ResultViewController.h"
#interface ViewController ()
#property(strong,nonatomic)UIImage *image;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//UIImage * img = [UIImage imageNamed:#"f1"];
UIImage * img = (UIImage *)sender;
ResultViewController *viewcontroller = [segue destinationViewController];
viewcontroller.img = img;
}
#end
in vc2, i have another button here, and i wish to paint this button background img with the img just sent from vc1 segue.
#interface ResultViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *cardBtn;
#property(strong,nonatomic)UIImage *img;
- (IBAction)cardDismiss:(id)sender;
#end
#import "ResultViewController.h"
#interface ResultViewController ()
#end
#implementation ResultViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.cardBtn setImage:self.img forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardDismiss:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
}
#end
assume my buttons is 1,2,3,4,5,6,7,8,9
for now, whatever buttons i clicked in vc1, it s always displaying as '6' in vc2...
any suggestions? thanks

The problem is this:
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
This will set self.image to the last item in self.cardBtns. You want to set self.image to sender.currentBackgroundImage (and change id in the argument type to UIButton *), and just eliminate the loop.

Related

UIBarButtonItem Cancel does not work

I want to cancel the second view controller with a UIBarButtonItem, but I just don't get the code right. Please help.
Viewcontroller.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface ViewController : UIViewController <SecondViewControllerDelegate>
#end
Viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[SecondViewController class]]) {
SecondViewController *vc2 = segue.destinationViewController;
vc2.delegate = self;
}
}
-(void)dismissViewController
{
NSLog(#"dismissed");
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Secondviewcontroller.h
#import <UIKit/UIKit.h>
#protocol SecondViewControllerDelegate <NSObject>
- (void) dismissViewController;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id <SecondViewControllerDelegate> delegate;
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender;
#end
BackbarButton means cancelbutton
Secondviewcontroller.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self.delegate dismissViewController];
}
#end
You can dismiss in secondViewController,I do not see the meaning of Delegate in your code
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:true completion:nil];
}
If you use show segue,and you have a navigationController with these two ViewControllers,Use
- (IBAction)dismiss:(id)sender {
[self.navigationController popViewControllerAnimated:true];
}

Send Screenshot of ViewController to other ViewController

I would like to take a screenshot of ViewController, blur the image, send it to ProfileViewController, then set it as the background of ProfileViewController. This should not be that difficult as each task is pretty straightforward, I am just having difficulty finding the correct syntax as to how to do this.
The way I want this to work is such:
The user starts on ViewController, the main view.
Upon the click of a button (labeled profTap) the user is taken to ProfileViewController.
ProfileViewController is displayed through a segue (present modally) with its background set as a blurred image of the previous view from ViewController.
If someone could show me with code how to send the image to ProfileViewController I would be most appreciative. For reference, here is my code below that I have for now of the ViewController. I believe I am capturing the image correctly, I am jsut not sure what to do from here to send it to the ProfileViewController.
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#import "ProfileViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)profTap:(id)sender {
UIGraphicsBeginImageContext(self.mainView.bounds.size);
[self.mainView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *mainViewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *data = UIImagePNGRepresentation(mainViewImage);
// NEXT: blur image, and send to ProfileViewControoler
// UIImageView *backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"mainViewImage"]];
// [self.view addSubview:backgroundView];
}
- (IBAction)unwindToHome:(UIStoryboardSegue *)segue {
}
#end
Try something like that
#interface ViewController ()
#property(nonatomic, strong) UIImage *backgroundImage;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)profTap:(id)sender {
}
- (IBAction)unwindToHome:(UIStoryboardSegue *)segue {
self.backgroundImage = [self takeSnapShot];
[self performSegueWithIdentifier:#"nameofyoursegue" sender:nil];
}
//function to take a screenshot of your current controller
- (UIImage *)takeSnapShot {
// Create the image context
CGRect bounds = self.mainView.bounds;
UIGraphicsBeginImageContextWithOptions(bounds.size, NO,
self.view.window.screen.scale);
[self.navigationController.view drawViewHierarchyInRect:bounds
afterScreenUpdates:NO];
// Get the snapshot
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
// Be nice and clean your mess up
UIGraphicsEndImageContext();
return snapshotImage;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"nameofyoursegue"]) {
ProfileViewController *profileViewController =
[segue destinationViewController];
[profileViewController setBackgroundImage:self.backgroundImage];
}
}
#end
PhotoViewController
#interface ProfileViewController ()
#property(nonatomic, weak) IBOutlet UIImageView *backgroundImageView;
#property(nonatomic, strong) UIImage *backgroundImage;
#end
#implementation ProfileViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.backgroundImageView
setImage:self.backgroundImage];
}
#end
About the blur effect, I advice you to use FXBlurView in your ProfileViewController :
https://github.com/nicklockwood/FXBlurView

Make some calculation on Viewcontroller, need show the result to another Viewcontroller

I have an app, where I making some calculation, and need to transfer result of this calculation to ViewController3 and show the result there. Now I use label in same ViewController2 where I have calculation. Thank you for your help.
ViewController2.h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UILabel *gasPrice;
#property (weak, nonatomic) IBOutlet UILabel *gasCarMileage;
#property (weak, nonatomic) IBOutlet UITextField *perGalon;
#property (weak, nonatomic) IBOutlet UITextField *miles;
#property(nonatomic, copy, readonly) NSString *result;
- (IBAction)getIt:(id)sender;
#end
ViewController2.m
#import "ViewController2.h"
#import "ViewController3.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//Start calculation
- (IBAction)getIt:(id)sender; {
float perGalon = ([_perGalon.text floatValue]);
float miles = ([_miles.text floatValue]);
float mileCost = perGalon / miles;
[self performSegueWithIdentifier:#"viewController3" sender: nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"viewController3"]) {
ViewController3 *viewController3 = [segue destinationViewController];
viewController3.result = [[NSString alloc] initWithFormat: #"Every mile you drive
will cost you $ %f", mileCost];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.perGalon.delegate = self;
self.miles.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [textField resignFirstResponder];
}
#end
ViewController3.h
#import <UIKit/UIKit.h>
#interface ViewController3 : UIViewController
#property(nonatomic, copy) NSString *result;
#end
ViewController3.m
#import "ViewController3.h"
#import "ViewController2.h"
#interface ViewController3 ()
#end
#interface ViewController2 ()
#property(nonatomic, copy, readwrite) NSString *result;
#end
#implementation ViewController3
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You can define a string property in View controller 3 which you will set when you push view controller 3 from view controller 2.
ViewController3 interface declaration
#interface ViewController2 ()
#property(nonatomic, copy) NSString *result;
#end
In ViewController 2, you will implement this line at the last of your getIt() method.
[self performSegueWithIdentifier:#"viewController3" sender: nil]
And implement another method called prepareForSegue as follows
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"viewController3"]) {
ViewController3 *viewController3 = [segue destinationViewController];
viewController3.result = "YOUR CALCULATION RESULT HERE"
}
}
Bear in mind, you have to set identifier for view controller 3, go to storyboard and select the view for view controller 3 and On identify inspector, specified Storyboard ID as "viewController3".
Use a protocol,
In ViewController2.h
#protocol ViewController2Delegate;
#property (strong, nonatomic) id<ViewController2Delegate> delegate;
#protocol BexAPIClientDelegate <NSObject>
- (void)ViewController2:(ViewController2 *)vc didCalculateCost:(CGFloat)cost;
#end
Then at the end of the getIt() call the delegate
[self.delegate viewController2:self didCalculateCost:gasCostPerMile];
You need to set ViewController3 to be ViewController2's delegate when you load it. Also you will need to setup ViewController3 to conform to the protocol.
Using the protocol is worth the effort as it will make your code clear and easy to manage.
Retain a string in VC3. While initializing the VC3 object, set the value from VC2. Update the label in VC3(in viewDidLoad method)

trying to learn objective-c delegates. why wont my sample project work?

I am trying to pass data between two view controllers. viewcontroller2 is a delegate of viewcontroller.. note.. i called the delegate property "homie" yes I know this is bad practice but I am just messing around trying to understand the concept.
here is viewcontroller:
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate <NSObject>
#required
- (void)sendData:(NSString *)theString;
#end
#interface ViewController : UIViewController
#property (nonatomic, assign) id <ViewControllerDelegate> homie;
- (void)doSomething;
- (IBAction)doneText:(id)sender;
#end
implementation:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)doSomething{
}
- (IBAction)doneText:(id)sender {
UITextField *thisField = sender;
if([_homie respondsToSelector:#selector(sendData:)]){
[_homie sendData:[thisField text]];
}
}
now here is the other view controller implementing the first
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface ViewController2 : UIViewController <ViewControllerDelegate>
- (IBAction)hittingbtn:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *textfield;
#property (strong, nonatomic) ViewController *vc;
#end
implementation:
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// DELEGATE METHOD
- (void)sendData:(NSString *)theString{
[_textfield setText:theString];
}
- (IBAction)hittingbtn:(id)sender {
}
#end
in viewdidload I instantiate the first viewcontroller, and set myself as its delegate. im assuming then when that viewcontroller2 runs the code in its method then it will see if its delegate has implemented the delegate method and use that code.. what am i missing here?
Your problem is that you use ViewControllers wrong. You have initialized ViewController
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
And what next? You haven't assign it to your properties or something. What have you do? It's simple. You have to implement - (void)prepareForSegue:sender:. First of all in your storyboard set segue's identifier. Then do following.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
}
You need to set the delegate in prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setHomie)]) {
[segue.destinationViewController setHomie:self];
//or
if ([[segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
//or the segue identifier which has already been mentioned
}

Pass Value in iOS

I created two pages, called ViewController and SecViewController. In ViewController, which is the first page, with one button and one label. And I set segue on a button to SecViewController, which is the second page.
I am trying to pass the segue identifier to page 2, but this is not success. I test the value passing in page1, the console display
2013-07-05 10:33:54.554 Testing2[1314:c07] 1, (null)
Here is my code:
Anyone can identify which code I typing wrong?
ViewController.h
#import <UIKit/UIKit.h>
#class SecViewController;
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *label;
#property (strong, nonatomic) IBOutlet UIButton *button;
#property (strong, nonatomic) SecViewController *view2;
#end
ViewController.m
#import "ViewController.h"
#import "SecViewController.h"
#implementation ViewController
#synthesize label, button, view2;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"1"]){
view2.received = [segue identifier];
NSLog(#"%#, %#", [segue identifier], view2.received);
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[label setText:#"Game Start!"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SecViewController.h
#import <UIKit/UIKit.h>
#interface SecViewController : UIViewController
#property (strong, nonatomic) id received;
#property (strong, nonatomic) IBOutlet UILabel *label;
#end
SecViewController.m
#import "SecViewController.h"
#implementation SecViewController
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You don't have to create a property for the second view controller. You can get it in the prepareForSegue and access the received variable from the second view controller.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"1"]){
SecViewController *vc = [segue destinationViewController];
vc.received = [segue identifier];
NSLog(#"%#, %#", [segue identifier], vc.received);
}
}
if you nslog in the the secondviewcontroller for the value of the received what do you get?
#import "SecViewController.h"
#implementation SecViewController
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Received %#",self.received);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

Resources