What’s the point of repeated class interface declaration in the implementation file? - iphone

In some of the Apple Iphone examples, some of the properties are declared in the header file and some properties in the implementation file. For example in the Siesmic XML examples
ParseOperation.h
#interface ParseOperation : NSOperation {
NSData *earthquakeData;
#private
NSDateFormatter *dateFormatter;
// these variables are used during parsing
Earthquake *currentEarthquakeObject;
Contact *currentContactObject;
NSMutableArray *currentParseBatch;
NSMutableString *currentParsedCharacterData;
BOOL accumulatingParsedCharacterData;
BOOL didAbortParsing;
NSUInteger parsedEarthquakesCounter;
}
#property (copy, readonly) NSData *earthquakeData;
#end
ParseOperation.m
#interface ParseOperation () <NSXMLParserDelegate>
#property (nonatomic, retain) Earthquake *currentEarthquakeObject;
#property (nonatomic, retain) NSMutableArray *currentParseBatch;
#property (nonatomic, retain) NSMutableString *currentParsedCharacterData;
#property (nonatomic, retain) Contact *currentContactObject;
#end
What is the use of the additional interface declaration in the implementation file ?

That’s simply a difference between a public and a private class interface. The header describes the public interface, but some of the properties are only meant to be used by the class itself, not by its collaborators. These private properties are usually declared the way you described, as a category or a class extension inside the implementation file.
// Foo.h – the public interface
#interface Foo : NSObject {…}
// Collaborators can only read bar.
#property(readonly) int bar;
#property(readonly) int baz;
#end
// Foo.m
#import "Foo.h"
// Private interface
#interface Foo ()
// Inside class implementation we can also change bar.
#property(assign) int bar;
#property(assign) int other;
#end
#implementation Foo
#synthesize bar, baz, other;
…
#end

Related

Local declaration of "speed view" hides instance variable

So I have been searching in a few hours for why my iPhone app hates me. This is the error I get:
Warning: local declaration of 'speedView' hides instance variable.
Here is my .m file
#implementation MainViewController
#synthesize speedCount;
#synthesize speedView;
#synthesize popoverController;
- (void)setspeedView:(UILabel *)speedView
{
[speedView setText: [NSString stringWithFormat:#"%d",speedCount]];
speedCount = 0;
speedCount++;
}
.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
{
AppDelegate *appDelegate;
IBOutlet MKMapView *userMap;
IBOutlet UILabel *speedView;
CLLocationManager *locationManager;
}
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property(nonatomic) int speedCount;
I really don't understand why it says that I am hiding the instance variable.
You have a ivar (an instance variable) called speedView.
In your method
- (void)setspeedView:(UILabel *)speedView
speedView is a local variable whose name clashes with the ivar.
If you are using a modern version of the compiler just remove the #synthesize directive.
It will be automatically added by the compiler in this form
#synthesize speedView = _speedView
which will create the ivar _speedView, whose name doesn't clash anymore with the local variable.
Also note that declaring both the instance variable and the property is redundant. The ivar will be automatically created by the (implicit) #synthesize directive.
Here's a "modern" version of your class:
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) IBOutlet MKMapView *userMap;
#property (strong, nonatomic) AppDelegate *appDelegate;
#property (nonatomic) int speedCount;
.m
#implementation MainViewController
- (void)setspeedView:(UILabel *)speedView {
[speedView setText:[NSString stringWithFormat:#"%d", self.speedCount]];
self.speedCount = 0;
self.speedCount++;
}
Please note:
properties are nice: use them whenever you can
#synthesize is implicit
the implicit version of #sythesize declares a _ivar for the property ivar
always access variables through the getters/setters, i.e. self.ivar, a part from init methods. If you need to access the var directly use _ivar or self->_ivar
As a final remark, this looks a bit weird
self.speedCount = 0;
self.speedCount++;
and it could be replaced with
self.speedCount = 1;
Are you sure it's what you mean? Also, as noted in the comments by others, you are not using the method parameter speedView. That smells bad and you may want to double check your implementation.

Class Extension - unrecognized setter

The following codes crashed:
#interface AppDelegate (PrivateMethods)
#property (nonatomic, strong) NSString * name;
#end
#implementation AppDelegate
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.name = #"foobar";
...
Error is:
'-[AppDelegate setName:]: unrecognized selector sent to instance 0x6d73df0'
When I change
#interface AppDelegate (PrivateMethods)
to
#interface AppDelegate ()
Then it is okay, what would be the reason?
Update: As answered below, since I must use class extension for this purpose, now this question become: Is the use of class extension to declare private methods acceptable?
e.g.
#interface AppDelegate ()
- (void) start;
#property (nonatomic, strong) NSString * name;
#end
Class extension is basically used to enhance the public property variable. Suppose you have exposed readonly object, or getter method of any variable, then you have make the same object as readwrite in extension.Whereas Category is only used to enhance the method/functionality of class.
check this
#interface MyClass : NSObject
// property here is used as readonly.
#property (retain, readonly) float value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, readwrite) float value;
#end
or
#interface MyClass : NSObject
// here we have exposed getter method of private instance.
- (float) value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, strong) float value;
#end
One is a category, the other is a class extension. If you want to add properties to an existing class, you need to use the latter.
This is the right approach:
#interface AppDelegate ()
#property (nonatomic, strong) NSString * name;
#end

Xcode 4 Core Data: How to use fetched property created in Data Model editor

How do you implement a fetched property in Xcode 4?
Here is an example of two entities, a book and a page:
I followed the guidelines here to create a fetched property that references a value from the source entity using the variable $FETCH_SOURCE: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html
Now, once I have this saved and I generate the source code I get this:
// Book.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Pages;
#interface Book : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSNumber * pageCount;
#property (nonatomic, retain) Pages * pages;
#end
And...
// Book.m
#import "Book.h"
#import "Pages.h"
#implementation Book
#dynamic title;
#dynamic pageCount;
#dynamic pages;
#end
Where is the fetched property 'fetchLastPage'? How can I use it in code?
From what I've read you need to add fetched properties to the generated class yourself using the #dynamic keyword
// In your header
#property (nonatomic, retain) NSArray *fetchLastPage;
// In your class
#dynamic fetchLastPage;

How to write covariant readwrite properties in class continuations?

Given the following example
// MyClass.h
#interface MyClass {
NSMutableArray *queue;
}
#property (readonly, retain) NSArray *queue;
#end
and
// MyClass.m
#interface MyClass ()
#property (readwrite, retain) NSMutableArray *queue;
#end
#implementation MyClass
#synthesize queue;
#end
I get a Property 'queue' type in 'MyClass' class continuation does not match class 'MyClass' property warning from the compiler. What is the best way to add "private" covariant setters to a class without writing them by hand?
You did it correctly. The issue here is NSArray isn't an NSMutableArray. If you make the private property a NSArray as well, and then write your own setter that accepts a NSMutableArray it should work as expected.

Can I create properties with a public getter and private setter?

I'd like to use properties for my instance variables, but in many cases, I only want the class itself to have access to the setter. I was hoping I could do something like this:
Foo.h:
#interface Foo {
NSString *bar;
}
#property (readonly) NSString *bar;
#end
Foo.m:
#import "Foo.h"
#interface Foo ()
#property (copy) NSString *bar;
#end
#implementation Foo
#synthesize bar;
#end
But this generates a warning:
Foo.m:4: warning: property ‘bar’ attribute in ‘Foo’ class continuation does not match class ‘Foo’ property
I can see what it's complaining about, but it still seems like a useful idiom. Is there some other way to accomplish this without writing my own setters?
Your approach is correct, but the redeclaration of #property bar in the class extension must match the original declaration except for readwrite vs. readonly. So this will work:
Foo.h
#interface Foo {
NSString *bar;
}
#property (copy,readonly) NSString *bar;
#end
Foo.m:
#import "Foo.h"
#interface Foo ()
#property (copy,readwrite) NSString *bar;
#end
#implementation Foo
#synthesize bar;
#end
(recall that the default is assign for properties, not copy).
When Barry says "the default is retain for properties" he means that retain should be specified like this:
#property (retain) NSDate *endDate;
If they are left like this:
#property NSDate *endDate;
assign is assumed by the compiler.