Property implementation error - ios

Im following this tutorial:
http://www.raywenderlich.com/1845/ios-tutorial-how-to-create-a-simple-iphone-app-tutorial-part-2
I get the following errors:
1.Property implementation must have its declaration in interface "RWTDetailViewController"
2.Property "data" not found on object of type "id"
Here is my code:
#import "RWTScaryBugDoc.h"
#import "RWTScaryBugData.h"
#import "RWTUIImageExtras.h"
#import "RWTDetailViewController.h"
#interface RWTDetailViewController ()
- (void)configureView;
#end
#implementation RWTDetailViewController
#pragma mark - Managing the detail item
#synthesize picker = _picker;
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
self.rateView.notSelectedImage = [UIImage imageNamed:#"shockedface2_empty.png"];
self.rateView.halfSelectedImage = [UIImage imageNamed:#"shockedface2_half.png"];
self.rateView.fullSelectedImage = [UIImage imageNamed:#"shockedface2_full.png"];
self.rateView.editable = YES;
self.rateView.maxRating = 5;
self.rateView.delegate = self;
if (self.detailItem) {
self.titleField.text = self.detailItem.data.title;
self.rateView.rating = self.detailItem.data.rating;
self.imageView.image = self.detailItem.fullImage;
}
}
- (IBAction)titleFieldTextChanged:(id)sender
{
self.detailItem.data.title = self.titleField.text;
}
#pragma mark UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
#pragma mark RWTRateViewDelegate
- (void)rateView:(RWTRateView *)rateView ratingDidChange:(float)rating
{
self.detailItem.data.rating = rating;
}
- (IBAction)addPictureTapped:(id)sender {
if (self.picker == nil) {
self.picker = [[UIImagePickerController alloc] init];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker.allowsEditing = NO;
}
[self presentViewController:_picker animated:YES completion:nil];
}
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:nil];
UIImage *fullImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
UIImage *thumbImage = [fullImage imageByScalingAndCroppingForSize:CGSizeMake(44, 44)];
self.detailItem.fullImage = fullImage;
self.detailItem.thumbImage = thumbImage;
self.imageView.image = fullImage;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (BOOL)shouldAutorotateToInterfaceOrientation
{
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
When I move my #synthesize into the interface-declaration, I the the following error: "Illegal interface qualifier"
Can anyone help me?
Here is my .h-file:
#import <UIKit/UIKit.h>
#import "RWTRateView.h"
#interface RWTDetailViewController : UIViewController <UITextFieldDelegate, RWTRateViewDelegate, UIImagePickerControllerDelegate, UINavigationBarDelegate>
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet RWTRateView *rateView;
#property (weak, nonatomic) IBOutlet UITextField *titleField;
#property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#property (strong, nonatomic) UIImagePickerController *picker;
- (IBAction)addPictureTapped:(id)sender;
- (IBAction)titleFieldTextChanged:(id)sender;
#end

Error description is self explanatory, you need to declare picker as a property in interface(.h) file before you move to implementation(.m) file and synthesize it. However you don't need to synthesize properties anymore but if you do that is also fine.
One more thing, you missed the part from tutorial in which writer has declared this property in .h file already. You can have a look again or add this line to RWTDetailViewController.h
#property (strong, nonatomic) UIImagePickerController *picker;
EDIT
For second error you are declaring detailItem as an object of type id, however writer is using a custom class RWTScaryBugDoc in which he should be having a property named data. That's why you are getting the error as property data doesn't belong to id type. You may want to download the sample code at the end of tutorial and cross check the missing points.

You just need to declare your property first. So in the interface (h file or top of your m file), add:
#property (nonatomic, strong)UIImagePickerController *picker;
The #synthetise need to stay in the implementation.

You declare self.detailItem as Id. Id is no class and so it has no attribute, but you try to access self.detailItem.data.... This is not possible.
I can't help you to fix this, because there are so many logical erros in your code, that 99% of it makes no sense for me.

Related

UITapGestureRecognizer for image picker not working

Trying to create an image picker with a tap gesture, so when the default picture is tapped it allows the user to pick an image from the device's photo library. For some reason when I click the view in the iOS simulator it simply doesn't do anything and I can't figure out why.
This is what I have so far. I'm pretty new to Objective-C
ViewController.m :
#import "ViewController.h"
interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *nameField;
#property (weak, nonatomic) IBOutlet UITextField *brandField;
#property (weak, nonatomic) IBOutlet UITextField *priceField;
#property (weak, nonatomic) IBOutlet UITextField *additionalNotesField;
#property (weak, nonatomic) IBOutlet UIButton *addItem;
#property (weak, nonatomic) IBOutlet UIButton *cancelAdditem;
#property (weak, nonatomic) IBOutlet UIImageView *toyImage;
- (IBAction)imageSelect:(UITapGestureRecognizer *)sender;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_nameField.delegate = self;
_brandField.delegate = self;
_priceField.delegate = self;
_additionalNotesField.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
-(BOOL) textFieldShouldReturn:(UITextField *) textField {
textField.resignFirstResponder;
return true;
}
-(void) textFieldDidEndEditing:( UITextField *) textField {
_nameField.text = textField.text;
_brandField.text = textField.text;
_priceField.text = textField.text;
_additionalNotesField.text = textField.text;
}
- (IBAction)imageSelect:(UITapGestureRecognizer *)sender {
// Hide the keyboard
_nameField.resignFirstResponder;
_brandField.resignFirstResponder;
_priceField.resignFirstResponder;
UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init]; // Creates image picker
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; // Source for picker is saved photos. Only allow photos to be picked, not taken
// Make sure the picker is notified when the user picks an image
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:true completion:nil];
}
// UIImagePickerControllerDelegete
-(void) imagePickerDidCancel:(UIImagePickerController *) imagePicker {
[self dismissViewControllerAnimated:true completion:nil]; // Dimiss the picker if the user canceled
}
-(void) imagePicker:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage* selectedImage = info[UIImagePickerControllerOriginalImage];
_toyImage.image = selectedImage; // Set the image view to display the selected image
// Dimiss the picker
[self dismissViewControllerAnimated:true completion:nil];
}
#end
As Larme said, I needed to add this line:
_toyImage.userInteractionEnabled = YES;

How do i pass an UIImageView between view controllers?

I'm trying to choose an image from the camera roll in a view controller and then pass it/show that image in another view controller. Why doesn't the image view get passed?
When landing on FirstViewController i have a segue in the navigation bar to the SecondViewController.
//FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#end
//FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
#interface FirstViewController () <SeconViewControllerDelegate>
#end
#implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - SecondViewControllerDelegate
- (void)didDismissWithImageView:(UIImageView *)imageView
{
self.imageView = imageView;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"addPhoto"]) {
SecondViewController *secondVC = segue.destinationViewController;
secondVC.delegate = self;
}
}
#end
//SecondViewController.h
#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>
#protocol PhotoPickerDelegate <NSObject>
- (void)didDismissWithImageView:(UIImageView *)imageView;
#end
#interface SecondViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (weak, nonatomic) id<PhotoPickerDelegate> delegate;
#property (strong, nonatomic) UIImageView *imageView;
- (IBAction)useCameraRoll:(id)sender;
#end
//SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)useCameraRoll:(id)sender
{
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeSavedPhotosAlbum]){
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = #[(NSString *) kUTTypeImage];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
#pragma mark - UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
[self dismissViewControllerAnimated:YES completion:nil];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
UIImage *image = info[UIImagePickerControllerOriginalImage];
_imageView.image = image;
}
if ([self.delegate respondsToSelector:#selector(didDismissWithImageView:)]) {
[self.delegate didDismissWithImageView:_imageView];
}
[self.navigationController popViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
If its just an image we are talking about here then lets make a property for the image.
#property (nonatomic, strong) UIImage *imageIWant;
Once we have our image property, we can set the image that you want by either calling [UIImage imageWithData:imageData]; or set it from a file within our Plist. I do not recommend saving an imageView and passing that view among controllers because within our MVC model, the view and the model are separate. At the end of the day, its an image within the model that you want not a view element.

Displaying image in a new view controllers UIImageView

I'll post my code first and then I'll explain the problem
RootViewController.h its called SpViewController.h
#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import "secondViewController.h"
#interface spViewController : UIViewController
<UIImagePickerControllerDelegate,
UINavigationControllerDelegate>
#property BOOL newMedia;
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (strong, nonatomic) spViewController *secondViewController;
#property (strong, nonatomic) UIImageView *image;
#property (strong, nonatomic) UIImage *myImage;
- (IBAction)useCamera:(id)sender;
- (IBAction)useCameraRoll:(id)sender;
#end
spViewController.m
#import "spViewController.h"
#import "secondViewController.h"
#interface spViewController ()
#end
#implementation spViewController
- (IBAction)backtohome:(UIStoryboardSegue *)unwindSegue
{
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)useCamera:(id)sender {
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = #[(NSString *) kUTTypeImage];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker
animated:YES completion:nil];
_newMedia = YES;
}
}
- (IBAction)useCameraRoll:(id)sender {
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = #[(NSString *) kUTTypeImage];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker
animated:YES completion:nil];
_newMedia = NO;
}
}
//image picker delegate
-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *chosenImage = info[UIImagePickerControllerEditedImage]; self.myImage = chosenImage;
NSString *mediaType = info[UIImagePickerControllerMediaType];
[self performSelector:#selector(myMethod:) withObject:info afterDelay:0.1];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
UIImage *image = info[UIImagePickerControllerOriginalImage];
_imageView.image = image;
if (_newMedia)
UIImageWriteToSavedPhotosAlbum(image,
self,
#selector(image:finishedSavingWithError:contextInfo:),
nil);
}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
}
}
-(void)myMethod:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"Perform segue");
[self performSegueWithIdentifier:#"Picture Unwind Segue" sender:self];
}];
}
-(void)image:(UIImage *)image
finishedSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
if (error) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Save failed"
message: #"Failed to save image"
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
//cancel delegate
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier]isEqualToString:#"Picture Unwind Segue"]) {
secondViewController *destinationViewController = [segue destinationViewController];
destinationViewController.imageView.image = self.myImage;
}
}
#end
secondViewController.h
#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import "spViewController.h"
#interface secondViewController : UIViewController
<UIImagePickerControllerDelegate,
UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (strong, nonatomic) UIImage *myImage;
#property (strong, nonatomic) UIImageView *image;
#end
secondViewController.m
#import "secondViewController.h"
#import "spViewController.h"
#interface secondViewController ()
#end
#implementation secondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
self.imageView.image = self.myImage;
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
So the problem I'm having is, I can't get the image that has just been selected in the UIImagePickerController to be displayed in the UIImageView, my ImagePickerController was initiated by a button in my previous view controller "spViewController" (rootViewController) I am using Storyboards, I thought if I put in the UIImageView then connected it using an outlet reference it would display there, this doesn't seem to be the case though. If I put the UIImageView in the first view controller and do the same it will display the image but thats not where I want it to go.
Thank you for any help
To fix my problem i decided to save the image and call on it later heres the code i put into my secondViewController.m
{NSString *docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filepathJPG = [docsPath stringByAppendingPathComponent:#"imagefile.jpg"];
UIImage *img = [UIImage imageWithContentsOfFile: filepathJPG];
if (img != nil) {
// assign the image to the imageview,
_imageView.image = img;
// Optionally adjust the size
BOOL adjustToSmallSize = YES;
CGRect smallSize = (CGRect){0,0,100,100};
if (adjustToSmallSize) {
_imageView.bounds = smallSize;
}
}
I hope this can help others that have the same problem.
So according to your code , you are setting the property of myImage which is an instance of UIImage from the RootViewController.
so your just passing the data of the image , But your not setting your imageView.image property to the passed image value.
So a possible fix would be to set
imageView.image = myImage in viewDidLoad
or
you can directly access the imageView property from the perform prepare for segue method in the RootViewController and set its image property.
I hope this helps .
Cheers
You can declare a property in AppDelegate class and access it across all controllers using appdelegate shared instance

Set Text of an UILabel after dismissViewController in other Class

I haven't found a similar question that could answer my question.
My Question is: Why can't I access a UILabel from another class after the dissmissViewController?
Here is my Code:
ClassA.h:
#interface ClassA : UIViewController {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
ClassA.m:
shouldPerformSegue, prepareForSegue and statusBarStyle Methods
ClassB.h:
- (IBAction)dismiss;
ClassB.m:
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
ClassA *login = [[ClassA alloc] init];
[[login ErrorLabel] setText:#"Please use login."];
[[login acIn1] stopAnimating];
[[login acIn1] setHidesWhenStopped:YES];
[[login acIn1] setHidden:YES];
}];
}
Here is my Code I really hope somebody can help me: I AM ABOUT TO GIVE UP I DON'T KNOW WHY THIS WON'T WORK!
Thanks for your help.
~Markus
Edit1:
I have a ViewController ClassA that contains two text fields and when you click on login you come to a TabBarController where one tab contains the ClassB ViewController and in the ClassB ViewController there is a logout button --> dismiss and when you click this button you should come to the ClassA ViewController AND the ErrorLabel Text should change.
Complete Class: A --> LoginViewControler.h
#import <UIKit/UIKit.h>
#import "ShowProfileViewController.h"
#interface LoginViewController : UIViewController <ShowProfileViewControllerDelegate> {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
#property (weak, nonatomic) IBOutlet UITextField *passwordTextField;
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
#end
Complete Class: A --> LoginViewController.m
#import "LoginViewController.h"
#import "NewsNavigationController.h"
#import "TabViewController.h"
#interface LoginViewController () <UITextFieldDelegate>
#end
#implementation LoginViewController
#synthesize usernameTextField;
#synthesize passwordTextField;
#synthesize ErrorLabel;
#synthesize acIn1;
- (void)viewDidLoad
{
[super viewDidLoad];
[usernameTextField setDelegate:self];
[passwordTextField setDelegate:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if([identifier isEqualToString:#"login"])
{
[acIn1 startAnimating];
[acIn1 setHidden:NO];
if([self login]){
return YES;
} else {
[self showErrorMessage:#"Data not correct!"];
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
return NO;
}
}
else {
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
return NO;
}
}
- (void)showErrorMessage:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
- (BOOL)login
{
NSString *usernameS = usernameTextField.text;
NSString *passwordS = passwordTextField.text;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://localhost:8888/login.php?username=%#&password=%#", usernameS, passwordS]]];
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *loginDic = [jsonDictionary objectForKey:#"login"];
NSString *ErrorString = [loginDic objectForKey:#"returnString"];
NSLog(#"[+] Login: %#", ErrorString);
if ([ErrorString isEqualToString:#"Success"]){
ErrorLabel.text = #"Login";
return YES;
}
else {
ErrorLabel.text = ErrorString;
return NO;
}
}
- (void)didDismissViewController
{
[ErrorLabel setText:#"Bitte benutzen Sie den Login."];
[acIn1 stopAnimating];
[acIn1 setHidesWhenStopped:YES];
[acIn1 setHidden:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)inSegue sender:(id)inSender
{
if([inSegue.identifier isEqualToString:#"login"])
{
ShowProfileViewController *vc = [[ShowProfileViewController alloc] init];
vc.delegate = self;
TabViewController *tabViewController = inSegue.destinationViewController;
NewsNavigationController *theController = [[tabViewController viewControllers] objectAtIndex:0];
[self presentViewController:vc animated:YES completion:nil];
}
}
#end
Complete Class: B --> ShowProfileViewController.h
#import <UIKit/UIKit.h>
#protocol ShowProfileViewControllerDelegate
- (void)didDismissViewController;
#end
#interface ShowProfileViewController : UIViewController
#property (nonatomic, assign) id<ShowProfileViewControllerDelegate> delegate;
- (IBAction)dismiss;
#end
Complete Class: B --> ShowProfileViewController.m
#import "ShowProfileViewController.h"
#import "LoginViewController.h"
#interface ShowProfileViewController ()
#end
#implementation ShowProfileViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
- (void)viewWillAppear:(BOOL)inAnimated
{
[super viewWillAppear:inAnimated];
}
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController];
}];
}
#end
This doesn't work because inside your completion block, you're creating a new instance of your LoginViewController, and setting its text. What you should be actually doing is setting the text of the existing LoginViewController, that should appear after dismissing ShowProfileViewController
In order to achieve your desired behaviour, you can use the delegation pattern. If you're not familiar with this technique, it'd be very important to learn. It's is used all over the place in iOS and Mac OS X development.
The code below might require some tweaking on your side.
In ShowProfileViewController.h, add before #interface:
#protocol ShowProfileViewControllerDelegate
- (void)didDismissViewController
#end
Also, add the following property declaration to ShowProfileViewController:
#property (nonatomic, assign) id<ShowProfileViewControllerDelegate> delegate;
Then, change LoginViewController.h so it looks like
#import "ShowProfileViewController.h"
#interface LoginViewController : UIViewController <ShowProfileViewControllerDelegate> {
UILabel *_ErrorLabel;
UIActivityIndicatorView *_acIn1;
}
#property (weak, nonatomic) IBOutlet UILabel *ErrorLabel;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *acIn1;
Now, in ShowProfileViewController.m, replace the code in the dismiss method so it looks like the following:
- (IBAction)dismiss
{
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController];
}];
}
In LoginViewController.m, add the following method:
- (void)didDismissViewController
{
[[self ErrorLabel] setText:#"Please use login."];
[[self acIn1] stopAnimating];
[[self acIn1] setHidesWhenStopped:YES];
[[self acIn1] setHidden:YES];
}
And finally, you need to set the delegate property in you ShowProfileViewController to point to the LoginViewController instance. Find in LoginViewController.m in which part of your code you create and present the ShowProfileViewController View Controller and set the delegate property to self. If you're using storyboards, you should do it inside prepareForSegue:.
ClassA *login = [[ClassA alloc] init];
is creating a completly new instance.Not the one you used for coming to class B

Xcode thinks delegate method is actually a new method being declared

I just created a new utility application from the Xcode templates and I have a problem with the - (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller method not being called. When I use the three finger tap on the trackpad to define it, it says that method is defined in MainViewController.m when it is definitely in the protocol of Flip.
MainVC.h
#import "FlipsideViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate, UIPopoverControllerDelegate>
#property (strong, nonatomic) UIPopoverController *flipsidePopoverController;
#property (weak, nonatomic) IBOutlet UIView *backgroundView;
#end
.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background.jpg"]];
_backgroundView.contentMode = UIViewContentModeCenter;
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View Controller
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
//width
if (controller.widthSegmentedControl.selectedSegmentIndex == 0) {
//number of icons
} else {
//icon space
}
NSLog(#"b"); // not called
[self.flipsidePopoverController dismissPopoverAnimated:YES];
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
self.flipsidePopoverController = nil;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showAlternate"]) {
[[segue destinationViewController] setDelegate:self];
UIPopoverController *popoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
self.flipsidePopoverController = popoverController;
self.flipsidePopoverController.delegate = self;
}
}
- (IBAction)togglePopover:(id)sender
{
if (self.flipsidePopoverController) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
self.flipsidePopoverController = nil;
} else {
[self performSegueWithIdentifier:#"showAlternate" sender:sender];
}
}
#end
FlipVC.h
#import <UIKit/UIKit.h>
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISegmentedControl *widthSegmentedControl;
#property (weak, nonatomic) IBOutlet UITextField *widthNumberOfIcons;
#property (weak, nonatomic) IBOutlet UITextField *widthIconSpace;
#property (weak, nonatomic) IBOutlet UISegmentedControl *heightSegmentedControl;
#property (weak, nonatomic) IBOutlet UITextField *heightNumberOfIcons;
#property (weak, nonatomic) IBOutlet UITextField *heightIconSpace;
#property (weak, nonatomic) id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
#end
.m
#import "FlipsideViewController.h"
#interface FlipsideViewController ()
#end
#implementation FlipsideViewController
- (void)awakeFromNib
{
self.preferredContentSize = CGSizeMake(320.0, 480.0);
[super awakeFromNib];
}
- (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.
}
#pragma mark - Actions
- (IBAction)done:(id)sender
{
NSLog(#"a"); //this is called
[self.delegate flipsideViewControllerDidFinish:self];
}
#end
There are two NSLogs in there, one for the method where the done button gets pressed (a) and one for the one where that didFinish method should be called (b). The problem is that when I press the done button on the Flip controller nothing happens (although "a" gets logged).
I found the problem. I removed the default button bar Info item and replace it with a normal button. The problem is that the segue needs to be anchored to that button and connected to the togglePopover method in the MainViewController.m file.

Resources