After several attempts I do not succeed to understand were is the error and why the image doesn't appear... This is my code.
myProtocol.h
#import <Foundation/Foundation.h>
#protocol myProtocol <NSObject>
-(UIImage *)transferImage;
#end
ViewController.h
#import "SecondViewController.h"
#interface ViewController : UIViewController<myProtocol, UINavigationControllerDelegate>
{
UIView *view;
}
#property (nonatomic,retain) UIImageView *imageView;
- (IBAction)sendImage:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#import "myProtocol.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"VoodooVibeThumb#2x.png"]];
[view addSubview:_imageView];
NSLog(#"VoodooVibeThumb#2x.png");
}
-(UIImage *)transferImage
{
NSLog(#"VoodooVibeThumb#2x.png");
return _imageView.image;
}
- (IBAction)sendImage:(id)sender
{
SecondViewController *secClass = [[SecondViewController alloc] init];
[secClass setImageName:#"VoodooVibeThumb#2x.png"];
[self.navigationController pushViewController:secClass animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "myProtocol.h"
#import "ViewController.h"
#interface SecondViewController: UIViewController <myProtocol, UINavigationControllerDelegate>
{
UIView *secondView;
IBOutlet UIImageView *myImage;
id <myProtocol> myDelegate;
}
#property (nonatomic,retain) UIImageView *myImage;
#property (nonatomic,retain) UIImage *transferImage;
#property(nonatomic,assign) id delegate;
#property (strong, nonatomic)NSString *imageName;
-(void)callTransfer;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "ViewController.h"
#import "myProtocol.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize delegate, myImage, transferImage;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[myImage setImage:[UIImage imageNamed:_imageName]];
UIImageView * myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:_imageName]];
[secondView addSubview:myImage];
}
-(void)callTransfer
{
myImage.image=[delegate performSelector:#selector(transferImage)];
myImage.image=[UIImage imageNamed:#"VoodooVibeThumb#2x.png"];
NSLog(#"%#",myImage.image);
NSLog(#"I am in call transfer");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
It appears that you are not initializing the myImage subview before adding it in the viewDidLoad method of SecondViewController.
Try removing:
[secondView addSubview:myImage];
from viewDidLoad, and add the following to viewWillAppear:
UIImageView * myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:_imageName]];
just before:
[secondView addSubview:myImage];
There may be a better way of doing this, but this might get you headed in the right direction.
[secondView addSubview:myImage];
Error: Local declaration of 'myImage' hidesistance variable.
Use this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
myImage = [[UIImageView alloc] initWithImage[UIImage imageNamed:_imageName]];
[secondView addSubview:myImage];
}
I presume you've got a variable in your interface (either in .h or .m) called myImage so when you then create the local instance of myImage (UIImageView *myImage), XCode is getting confused. As it was declared latest (no reference, sorry) it is using the local declaration, but it is aware that there is an instance variable using the same name that can't be accessed. You instead want to save straight to the instance variable by removing the UIImageView * from your method
Hope this makes sense!
Matt
Related
I have Xib UIView which is being displayed by my ViewController. The Xib contains an UILabel and an UIButton. My button coats all over my xib and i'm using it to navigate my SecondViewController and i achieve this by delegate methods.
Here's the thing about my label; because my button is transparent, i can show it beneath the button. What i can't do is to change mylabel's text from ViewController.
I did some search and come across a suggestion like this:
is create another .nib file for the subview and put the subview in
there. Then in that .nib file, make the file owner IOSubview. Property
connections will work just fine there. Then just add the subview to
your IOViewController programatically. Just remember to load the nib
file from bundle first.
link : https://stackoverflow.com/a/20294118/1450201
But it doesn't make sense to me because the reason i created the xib at first is to use it more than once. I believe solution to this problem could be much simpler. But how??
This is what my xib looks like:
And here is a github repo link and my code:
https://github.com/TimurAykutYildirim/demoView
ViewController.h
#import <UIKit/UIKit.h>
#import "Mini.h"
#interface ViewController : UIViewController <SelectionProtocol>
#property (weak, nonatomic) IBOutlet Mini *miniView;
#property (weak, nonatomic) IBOutlet UILabel *miniLabel;
#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.
self.miniView.delegate = self;
}
-(void) isClicked {
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Mini.h
#import <UIKit/UIKit.h>
#protocol SelectionProtocol;
#interface Mini : UIView
#property (nonatomic, weak) id<SelectionProtocol> delegate;
- (IBAction)btnClick:(id)sender;
#end
#protocol SelectionProtocol <NSObject>
#required
-(void) isClicked;
#end
Mini.m
#import "Mini.h"
#implementation Mini
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self load];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self load];
}
return self;
}
- (void)load {
UIView *view = [[[NSBundle bundleForClass:[self class]] loadNibNamed:#"Mini" owner:self options:nil] firstObject];
[self addSubview:view];
view.frame = self.bounds;
// ui component properties will be set here
}
- (IBAction)btnClick:(id)sender {
if ([self.delegate conformsToProtocol:#protocol(SelectionProtocol)]) {
[self.delegate isClicked];
}
}
#end
Update your Mini.h to add label outlet to it.
Mini.h
#import <UIKit/UIKit.h>
#protocol SelectionProtocol;
#interface Mini : UIView
#property (nonatomic, weak) id<SelectionProtocol> delegate;
#property (weak, nonatomic) IBOutlet UILabel *miniLabel;
- (IBAction)btnClick:(id)sender;
#end
#protocol SelectionProtocol <NSObject>
#required
-(void) isClicked;
#end
and in ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.miniView.delegate = self;
self.miniView.miniLabel.text = //set whatever value
}
How do I access IBOutlets that have been created in another class?
here is my code...
Class one
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (retain, readwrite) IBOutlet UIView *myView;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myView;
- (void)viewDidLoad {
[super viewDidLoad];
}
#end
Class two
.h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController
- (IBAction)accion:(id)sender;
- (IBAction)btnBack:(id)sender;
#end
.m
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)accion:(id)sender {
ViewController *a = [ViewController new];
UIView *someView = [a myView];
[someView setBackgroundColor:[UIColor redColor]];
}
- (IBAction)btnBack:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
why not works? no change the backgroundColor when return on my view
I think you try to delegate pattern to set the values Viewcontroller2.h file
Add protocol like this...
#import <UIKit/UIKit.h>
#protocol tutorialDelegate <NSObject> //set protocol
-(void)delegatesDescribedWithDescription;
#end
#interface ViewController2 : UIViewController
#property (weak, nonatomic) id<tutorialDelegate> tutorialDelegate1;
- (IBAction)accion:(id)sender;
- (IBAction)btnBack:(id)sender;
#end
after the declaring protocol in viewcontroller2.m file first synthesize and call method like this..
#import "ViewController.h"
#interface ViewController2 ()
#end
#implementation ViewController2
#synthesize tutorialDelegate1; // synthesize here
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)accion:(id)sender {
ViewController *a = [ViewController new];
UIView *someView = [a myView];
[someView setBackgroundColor:[UIColor redColor]];
}
- (IBAction)btnBack:(id)sender {
// Here we tell delegate to invoke method in parent view.
[self.tutorialDelegate1 delegatesDescribedWithDescription
];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
and finally we implement this method in view controller.m file but first set delegate in viewcotroller.h file like this...
#import <UIKit/UIKit.h>
#import "ViewController2.h" //import here
#interface ViewController : UIViewController <tutorialDelegate> //set delegate
#property (retain, readwrite) IBOutlet UIView *myView;
#end
and viewcontroller.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myView;
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"yourIdentifier"]) {
ViewController2 *detailViewController =
segue.destinationViewController;
// here we set the ViewController to be delegate in
// detailViewController
detailViewController.tutorialDelegate1 = self;
}
}
// ViewController must implement tutorialDelegate's methods
// because we specified that ViewController will conform to
// tutorialDelegate protocol
-(void)delegatesDescribedWithDescription
{ // here your code please
viewTemp.backgroundColor =[UIColor redColor];
}
#end
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)
How to show an UIIimage by clicking on an UIButton inside another UIViewController? I would like to add to the same UIButton the command to add an image to the SecondViewController. Excused my poor question.
myProtocol.h
#import <Foundation/Foundation.h>
#protocol myProtocol <NSObject>
-(UIImage *)transferImage;
#end
ViewController.h
#import "SecondClass.h"
#interface ViewController : UIViewController<myProtocol, UINavigationControllerDelegate>{
UIView *view;
}
#property (nonatomic,retain) UIImageView *imageView;
- (IBAction)sendImage:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#import "myProtocol.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad{
[super viewDidLoad];
_imageView = [[UIImageView alloc]initWithImage:
[UIImage imageNamed:#"VoodooVibe#2x.png"]];
[view addSubview:_imageView];
NSLog(#"I am in VC.m");
}
-(UIImage *)transferImage{
NSLog(#"I am in transferImage");
return _imageView.image;
}
- (IBAction)sendImage:(id)sender {
SecondViewController *secClass = [[SecondViewController alloc]init];
secClass.delegate=self;
[secClass callTransfer];
NSLog(#"I am in sender");
[self.navigationController pushViewController:secClass animated:YES];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "myProtocol.h"
#import "ViewController.h"
#interface SecondViewController :UIViewController
<myProtocol,UINavigationControllerDelegate> {
UIView *secondView;
IBOutlet UIImageView *myImage;
id <myProtocol> myDelegate;
}
#property (nonatomic,retain) UIImageView *myImage;
#property(nonatomic,assign) id delegate;
-(void)callTransfer;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "ViewController.h"
#import "myProtocol.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize delegate,myImage;
- (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.
[secondView addSubview:myImage];
}
-(void)callTransfer{
myImage.image=[delegate performSelector:#selector(transferImage)];
myImage.image=[UIImage imageNamed:#"VoodooVibe#2x.png"];
NSLog(#"%#",myImage.image);
NSLog(#"I am in call transfer");
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Delegates should normally be used, if you you have a class included inside your UIViewController which will do something and notify you with the delegate method when the specific process has finished. But in this case you would set an UIImage two times. Once by your delegate and a second time by setting an UIImage programmatically.
You shouldn't do anything like calling a method for initializing the UIImage of the second UIViewController from outside. Just call everything inside viewDidLoad and you don't have to care about it, because the UIViewController handles it itself.
You just have to insert an UIImageView inside your SecondViewController and connect it to your header file. then you can access it inside the m. file. I had the problem that I first used a jpg instead of a png, but after changing the suffix everything worked fine.
ViewController.m
- (IBAction)sendImage:(id)sender {
SecondViewController *secClass = [[SecondViewController alloc] init];
[secClass setImageName:#"pic.png"];
[self.navigationController pushViewController:secClass
animated:YES];
}
SecondViewController.h
#interface SecondViewController : UIViewController
#property (strong, nonatomic)NSString *imageName;
#property (weak, nonatomic) IBOutlet UIImageView *myImage;
#end
SecondViewController.m (There are just these two lines)
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[_myImage setImage:[UIImage imageNamed:_imageName]];
}
I'm trying to figure out delegates because I really need them for a project I'm working on, but for the life of me, I can't figure them out. No matter how much I tweak the code, nothing works
ViewController.h:
#import <UIKit/UIKit.h>
#class ViewController;
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
- (IBAction)button:(id)sender;
#property (weak, nonatomic)id <testDelegate> delegate;
#end
ViewController.m:
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
DelegateController *dc = [[DelegateController alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button:(id)sender {
[self.delegate sayHi];
}
#end
DelegateController.h:
#import "ViewController.h"
#interface DelegateController : UIViewController <testDelegate>
#end
DelegateController.m:
#import "DelegateController.h"
#interface DelegateController ()
#end
#implementation DelegateController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(#"init");
ViewController *vc = [[ViewController alloc] init];
[vc setDelegate:self];
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
-(void)sayHi
{
NSLog(#"hi");
}
#end
The - (IBAction)button:(id)sender method is connect to a button, but when clicked I get no output. What am I doing wrong?
ViewController.h:
#import <UIKit/UIKit.h>
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
#end
ViewController.m:
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController () <testDelegate>
#end
#implementation ViewController
- (IBAction)pushNewViewController:(id)sender
{
DelegateController *dc = [[DelegateController alloc] init];
dc.delegate = self;
[self.navigationController pushViewController:dc animated:YES];
}
- (void)sayHi
{
NSLog(#"It works!");
}
#end
DelegateController.h:
#import "ViewController.h"
#interface DelegateController : UIViewController
#property (weak, nonatomic) id<testDelegate> delegate;
#end
DelegateController.m:
#import "DelegateController.h"
#implementation DelegateController
- (IBAction)button:(id)sender
{
if([_delegate respondsToSelector:#selector(sayHi)]) {
[_delegate performSelector:#selector(sayHi)];
}
}
#end
Try this:
ViewController.h
#import <UIKit/UIKit.h>
#class ViewController;
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
- (IBAction)button:(id)sender;
#property (weak, nonatomic)id <testDelegate> delegate;
#end
ViewController.m
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController ()
#property (nonatomic, strong) DelegateController *dc;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_dc = [[DelegateController alloc] init];
[self setDelegate:_dc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button:(id)sender
{
[self.delegate sayHi];
}
#end
DelegateController.h
#interface DelegateController : UIViewController <testDelegate>
#end
DelegateController.m
#import "DelegateController.h"
#interface DelegateController ()
#end
#implementation DelegateController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
NSLog(#"init");
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
-(void)sayHi
{
NSLog(#"hi");
}
#end
Your problem is that ViewController creates DelegateController, then in DelegateController you're creating a new, different, instance of ViewController, and setting yourself as the delegate of that instance. Normally, the way you set a delegate is that DelegateController would create an instance of ViewController and set itself as the delegate. This assumes that DelegateController is created first, but exactly how to do this depends on your app structure, and how you move from controller to controller.
Replace you button Click method with following
- (IBAction)button:(id)sender {
// Check whether your Delegate method is implemeted or not
if([delegate respondsToSelector:#selector(sayHi)])
{
// Call Delegate Method
[delegate performSelector:#selector(sayHi)];
}
}