How can i use id as a temporary storage for a variable value - iphone

I am new to programming so can anyone here please let me know if the below is the valid in Objective-C.
Thanks.
#interface MainViewController : UIViewController
{
id iTempStore;
}
#property (nonatomic, assign) id iTempStore;
// FirstViewController
#interface FirstViewController : UIViewController
{
MainViewController* pParent;
}
-(void) SomeFunction
{
m_pParent = [[[MainViewController]alloc]init];
NSString* pTest = [[[NSString alloc] initWithString:#"Test"]autorelease];
// Is this valid way to store an object ???
[m_pParent setITempStore: pTest];
// Check Value
NSString* pValue = [m_pParent iTempStore];
NSLog(#"Value is: %#", pValue);// Value is: Test
[m_pParent release];
}

id can hold a reference to any object, so storing a string there is fine, but since you are backing with an iVar you probably want to use copy or retain rather than assign as your propery storage class... you would use copy if it were alway NSString or any class that has a mutable subclass... but since id can't specify that to be type safe you would either do :
#property(copy) id <NSCopying> iTempStore;
or
#propery(retain) id iTempStore;

it's technically ok...but not very...good
If you're declaring a property you don't necessary need it as instance variable too.
Do not use non-ARC things ...ARC is supported on all ios devices ( not sure about first gen) but on all that really matter at least.
If you know the object type you don't need to use id. id is used for when you are not sure of the returning type.
your code should look something like this :
#interface MainViewController : UIViewController
#property (nonatomic, assign) NSString* iTempStore;
// FirstViewController
#interface FirstViewController : UIViewController
{
MainViewController* pParent;
}
-(void) SomeFunction
{
m_pParent = [[MainViewController alloc]init];
NSString* pTest = [[[NSString stringWithString:#"Test"];
[m_pParent setITempStore: pTest];
NSString* pValue = [m_pParent iTempStore];
NSLog(#"Value is: %#", pValue);
}

Related

instanced variable accessed in class method, Objective C

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.

how do I build up a global like integer array?

How do I build up a global like integer array?
I tried variations of the following:
#interface
int *iArray; //this space will vary depending upon need in the implementation
#implementation
...
int iArrayInit[4] = {1,2,3,4};
iArray = iArrayInit;
-bottom line: I need to keep index values in array that I can access easily, and use of [NSArray intValue] maybe to slow.
thanks
If it needs to be static you can declare an NSMutableArray as static in the implementation file and expose static methods to access it. When using an NSArray the values need to be of type id which NSNumber can do. Here is an example which currently is not thread safe.
//.h file
#interface Foo : NSObject
{
}
+(NSArray*)iArray;
+(void)addiArrayValue:(NSNumber*)value;
#end
//.m file
#implementation Foo
static NSMutableArray *_iArray;
+(void)initialize
{
if([Foo class] == self)
{
_iArray = [[NSMutableArray alloc] init];
}
}
+(NSArray*)iArray
{
return [[_iArray copy] autorelease];
}
+(void)addiArrayValue:(NSNumber*)value
{
[_iArray addObject:value];
}
#end
//Use
[Foo addiArrayValue:[NSNumber numberWithInt:10]];
[Foo addiArrayValue:[NSNumber numberWithInt:12]];
NSLog(#"%#", [Foo iArray]);

How to retain this object when inserting to mutable array?

update: I have found the bug in my copyWithZone method in A. Thanks everyone.
update: sorry, I do have the #properties declared, I thought it was obvious so I skipped them in my OP. Sorry about that.
The crash message is: objA was released (zombie) memory when trying to access the str.
My data structure looks like this:
#class A
{
NSString *str;
}
#property (retain) NSString *str; // str synthesized in .m
#class B
{
A *objA;
}
#property (copy) A *objA; // objA synthesized in .m
What I am trying to do is:
B *newB = [[B alloc] init];
[someMutableArray addObject: newB];
However, I will crash some times when I try to access like this:
B *myB = [someMutableArray objectAtIndex: index];
someLabel.text = myB.objA.str;
I guess the objA & objA.str were not retained when inserting B into the array. But I don't know how to make sure they are retrain.
Any help is appreciated
-Leo
You should be using properties for Class A and B:
#interface A : NSObject {
NSString *str;
}
#property (nonatomic, retain) NSString *str;
#end
The use #synthesize str; in .m file, this will retain the str, don't forget to release the str in the dealloc method:
#implementation A
#synthesize str;
- (void) dealloc {
[str release], str= nil;
[super dealloc];
}
#end;
You should look in to
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17
to learn about properties and how they manage memory.
Have you tried:
[someMutableArray addObject: [newB copy] ];
At this line
someLabel.text = myB.A.str;
it should be...
someLabel.text = myB.objA.str;
Yes, also you should be using properties for the members of your class. That will retain them. Just don't forget to release in dealloc

passing NSString from one class to the other

I have a NSString that is taken from a UITextField in a ViewController. Every of my other ViewController will use this NSString as well. How can I pass this NSString to others ViewControllers?
You want to have a property in each of your controllers
#interface MyViewController : UIViewController{
NSString *title;
}
#property (retain) NSString *title;
#end;
#implementation MyViewController
#synthesize title;
#end;
Use it like:
MyViewController *myVC = [[MyViewController alloc] initWithFrame:...];
myVC.title = #"hello world";
You should be familiar with Memory Management
Create a class for sharing your common objects. Retrieve it using a static method, then read and write to its properties.
#interface Store : NSObject {
NSString* myString;
}
#property (nonatomic, retain) NSString* myString;
+ (Store *) sharedStore;
#end
and
#implementation Store
#synthesize myString;
static Store *sharedStore = nil;
// Store* myStore = [Store sharedStore];
+ (Store *) sharedStore {
#synchronized(self){
if (sharedStore == nil){
sharedStore = [[self alloc] init];
}
}
return sharedStore;
}
// your init method if you need one
#end
in other words, write:
Store* myStore = [Store sharedStore];
myStore.myString = #"myValue";
and read (in another view controller):
Store* myStore = [Store sharedStore];
myTextField.text = myStore.myString;
If the string remains the same, and never changes, you could make a file named defines.h (without the .m file) and have this line:
#define kMyString #"Some text"
Then wherever you need the string, just import the defines file and use the constant.
#import "defines.h"
Much simpler than making custom classes.
EDIT:
Didn't see you needed to grab from the text field.
In that case, you could have it stored as property of your app delegate class and get it from there. The delegate can be accessed from anywhere in your app.

CoreData Relationships Clarification: How to effectively set an inverse relationship

I have a CoreData relationship set up as follows:
(sorry, I'm new to stackoverflow so I have to draw it with ascii).
Story (object)
Attributes:
creationDate,
order,
Relationships:
sentences (one to many with Sentence)
Sentence (object)
Attributes: image, order, text
Relationships: belongsTo (one to one with Story)
Notes:
the sentences relationship is an NSSet
the belongsTo relationship is a Story
Simply put, a Story has many Sentences, but a Sentence can only belong to one Story.
I'm having trouble effectively setting the belongsTo property - and I'm aware I'm missing the paradigm a bit. I'm afraid that when I set belongsTo I'll be creating another Story object with it's own NSSet, creating a recursive loop of doom. In any case, my problem appears to be effectively setting the belongsTo property / relationship of each sentence.
The code to insert my data into the CoreData repository looks like this:
-(void)addStoryItemAction:(Sentence*)sentence{
[self dismissModalViewControllerAnimated:YES];
Story *story = [[Story alloc] initWithSentence: sentence];
sentence.belongsTo = story;
//crash and burn here.
Story *storySetter = (Story*) [NSEntityDescription insertNewObjectForEntityForName:#"Story" inManagedObjectContext:managedObjectContext];
[storySetter setSentences: story.sentences];
[storySetter setCreationDate: story.creationDate];
[storySetter setOrder: story.order];
NSError *error;
BOOL isSaved = [managedObjectContext save:&error];
NSLog(#"isSaved? %#", (isSaved ? #"YES" :#"NO ") );
if (!isSaved) {
NSLog(#"%#:%s Error saving context: %#", [self class], _cmd, [error localizedDescription]);
return;
}
}
I get the following error when it runs:
-[Sentence setBelongsTo:]: unrecognized selector sent to instance 0x5b5aa00
I'm aware that I'm missing the point somewhere along the way - could someone clear up where I'm going wrong so that I can implement the insert of this CoreData set effectively?
FYI:
Sentence.h:
#import <Foundation/Foundation.h>
#import "Story.h"
#class Story;
#interface Sentence : NSManagedObject {
}
#property (assign) NSString *text;
#property (assign) NSString *image;
#property (assign) NSInteger *order;
#property (nonatomic, retain) Story *belongsTo;
- (id)initWithContent:(NSString*)sentenceText image:(NSString*)sentenceImage order: (NSInteger*)sentencePosition;
#end
Sentence.m:
#import "Sentence.h"
#implementation Sentence
#synthesize text;
#synthesize image;
#synthesize order;
#dynamic belongsTo;
- (id)initWithContent:(NSString*)sentenceText image:(NSString*)sentenceImage order: (NSInteger*)sentencePosition{
[self setText: sentenceText];
[self setImage: sentenceImage];
[self setOrder: sentencePosition];
return self;
}
#end
story.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Sentence.h"
#class Sentence;
#interface Story : NSManagedObject {
}
#property (assign) NSSet *sentences;
#property (assign) NSDate *creationDate;
#property (assign) NSInteger *order;
- (id)initWithSentence:(Sentence*)sentence;
#end
story.m
#import "Story.h"
#implementation Story
#synthesize sentences;
#synthesize creationDate;
#synthesize order;
- (id)initWithSentence: (Sentence*) sentence{
NSLog(#"initWithSencence: sentence: %#", sentence);
sentences = [[NSSet alloc] initWithObjects:sentence, nil];
//[sentences setByAddingObject:sentence];
[self setSentences:sentences];
NSLog(#"sentences (in story object): %#", sentences);
creationDate = [NSDate date];
[self setCreationDate:creationDate];
//later expansion, position should be max(position of all stories) ++
[self setOrder:0];
return self;
}
#end
I'm a bit confused about why you're calling alloc / init on Story directly. I suspect that if you're doing the same thing elsewhere in your code (which you should publish for us to gawk at) then the "sentence" object passed in to addStoryItemAction: is probably NOT a properly initialized NSManagedObject.
The error you are encountering means that the underlying class has not properly implemented the accessors for that property "belongsTo", so it would seem something went afoul in your initialization code. You should be using:
NSEntityDescription *entityFromModel = [[aModel entitiesByName] valueForKey:#"Sentence"];
Sentence *sentence = (Sentence *)[[NSManagedObject alloc] initWithEntity:entityFromModel insertIntoManagedObjectContext:context];