Why definition not required and synthesize required iphone - iphone

I have an interface
#interface A
{
NSMutableArray *_myArray;
}
#property(nonatomic, retain)NSMutableArray *myArray;
In in the implementation I have written
#synthesize myArray = _myArray;
And in the body of the code where I am using this array is only storing some arrays values which is like this...
-(void)updateArray:(NSArray*)p_NewValues
{
self.myArray = nil;
myArray = [NSMutableArray alloc]initwithArray:p_NewArray];
}
but unfortunate in code review I found that I don't required any variable definition only Synthesize is OK, can anybody explain why?

From documentation
The #synthesize directive also synthesizes an appropriate instance
variable if it is not otherwise declared.

With the modern Objective-C compiler used in the latest versions of Xcode, you don't need an explicit ivar nor do you even need the #synthesize anymore. Your code can now be:
#interface A
#property (nonatomic, retain) NSMutableArray *myArray;
#end
#implementation A
- (void)updateArray:(NSArray *)p_NewValues {
self.myArray = [NSMutableArray arrayWithArray:p_NewArray];
}
#end

Related

No known instance method for selector error in NSMutableArray

I have a problem accessing a object in my array. I store "Place" objects in my NSMutableArray. I want to access this array for my TableView. I get the "No known instance method for selector" error in line one. See lines below.
cell.imageView = [[self.currentPlaces objectAtIndex:indexPath.row]picture];
cell.subtitleLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]description];
cell.objectNameLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]name];
This is my Place object:
#interface Place : NSObject{
CLLocation *objectLocation;
UIImageView *picture;
NSString *name;
NSString *description;
}
The access of the properties "description" and "name" is no problem. I just dont know why this error occurs.
Thx. Dominik
I had the same problem; what worked for me was passing the UIImage instead of the UIImageView. So your code should look like this:
#interface Place : NSObject{
CLLocation *objectLocation;
UIImage *picture;
NSString *name;
NSString *description;
}
and this
cell.imageView.image = [[self.currentPlaces objectAtIndex:indexPath.row]picture];
cell.subtitleLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]description];
cell.objectNameLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]name];
If that doesn't work I'll post some more code for you to look at.
You haven't actually declared any methods. What you have declared are instance variables. You should probably be using #propertys instead.
#interface Place : NSObject
#property (nonatomic, retain) CLLocation *objectLocation;
#property (nonatomic, retain) UIImageView *picture;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy, getter=objectDescription) NSString *description;
#end
This will actually create the methods that you want. Note that I changed the method for the description property to read -objectDescription. This is because NSObject already declares the -description method and you shouldn't be overriding it with an unrelated property.
If you're on recent Clang, then this is all you need, and instance variables will get synthesized automatically (using an underbar prefix, e.g. _picture). If you're on an older version (e.g. if this causes errors), you need to add #synthesize lines, as in
#implementation Place
#synthesize objectLocation=_objectLocation;
#synthesize picture=_picture;
#synthesize name=_name;
#synthesize description=_description;
#end

Using AppDelegate for global readonly data

I have a project on iPhone with iOS4.
A instance variable of app delegate is a dictionary with global readonly data loaded from a plist when app starts.
CalculatorAppDelegate.h
#import <UIKit/UIKit.h>
#class MainViewController;
#interface CalculatorAppDelegate : NSObject <UIApplicationDelegate> {
NSDictionary *RGBSpacesDictionary;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain, readonly) NSDictionary *RGBSpacesDictionary;
#property (nonatomic, retain) IBOutlet MainViewController *mainViewController;
#end
CalculatorAppDelegate.m
#import "CalculatorAppDelegate.h"
#import "MainViewController.h"
#implementation CalculatorAppDelegate
#synthesize mainViewController=_mainViewController;
#synthesize RGBSpacesDictionary;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// load plist
NSString* plistPath1 = [[NSBundle mainBundle] pathForResource:#"RGBSpaces" ofType:#"plist"];
RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];
etc.
}
Then in MainViewController i am able to successfully reading the dictionary in viewDidLoad
MainViewController.h
#class CalculatorAppDelegate;
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
CalculatorAppDelegate *appDelegate;
}
#property (nonatomic, retain) CalculatorAppDelegate *appDelegate;
etc.
}
MainViewCOntroller.m
#import "CalculatorAppDelegate.h"
#implementation MainViewController
#synthesize appDelegate;
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = [[UIApplication sharedApplication] delegate];
RGBSpacesCount = (int) [appDelegate.RGBSpacesDictionary count];
}
In viewDidLoad it is all OK, I can read my dictionary as appDelegate.REGSpaceDictionary.
The problem is with another method of MainVievController called when a button is pressed
- (IBAction) RGBSpaceButtonPressed {
NSLog(#"appDelegate.RGBSpacesDictionary %#", appDelegate.RGBSpacesDictionary);
etc.
}
At this time calling the dictionary (for example with a NSLog) return in a crash.
Can someone help me? Thank you.
In this line
RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];
you are assigning an autoreleased object straight to the ivar so there is no guarantee how long it will stay around for. You should be assigning a non autoreleased object or going through the setter
// Going through the setter
self.RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];
// OR
// Non assigning a non autoreleased object
RGBSpacesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath1];
To use the setter you would have to redeclare the property in an extension at the top of the app delegate's .m file like this
#interface CalculatorAppDelegate ()
#property (nonatomic, retain, readwrite) NSDictionary *RGBSpacesDictionary;
#end
...
The rest of your implementation
Try to retain the dictionary in app delegate. It must be deallocated at some point, because you get an autoreleased one and you didn't use the property to set it.
// here you must retain the dictionary
[[NSDictionary dictionaryWithContentsOfFile:plistPath1] retain];
Of course don't forget to release it later in dealloc.

What is the best way to declare a property?

We declare properties using the #property keyword and synthesize it in the implementation file. My question is,
What if I declare a property using the #property keyword and also declare a variable in the interface block with the same name? For example, consider the following code,
Interface:
#interface myClass : NSObject {
NSString *myClass_name; // LINE 1
}
#property(nonatomic, retain) NSString *myClass_name; // LINE 2
#end
Implementation:
#implementation myClass
#synthesize myClass_name // LINE 3
#end
Declaring myClass_name in LINE 1 will make any problem? Like any reference problem or any unnecessary memory consumption problem?
No, in fact, declaring properties like that expects it. You could replace your declaration to:
#interface MyClass : NSObject {
NSString *ivar;
}
#property (nonatomic, retain) NSString *myClass_name;
#end
And then change your implementation to
#implementation MyClass
#synthesize myClass_name = ivar;
#end
(If you don't specify the = some_ivar, it will assume the ivar has the same name as the property.)
You always need to have the following lines:
Declaration of the property (Line 2)
Synthesization of the property (Line 3)
When you synthesize the property, if you do not specify which ivar to use (by using =ivar at the end), it will assume that there is an ivar with the same name as the property.
Declaring properties and synthesizing it will not create any reference problem in your case.
Doing this will create accessor and setter methods for your instance variable in your class.
If the variable names in the property and the one declared in the class, then the xcode will refer both as a single variable.
Line 3 and Line 4 are must. Line 1 is optiona
I got the following content from Apple's doc for Declared Properties. I am posting it here, so that it may be helpful for someone in future.
Runtime Difference
In general the behavior of properties is identical on all runtimes (see Runtime Versions and Platforms in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you. For example, given the following class declaration and implementation:
#interface MyClass : NSObject {
float sameName;
float otherName;
}
#property float sameName;
#property float differentName;
#property float noDeclaredIvar;
#end
#implementation MyClass
#synthesize sameName;
#synthesize differentName=otherName;
#synthesize noDeclaredIvar;
#end
the compiler for the legacy runtime would generate an error at #synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.
The following is the Object-oriented way:
DeclaringProperties.h
#interface DeclaringProperties : NSObject
// ivars and {} can be omitted
#property (nonatomic, readwrite, retain) NSString *normal;
#property (nonatomic, readwrite, retain) NSString *alias;
#property (nonatomic, readonly, retain) NSString *readonly;
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;
#end
DeclaringProperties.m
#import "DeclaringProperties.h"
// private interface
#interface DeclaringProperties ()
#property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
#property (nonatomic, readwrite, retain) NSString *private;
#property (nonatomic, readwrite, retain) NSString *retain;
#end
#pragma mark -
#implementation DeclaringProperties
#synthesize normal, alias = _alias, readonly, private, retain;
// You can not use "normal" here;
// But you can still use "alias", and it is highlighted in XCode!
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
self = [super init];
if (self) {
self.normal = aNormal;
self.alias = alias;
self.readonly = #"readonly";
self.private = #"private";
// allocated(copied) variable for retained(copied) property should be released or autoreleased
NSString *alloc = [[NSString alloc] init];
self.retain = alloc;
[alloc release];
// or
self.retain = [[NSString alloc] init];
[self.retain release];
// or
self.retain = [[[NSString alloc] init] autorelease];
// I don't like ;)
retain = [[NSString alloc] init];
}
return self;
}
- (void) dealloc {
self.normal = nil;
self.alias = nil;
self.readonly = nil;
self.private = nil;
self.retain = nil;
[super dealloc];
}
#end

Memory management in iphone

I have a class where i have define a array as a retain property such as:
#property (nonatomic,retain) NSMutableArray *temp;
can i use the self.temp = self.temp;
if yes can any one tell setter method for this and step by step implementation for this
looking forward from here.
Thanks
If you want a setter method declare your NSMutableArray in your header file:
{
NSMutableArray *temp;
}
#property(nonatomic, retain) NSMutableArray *temp;
And then in the main file make sure you call this after the #implementation MyClass:
#synthesize temp;
This gives you your getter and setter methods so from outside this class you can call MyClass.temp = ...;

How can I simply change a class variable from another class in ObjectiveC?

I simply want to change a variable of an object from another class. I can compile without a problem, but my variable always is set to 'null'.
I used the following code:
Object.h:
#interface Object : NSObject {
//...
NSString *color;
//...
}
#property(nonatomic, retain) NSString* color;
+ (id)Object;
- (void)setColor:(NSString*)col;
- (NSString*)getColor;
#end
Object.m:
+(id)Object{
return [[[Object alloc] init] autorelease];
}
- (void)setColor:(NSString*)col {
self.color = col;
}
- (NSString*)getColor {
return self.color;
}
MyViewController.h
#import "Object.h"
#interface ClassesTestViewController : UIViewController {
Object *myObject;
UILabel *label1;
}
#property UILabel *label1;
#property (assign) Object *myObject;
#end
MyViewController.m:
#import "Object.h"
#implementation MyViewController
#synthesize myObject;
- (void)viewDidLoad {
[myObject setColor:#"red"];
NSLog(#"Color = %#", [myObject getColor]);
[super viewDidLoad];
}
The NSLog message is always Color = (null)
I tried many different ways to solve this problem, but no success.
Any help would be appreciated.
Thanks for the help so far.
I modified the code as follow, but it still doesn't work as it should.
MyViewController.h:
#import <UIKit/UIKit.h>
#import "Object.h"
#interface MyViewController : UIViewController {
Object *myObject;
}
#property (nonatomic, retain) Object *myObject;
#end
MyViewController.m:
#import "MyViewController.h"
#import "Object.h"
#implementation MyViewController
#synthesize myObject;
- (void)viewDidLoad {
Object *myObject = [Object new];
myObject = 0;
[myObject setColor:#"red"];
NSLog(#"color = %#", myObject.color);
[super viewDidLoad];
}
If I do it like this, NSLog returns color = null (and I think myObject is only visible in viewDidLoad). How can declare myObject and make it visible in MyViewController?
I stripped down my Object class to
Object.h:
#interface Object : NSObject {
NSString *color;
}
#property(nonatomic, retain) NSString *color;
#end
Object.m:
#import "Object.h"
#implementation Object
#synthesize color;
#end
I wasn't able to define an object myObject in ViewDidLoad so that I can access its properties from the whole ViewController class? What did I miss?
Side question: Why do I have to set myObject to 0?
You're declaring a property, then explicitly declaring the accessors in Object.h. You only need to do one or the other - they mean the same thing (well, almost - you'll have color instead of getColor)
To implement the property in Object.m you should use #synthesize color. The explicit implementations, again, are then redundant (unless they do anything extra).
The explicit setColor implementation in Object.m is calling the property - which you are implementing explicitly, so I would have expected you to get an infinite recursion here.
MyViewController.m should probably synthesize label1, since you declare the property in the header (although it's not being used in your snippet).
[myObject getColor] is calling the color property, which you declared but did not synthesize. If you had explicitly implemented it as color it would have picked that up - but it won't match getColor (which is fortunately as that would have led to an infinite recursion again.
I don't see anywhere where you create your myObject instance. If you don't it will be nil and methods called on it (including property accesses) will return 0 or nil.
I suspect (6) is the cause of your issue, but the others need to be addressed too. Make sure you read up on property syntax.