Objective C: "Property implementation must have its declaration in interface" - objective-c

I have the following code:
//RootViewController.h:
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController{
IBOutlet UITextField *login_uname;
IBOutlet UITextField *login_pword;
IBOutlet UIActivityIndicatorView *login_thinger;
IBOutlet UIImageView *logo;
IBOutlet UISwitch *login_remember;
IBOutlet UIScrollView *scrollView;
}
-(IBAction) login_submitClick:(id)sender;
-(IBAction) doneEditing:(id)sender;
-(IBAction) clearPword:(id)sender;
-(void) showSignUp:(id)sender;
-(void)doLogout:(id)sender;
//for file handling:
-(NSString *)documentsPath;
-(NSString *)readFromFile:(NSString *)filePath;
-(void) writeToFile:(NSString *)text withFileName:(NSString *) filePath;
#end
//RootViewController.m
#import "RootViewController.h"
//#import "Main.h"
//#import "SignUp.h"
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "CommonCrypto/CommonHMAC.h"
#import "Details.h"
//#import "signUpSMS.h"
#import "JSON.h"
#implementation PrestoCab3ViewController
#synthesize login_uname; //this line throws the error in the title
...
I'm using XCode 4.1 and was wondering if someone could please help me get to the bottom of this error. I'm very new to XCode.
Many thanks in advance,

You need to declare the property with #property in your interface.
#property( nonatomic, retain ) IBOutlet UITextField * login_uname;
Here, non-atomic is used because it's an IBOutlet.
Also note the property has the retain modifier, meaning you are responsible to release the object when you don't need it anymore.

Related

push segue causing break point

hoepfully a simple fix. :)
I'm using a collection view with a push segue to a detailed view controller. When the cell is clicked in simulator the app crashes with a break point indicating at this part of the code:
#import "DetailViewController.h"
#interface DetailViewController ()
#property (nonatomic, weak) IBOutlet UIImageView *imageView;
#end
#implementation DetailViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated]; //<--------- break point
self.imageView.image = self.image;
}
#end
segue id etc is correct. So not at all sure why it shouldn't be working.
Any help on this as always is appreciated. If you need further info let me know.
A.
edit:
.h file as follows:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (nonatomic, strong) UIImage *image;
#end

Setting up the App Delegate to Manage Data

I'm working on an app with a Split View controller and would like to store the main data class in the App Delegate so I can access it from multiple views (MasterView, DetailView, and several PopUps).
I'm a bit of a noob and can't figure out why Im getting the error:
AppDelegate.m:31:26: Property 'dataController' not found on object of type 'MasterViewController'
Below is the relevant code - any help is much appreciated. Thanks.
AppDelegate.h
#import <UIKit/UIKit.h>
#class EventClassDataController;
#class MasterViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
#import <UIKit/UIKit.h>
#class EventClassDataController;
#class MasterViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
MasterViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#class EventClassDataController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) EventClassDataController *dataController;
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
MasterViewController.m
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "EventClassDataController.h"
#import "EventClass.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
#synthesize detailViewController, dataController;
- (void)awakeFromNib
{
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
[super awakeFromNib];
// Initialize event data
self.dataController = [[EventClassDataController alloc] init];
}
EventClassDataController.h
#import <Foundation/Foundation.h>
#class EventClass;
#interface EventClassDataController : NSObject
#property (nonatomic, copy) NSMutableArray *masterEventList;
-(NSUInteger)countOfList;
-(EventClass *)objectInListAtIndex:(NSUInteger)theIndex;
-(void)addNewEvent:(EventClass *)event;
-(void)removeEvent:(EventClass *)event;
#end
You need to add
#import "MasterViewController.h"
to AppDelegate.m.
Explantation:
From your error message I can tell that you're trying to access a property of MasterViewController on line 26 of your AppDelegate. However, in your AppDelegate class you only have a forward declaration ("#class MasterViewController") and you don't include the actual header file for MasterViewController. What this means is that AppDelegate knows there exists a class named MasterViewController somewhere in your project... but that's all it knows. AppDelegate doesn't know anything about the contents of MasterViewController, i.e. properties or methods MasterViewController declares.
The reason to use #class in a header file is so that you can have properties in an #interface such as
#property (nonatomic, strong) MasterViewController * appDelegatesReferenceToMasterViewController;
without having to import MasterViewController.h in AppDelegate.h. This way, other files in your project can import AppDelegate.h without also inadvertently importing MasterViewController.h.
Translation:
You writing the code:
#class MasterViewController;
is like saying to the compiler:
Yo... compiler. I'm going to be talking about something called MasterViewController in this header file and you don't know what a MasterViewController is... but don't trip out bro. It's all good.
But then, later in the .m file after you write the code:
... masterViewController.dataController ...
the compiler responds:
Whoa, whoa, whoa. I was cool with you just having a variable with the type MasterViewController in the header file because you told me it was all good and not to worry. But now here you are trying to use some aspect of MasterViewController that I know nothing about. How am I supposed to know if this is legal or not? Not cool bro.

Forward Declaration

I was building an app when I ran into some errors. After doing some research, I found that the reason is because I am working with 2 files, that each #import each other. I read that the cure to this is to use Forward Declaration, but I couldn't find a good example of how this is done.
Here is what I have.
RootViewController.h
#import <UIKit/UIKit.h>
#import "FirstDetailViewController.h"
#protocol SubstitutableDetailViewController
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#interface RootViewController : UITableViewController <UISplitViewControllerDelegate, FirstDetailViewControllerDelegate>{
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
NSMutableArray *logMessages;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
#end
FirstViewDetailController.h
#import <UIKit/UIKit.h>
#import "RootViewController.h
//test2
#protocol FirstDetailViewControllerDelegate <NSObject>
- (void)addItemViewController:(FirstDetailViewController *)controller didFinishEnteringItem:(NSString *)item;
#end
//end test2
#interface FirstDetailViewController : UIViewController <SubstitutableDetailViewController> {
//for the output
IBOutlet UITextView *outputView;
UIToolbar *navigationBar;
}
#property (nonatomic, retain) IBOutlet UIToolbar *navigationBar;
//test
#property(nonatomic, retain) NSString *message;
//end test
#property (nonatomic, retain) id <FirstDetailViewControllerDelegate> delegate;
#end
I know that I need to replace #import with #class, but do I do it for both occurrences? Also, I a already #import "FirstDetailViewController.h" in the RootViewController.m file, so do I switch it there as well ?
I am a little confused so any help would be appreciated !
Forward declaration would be the solution if it were just pointers you needed, but you are implementing the other header's protocol in each class.
My suggestion would be to declare your protocols in some other header file, such as MyProtocols.h and include that in both of your .h files instead of the controllers' headers.
On a side note, having a strong, or retained reference to one's delegate isn't really standard practice, as this can easily cause a retain cycle which leads to leaked memory
Replace
#import "FirstDetailViewController.h"
with
#class FirstDetailViewController;
Replace
#import "RootViewController.h" with
#class RootViewController;
in RootViewController.m, make sure you have
#import "RootViewController.h"
#import "FirstDetailViewController.h"
in FirstDetailViewController.h make sure you have
#import "FirstDetailViewController.h"
#import "RootViewController.h"
Edit: Oops missed the protocol references... Dan F's answer is correct

Textfield return (null) no matter what

I have searched stackoverflow for similar problems and have found some, but they did not resolve my problem. I have 3 textfields (name,address,phone) from which I want to get the text. I have declared them in the (.h) file, also the #property, and then #synthesized them in the (.m) file. I have a IBAction for a button declared in the (.h) file and linked up correctly. Now when I push this button I want to get the values from the textfields but NSLog shows they are all (null) even before I do anything with the textfields. Its very simple code, i can't understand why it returns null.
//CoreDataViewController.h
#interface coreDataViewController : UIViewController {
UITextField *name;
UITextField *address;
UITextField *phone;
UILabel *status;
}
#property (strong, retain) IBOutlet UITextField *name;
#property (strong, retain) IBOutlet UITextField *address;
#property (strong, retain) IBOutlet UITextField *phone;
#property (strong, retain) IBOutlet UILabel *status;
- (IBAction) saveData;
#end
//CoreDataViewController.m
#import "coreDataViewController.h"
#import "AppDelegate.h"
#implementation coreDataViewController
#synthesize name=_name;
#synthesize phone=_phone;
#synthesize address=_address;
#synthesize status=_status;
- (void) saveData
{
NSLog(#"Name %# Address %# Phone %#",self.name.text,self.address.text,self.phone.text);
...some more code (commented out)....
}
IMO you have incorrectly synthesized iVars.
You use syntax:
synthesize name=_name;
but in the .h file you have:
#interface coreDataViewController : UIViewController {
UITextField *name;
UITextField *address;
UITextField *phone;
UILabel *status;
}
Change this part to:
#interface coreDataViewController : UIViewController {
UITextField *_name;
UITextField *_address;
UITextField *_phone;
UILabel *_status;
}
Just change below code
write synthesize like this
#synthesize name;
#synthesize phone;
#synthesize address;
#synthesize status;
ratherthen
#synthesize name=_name;
#synthesize phone=_phone;
#synthesize address=_address;
#synthesize status=_status;

why wont it recognize the #properties from header file from main file?

UIView.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface UIView : UIResponder {
IBOutlet UILabel *endLabel;
IBOutlet UIButton *goButton;
IBOutlet UITextField *textBox1;
IBOutlet UITextField *textBox2;
#property(nonatomic, retain) UILabel *endLabel;
#property(nonatomic, retain) UIButton *goButton;
#property(nonatomic, retain) UITextField *textBox1;
#property(nonatomic, retain) UITextField *textBox2;
}
- (IBAction)goButtonClicked;
#end
UIView.m
#import "UIView.h"
#implementation UIView
#synthesize textBox1, goButton;
#synthesize textBox2, goButton;
#synthesize textBox1, endLabel;
#synthesize textBox2, endLabel;
#synthesize goButton, endLabel;
- (IBAction)goButtonClicked {
}
#end
Going a bit crazy with the #synthesizes, are we? I do believe that your main problem here is that #property declarations need to be after the closing } of #interface.
I'm surprised the compiler didn't throw up a red flag the size of Greenland, tho'.
Additionally, you probably meant to make a custom subclass of UIView; I'll use MyView.
//MyView.m -- correct synthesize declaration
#synthesize textBox1, goButton, textBox2, endLabel;
//MyView.h -- correct interface declaration
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface MyView : UIView {
IBOutlet UILabel *endLabel;
IBOutlet UITextField *textBox1;
IBOutlet UITextField *textBox2;
IBOutlet UIButton *goButton;
}
#property(nonatomic, retain) UIButton *goButton;
#property(nonatomic, retain) UILabel *endLabel;
#property(nonatomic, retain) UITextField *textBox1;
#property(nonatomic, retain) UITextField *textBox2;
#end
The first problem is that you're naming your class UIView, which already exists in UIKit. See #Williham's advice on resolving this.
You only need one #synthesize per property, and when the property name matches the instance variable name, you should only need to do something like this in your .m file:
#synthesize endLabel;
#synthesize goButton;
#synthesize textBox1;
#synthesize textBox2;
Also, you're likely to run into problems getting your IBAction method to work. To use a method for a target-action linkage, it must have a return type of IBAction (which you have correct) and accept an id parameter representing the sender. The canonical method signature looks like this:
- (IBAction) goButtonClicked:(id)sender;
I'd actually recommend a method name that's not explicitly tied to the button that invokes it, especially since there could be other ways to invoke the same action. (For example, if you were writing a desktop application, a key equivalent or menu command could do the same thing.)