instanced variable accessed in class method, Objective C - iphone

This is the original codes when I am getting this error
ClassA.h
+(ClassA*)methodA:(NSData*)data;
#property (nonatomic, strong) NSMutableArray *arr;
#property (nonatomic, strong) RXMLElement *rxmlRoot;
#end
ClassA.m
+(ClassA*)methodA:(NSData*)data {
//NSLog(#"class is %#",[name class]);
ClassA *ClassA = [[Stores alloc] init];
arr = [NSMutableArray array];
rxmlRoot = [RXMLElement elementFromXMLData:data];
}
I am reviewing my codes and now I have tow options to fix the code
OptionA
ClassA.h
+(ClassA*)methodA:(NSData*)data;
#property (nonatomic, strong) NSMutableArray *arr;
#property (nonatomic, strong) RXMLElement *rxmlRoot;
#end
ClassA.m
+(ClassA*)methodA:(NSData*)data {
//NSLog(#"class is %#",[name class]);
ClassA *ClassA = [[Stores alloc] init];
ClassA.arr = [NSMutableArray array]; <----- this has been modified
ClassA.rxmlRoot = [RXMLElement elementFromXMLData:data];<----- this has been modified
}
OptionB
ClassA.h
+(ClassA*)methodA:(NSData*)data;
#end
ClassA.m
static RXMLElement *rxlRoot; <----- this has been added as class variable
static NSMutableArray *arr; <----- this has been added as class variable
+(ClassA*)methodA:(NSData*)data {
//NSLog(#"class is %#",[name class]);
ClassA *ClassA = [[Stores alloc] init];
arr = [NSMutableArray array];
rxmlRoot = [RXMLElement elementFromXMLData:data];
}
I try either optionA or optionB and the compiler does not complain anything and the codes work properly.
I see many posts following the optionB which create class variables.
Question: is optionA also a good way to follow when we are dealing with class method and class variable as well.
Please advice me on this issue and by the way if I have made mistakes somewhere, please correct me. Thanks

There is no such thing as a "class variable" in Objective-C. When you declare a variable as static it is, effectively, a global variable that is limited to either the scope of the file it is compiled within or the scope of a method/function (or sub-expression).
Get rid of the Class. part of your calls to set the variables; that'll work in the .m file for the Class only; which is generally the pattern you would want (truly global variables are generally discouraged -- sometimes useful, though).

Create a designated initializer with a data parameter. Every class should have a designated initializer.
In your class method call the designated initializer passing in data.
Here is example code:
//ClassA.h
#class RXMLElement;
#interface ClassA : NSObject
+(ClassA*)methodA:(NSData*)data;
-(id)initWithData:(NSData*)data;
#property (nonatomic, strong) NSMutableArray *arr;
#property (nonatomic, strong) RXMLElement *rxmlRoot;
#end
//ClassA.m
#implementation ClassA
#synthesize arr;
#synthesize rxmlRoot;
+(ClassA*)methodA:(NSData*)data {
return [[ClassA alloc] initWithData:data];
}
-(id)initWithData:(NSData*)data {
self = [super init];
if (self) {
arr = [NSMutableArray array];
rxmlRoot = [RXMLElement elementFromXMLData:data];
}
return self;
}
#end
ARC is assumed in the example.

Related

Not Able to Add Object to NSMutableArray

Hey guys, I have this code within a function inside a class that is a subclass of NSOperation:
//...
#implementation DataLoader
#synthesize addedAnnotations;
#synthesize addedOverlays;
#synthesize loaderFunc;
#synthesize DLDelegate;
//...
-(id)initWithFunction:(LoaderFunc)func withDelegate:(id)delegate {
if (self = [super init]) {
self.addedOverlays = nil;
self.addedAnnotations = nil;
self.loaderFunc = func;
self.DLDelegate = delegate;
return self;
}
return nil;
}
//...
//inside a function
for (ParkingAnnotations *annotation in fetchedObjects) {
ParkingAnnotation *parkingAnnot = [[ParkingAnnotation alloc] init];
workingCoordinate.latitude = [[annotation latitude] doubleValue];
workingCoordinate.longitude = [[annotation longitude] doubleValue];
[parkingAnnot setCoordinate:workingCoordinate];
[parkingAnnot setTitle:[annotation valueForKey:#"lotName"]];
[parkingAnnot setAnnotationType:[annotation iconTypeRaw]];
[self.addedAnnotations addObject:parkingAnnot];//parkingAnnot not added to array here
[parkingAnnot release];
}
//...
Added annotations is an NSMutable array, I have been walking through this code with the debugger and for some reason the parkingAnnot object is not getting added to the array. Here is the relevant header code for the class:
//...
#interface DataLoader : NSOperation {
NSMutableArray *addedAnnotations;
NSMutableArray *addedOverlays;
LoaderFunc loaderfunc;
id <DataLoaderProtocol> DLDelegate;
}
#property (nonatomic, retain) NSMutableArray* addedAnnotations;
#property (nonatomic, retain) NSMutableArray* addedOverlays;
#property (nonatomic) LoaderFunc loaderFunc;
#property (assign) id DLDelegate;
//...
It is an astonishing problem because the function in which I am experiencing the problem was copied from my MapViewController and is essentially the same, but instead of mapView addAnnotation: I am adding to an NSMutable array instead. Any idea of what's up? Thanks in advance!
Where are you actually instantiating the addedAnnotations array? I only see it being assigned nil in your initialize function, maybe it should change to something like:
self.addedAnnotations = [[[NSMutableArray alloc] init] autorelease];

NSCFNumber unrecognized selector

i want to send data between views, but i get an error: unrecognized selector....
and the in the debugger, the variable mystring is a NSCFNumber ("at this time") instead of NSString...
allergy_appAppDelegate.h
#import <UIKit/UIKit.h>
#interface allergy_appAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
NSMutableArray *result_array;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (copy , readwrite) NSMutableArray *result_array;
#end
viewcontroller.m
allergy_appAppDelegate *dataCenter = (allergy_appAppDelegate *)[[UIApplication sharedApplication]delegate];
dataCenter.result_array = [[NSMutableArray alloc] initWithArray:Parser_result];
result.m
allergy_appAppDelegate *dataCenter = (allergy_appAppDelegate*)[[UIApplication sharedApplication]delegate];
show_user_array = [[NSMutableArray alloc] initWithArray: dataCenter.result_array]
for (NSString *mystring in show_user_array) {
textView.text = [[textView text] stringByAppendingString:#"\n"];
textView.text = [[textView text] stringByAppendingString:mystring];
}
Instance variables should be camel-cased, not have _. I.e. result_array should be resultArray. Classes start with capital letters.
Are you sure your result array is full of instances of NSString or NSNumber (or whatever you need)?
Given that you are leaking the array here...
dataCenter.result_array = [[NSMutableArray alloc] initWithArray:Parser_result];
... it is unlikely that this is an over-release problem. Note also that copy with NSMutableArray won't do what you want (the compiler should flag it, but doesn't). -copy always returns an immutable copy of an instance of a class cluster.

NSMutableArray crashes when adding after proper initialization

I have an NSMutableArray defined as a property, synthesized and I have assigned a newly created instance of an NSMutableArray. But after this my application always crashes whenever I try adding an object to the NSMutableArray.
Page.h
#interface Page : NSObject
{
NSString *name;
UIImage *image;
NSMutableArray *questions;
}
#property (nonatomic, copy) NSString *name;
#property (nonatomic, retain) UIImage *image;
#property (nonatomic, copy) NSMutableArray *questions;
#end
Page.m
#implementation Page
#synthesize name, image, questions;
#end
Relevant code
Page *testPage = [[Page alloc] init];
testPage.image = [UIImage imageNamed:#"Cooperatief leren Veenman-11.jpg"];
testPage.name = [NSString stringWithString:#"Cooperatief leren Veenman-11.jpg"];
testPage.questions = [[NSMutableArray alloc] init];
[testPage.questions addObject:[NSNumber numberWithFloat:arc4random()]];
The debugger reveals that the moment I use testPage.questions = [[NSMutableArray alloc] init]; the type of testPage.questions changes from NSMutableArray* to __NSArrayL* (or __NSArrayI*, not sure). I suspect this to be the problem, but I find it extremely odd. Anyone know what's happening here?
The problem is that you've declared the property as copy. This means your setter is going to be implemented something like this:
- (void) setQuestions:(NSMutableArray *)array {
if (array != questions) {
[questions release];
questions = [array copy];
}
}
The kicker here is that if you -copy an array (whether immutable or mutable), you will always get an immutable NSArray.
So to fix this, change the property to be retain instead of copy, and also fix this memory leak:
testPage.questions = [[NSMutableArray alloc] init];
It should be:
testPage.questions = [NSMutableArray array];
#property (nonatomic, copy) This setter declaration "copy" probably cast to NSArray why not retain or assign? I would retain anyway
You can also create a mutable copy method like so:
- (void)setQuestions:(NSMutableArray *)newArray
{
if (questions != newArray)
{
[questions release];
questions = [newArray mutableCopy];
}
}

EXC_BAD_ACCESS when calling class init in Objective C

I've been trying to figure this out but I can't figure out what I'm doing wrong.
I wrote a class and whenever I try to initialize it, I get a EXC_BAD_ACCESS error. I can't even step into the initialization.
Anyone have any idea what I'm doing wrong?
User *myUser = [myUser init];
.h file:
#import <Foundation/Foundation.h>
#interface User : NSObject {
long rowId;
NSString *email;
NSString *password;
NSString *fileVersion;
}
#property long rowId;
#property (assign) NSString *email;
#property (assign) NSString *password;
#property (assign) NSString *fileVersion;
#end
.m file
#import "User.h"
#implementation User
#synthesize rowId, email, password, fileVersion;
-(id)init {
self = [super init];
return self;
}
#end
You have to actually allocate the object:
User *myUser = [[User alloc] init];
Don't forget to release it when you're done using it.

Cannot figure out how to get rid of memory leak

I'm trying to test for memory leaks in my iphone and I'm not having much luck getting rid of this one. Here is the code that is leaking.
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)aMoc delegate:(id)aDelegate runSync:(BOOL)aRunSync {
if (self = [super init]) {
self.moc = aMoc;
self.settingsManager = [[VacaCalcSettingsManager alloc] initWithManagedObjectContext:self.moc];
self.delegate = aDelegate;
calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
self.runSync = aRunSync;
}
return self;
}
It is leaking on the self.settingsManager = [[VacaCalcSettingsManager alloc] initWithManagedObjectContext:self.moc]; line.
The self.settingManager instance variable is released in the dealloc method of the class.
I'm not sure what other information would be pertinent. Please let me know and I can provide it.
Thanks for any assistance.
-Mark
Here is the header file.
#interface VacaCalcCalculation : NSObject {
NSManagedObjectContext *moc;
VacaCalcSettingsManager *settingsManager;
id delegate;
NSCalendar *calendar;
NSDate *nextBankLimitDate;
BOOL runSync;
}
#property (nonatomic, retain) NSManagedObjectContext *moc;
#property (nonatomic, retain) VacaCalcSettingsManager *settingsManager;
#property (nonatomic, retain) id delegate;
#property (nonatomic, retain) NSCalendar *calendar;
#property (nonatomic, retain) NSDate *nextBankLimitDate;
#property (nonatomic) BOOL runSync;
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)aMoc delegate:(id)aDelegate;
If your settingsManager property is set to retain then you are retaining an object twice with the line: self.settingsManager = [[VacaCalcSettingsManager alloc] initWithManagedObjectContext:self.moc];
Try adding autorelease to the alloc]init or creating a class method on VacaCalcSettingsManager that returns an autoreleased object. Otherwise you could redeclare your property with assign so that it does not retain the object a second time.