So I have a class where I need to initialize some properties once after the first initialization. These properties need to not be reinitialized the whole run of the program. How do I do this in iOS 7 SDK? I tried use initWithNibName, but it doesn't run, at all. Same with init. What method should I use?
Here's my code
PSACurrentGame.h:
#import <UIKit/UIKit.h>
#import "phase10Scorer.h"
#interface PSACurrentGame : UIViewController
#property (strong, nonatomic) NSArray *playerNamesArray;
#property (nonatomic) BOOL moveNums;
#property (strong, nonatomic) phase10Scorer *scorer;
#property (strong, nonatomic) NSMutableArray *R1Scores;
#property (strong, nonatomic) NSMutableArray *R1Phases;
#property (strong, nonatomic) NSMutableArray *R2Scores;
#property (strong, nonatomic) NSMutableArray *R2Phases;
#property (strong, nonatomic) NSMutableArray *R3Scores;
#property (strong, nonatomic) NSMutableArray *R3Phases;
#property (strong, nonatomic) NSMutableArray *ToScores;
#property (strong, nonatomic) NSMutableArray *ToPhases;
#end
PSACurrentGame.m:
#import "PSACurrentGame.h"
#import "phase10Scorer.h"
#interface PSACurrentGame ()
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round1Scores;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round1Phases;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round2Scores;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round2Phases;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round3Scores;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *round3Phases;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *totalScores;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *totalPhases;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *playerNames;
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *roundLabelsSecondSet;
#end
#implementation PSACurrentGame
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.scorer = [[phase10Scorer alloc] init];
self.R1Scores = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.R1Phases = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.R2Scores = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.R2Phases = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.R3Scores = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.R3Phases = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.ToScores = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.ToPhases = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], [NSNumber numberWithInt:0], nil];
self.moveNums = true;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
int j = 0;
for (UILabel *playerLabel in self.playerNames) {
playerLabel.text = self.playerNamesArray[j];
j++;
}
if (self.moveNums) {
for (int i = 0; i < 5; i++) {
self.R3Scores[i] = self.R2Scores[i];
self.R2Scores[i] = self.R1Scores[i];
self.R1Scores[i] = self.ToScores[i];
self.R3Phases[i] = self.R2Phases[i];
self.R2Phases[i] = self.R1Phases[i];
self.R1Phases[i] = self.ToPhases[i];
self.ToScores[i] = [NSNumber numberWithInt:([self.scorer getScores:(i + 1)])];
self.ToPhases[i] = [NSNumber numberWithInt:([self.scorer getPhases:(i + 1)])];
}
}
int i = 0;
for (UILabel *tf in self.totalScores) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
pName.hidden = true;
tf.hidden = true;
i++;
continue;
}
tf.text = self.ToScores[i];
i++;
}
i = 0;
for (UILabel *tf in self.totalPhases) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.ToPhases[i];
i++;
}
i = 0;
for (UILabel *tf in self.round1Scores) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R1Scores[i];
i++;
}
i = 0;
for (UILabel *tf in self.round1Phases) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R1Phases[i];
i++;
}
i = 0;
for (UILabel *tf in self.round2Scores) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R2Scores[i];
i++;
}
i = 0;
for (UILabel *tf in self.round2Phases) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R2Phases[i];
i++;
}
i = 0;
for (UILabel *tf in self.round3Scores) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R1Scores[i];
i++;
}
i = 0;
for (UILabel *tf in self.round3Phases) {
UILabel *pName = self.playerNames[i];
if ([pName.text isEqualToString:#""]) {
tf.hidden = true;
i++;
continue;
}
tf.text = self.R1Phases[i];
i++;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You should use awakeFromNib instead.
- (void) awakeFromNib {
//Custom initialization
}
initWithNibName is not called when you instantiate a view controller from a XIB or storyboard.
Well, there are also initWithStyle: and initWithCoder: :)
You could modify them all but I think an easier solution would be to use a 'lazy initialization'.
For instance, in your interface you have a #property defined like so:
#interface YourClass
...
#property (nonatomic, strong, readonly) YourType* propertyName;
...
#end
Note the readonly attribute. This means, that there will be no publicly accessible setter for this property (you mentioned, that these properties won't ever be modified).
Then in your .m file you can define a category:
#interface YourClass()
...
#property (nonatomic, strong) YourType* propertyName; //this will give us a private setter.
...
#end
And then you define a getter like so:
#implementation
...
-(YourType*)propertyName
{
if (nil == _propertyName)
{
//initialize _propertyName here. This code will run once.
}
return _propertyName;
}
...
#end
This way properties will be initialized on demand. The good thing is that there is a guarantee that they'll be initialized. The bad thing is that the first call to these methods would take more time. But there is another plus: object creation is cheaper.
P.S. This code uses ARC.
Related
I have one tables looks like as below
I have one XML where detail of CLUB is available. Every tag has one value but Images tag contain dynamic images.
After this my object looks like as below
ClubDetails.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "ClubDetailsImages.h"
#interface ClubDetails : NSManagedObject
#property (nonatomic, retain) NSString * clubarea;
#property (nonatomic, retain) NSString * clubdealhere;
#property (nonatomic, retain) NSString * clubdescription;
#property (nonatomic, retain) NSString * clubdistance;
#property (nonatomic, retain) NSString * clubemail;
#property (nonatomic, retain) NSString * clubfacility;
#property (nonatomic, retain) NSString * clubfav;
#property (nonatomic, retain) NSString * clubid;
#property (nonatomic, retain) NSString * clublat;
#property (nonatomic, retain) NSString * clublogopath;
#property (nonatomic, retain) NSString * clubname;
#property (nonatomic, retain) NSString * clubphone;
#property (nonatomic, retain) NSString * cluburl;
#property (nonatomic, retain) NSString * clubvenutype;
#property (nonatomic, retain) NSString * clublong;
#property (nonatomic, retain) NSSet *clubdetailsimages;
#end
#interface ClubDetails (CoreDataGeneratedAccessors)
- (void)addClubdetailsimagesObject:(ClubDetailsImages *)value;
- (void)removeClubdetailsimagesObject:(ClubDetailsImages *)value;
- (void)addClubdetailsimages:(NSSet *)value;
- (void)removeClubdetailsimages:(NSSet *)value;
Its .m files looks like as below
#implementation ClubDetails
#dynamic clubarea;
#dynamic clubdealhere;
#dynamic clubdescription;
#dynamic clubdistance;
#dynamic clubemail;
#dynamic clubfacility;
#dynamic clubfav;
#dynamic clubid;
#dynamic clublat;
#dynamic clublogopath;
#dynamic clubname;
#dynamic clubphone;
#dynamic cluburl;
#dynamic clubvenutype;
#dynamic clublong;
#dynamic clubdetailsimages;
- (void)addClubdetailsimagesObject:(ClubDetailsImages *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:#"ClubDetailsImages"] addObject:value];
[self didChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
}
- (void)removeClubdetailsimagesObject:(ClubDetailsImages *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:#"ClubDetailsImages"] removeObject:value];
[self didChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
}
- (void)addClubdetailsimages:(NSSet *)value {
[self willChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveValueForKey:#"ClubDetailsImages"] unionSet:value];
[self didChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
}
- (void)removeClubdetailsimages:(NSSet *)value {
[self willChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveValueForKey:#"ClubDetailsImages"] minusSet:value];
[self didChangeValueForKey:#"ClubDetailsImages" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
}
***ClubDetailsImages.h*** looks like
#class ClubDetails;
#interface ClubDetailsImages : NSManagedObject
#property (nonatomic, retain) NSString * images;
#property (nonatomic, retain) ClubDetails *clubdetailed;
***ClubDetailsImages.m*** looks like
#implementation ClubDetailsImages
#dynamic images;
#dynamic clubdetailed;
For Saving, I wrote code like this
-(void)saveClubDetails:(NSMutableArray*)allClubs{
NSError *error;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"ClubDetails" inManagedObjectContext:context]];
[fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSArray *allObject = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject * obj in allObject) {
[context deleteObject:obj];
}
NSError *saveError = nil;
[context save:&saveError]; // NO MORE VALUE IS DB
for (int x = 0; x<[allClubs count]; x++) {
ClubDetails *club = [NSEntityDescription insertNewObjectForEntityForName:#"ClubDetails"
inManagedObjectContext:context];
ClubDetails2 *ob = (ClubDetails2*)[allClubs objectAtIndex:x];
club.clubarea = [NSString stringWithFormat:#"%#", ob.clubarea];
club.clubdealhere = [NSString stringWithFormat:#"%#", ob.clubdealhere];
club.clubdescription = [NSString stringWithFormat:#"%#", ob.clubdescription];
club.clubdistance = [NSString stringWithFormat:#"%#", ob.clubdistance];
club.clubemail = [NSString stringWithFormat:#"%#", ob.clubemail];
club.clubfacility = [NSString stringWithFormat:#"%#", ob.clubfacility];
club.clubfav = [NSString stringWithFormat:#"%#", ob.clubfav];
club.clubid = [NSString stringWithFormat:#"%#", ob.clubid];
club.clublat = [NSString stringWithFormat:#"%#", ob.clublat];
club.clublogopath = [NSString stringWithFormat:#"%#", ob.clublogopath];
club.clubname = [NSString stringWithFormat:#"%#", ob.clubname];
club.clubphone = [NSString stringWithFormat:#"%#", ob.clubphone];
club.cluburl = [NSString stringWithFormat:#"%#", ob.cluburl];
club.clubvenutype = [NSString stringWithFormat:#"%#", ob.clubvenutype];
club.clublong = [NSString stringWithFormat:#"%#", ob.clublong];
ClubDetailsImages *clubImages = [NSEntityDescription insertNewObjectForEntityForName:#"ClubDetailsImages"
inManagedObjectContext:context];
clubImages.images = [NSString stringWithFormat:#"veer url image"];
[club addClubdetailsimagesObject:clubImages];
}
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
// NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Clubs"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedArray = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"COUNT of arary is %d", [fetchedArray count]);
for (Clubs *info in fetchedArray) {
NSLog(#" Duaan Name ~~~~ : %#", info.clubname);
}
}
I AM STUCK IN FOLLOWING POINTS
1. How to save such objects in CoreData where one club may be 3, 4, 5 images which are stored in Array?
2. How can I fetch that one-to-more relationship from CoreData?
Just keep adding the objects and linking them to the ClubDetails, e.g.given that you have an array of image strings from somewhere....
for (NSString *image in images)
{
ClubDetailsImages *clubImages = [NSEntityDescription insertNewObjectForEntityForName:#"ClubDetailsImages" inManagedObjectContext:context];
clubDetailsImages.image = image;
clubDetailsImages.clubdetailed = club;
}
Not sure exactly what you asking here, but given a ClubDetails instance:
NSSet *images = club.clubdetailsimages;
Also, why have you implemented addClubdetailsimagesObject etc. This is not required. Use XCode to generate your entity classes and you will see that these methods are not created.
I'm trying to sort an array of a table view with no luck, this is how I'm trying to do it:
- (void) compare
{
NSMutableArray *temp = [[NSMutableArray alloc] initWithObjects: nil];
[temp addObjectsFromArray:[self displayedObjects]];
int a = [[self displayedObjects] count];
for (int i = 0; i < (a - 1); i++){
for (int j = 0; j <= (i^2); j++) {
NSString *temp1 = [temp objectAtIndex:i];
NSString *temp2 = [temp objectAtIndex:i+1];
if (temp1 > temp2) {
[movieIndex replaceObjectAtIndex:i withObject:temp2];
[movieIndex replaceObjectAtIndex:i+1 withObject:temp1];
}
}
}
[self movieIndex];
[[self tableView] reloadData];
}
displayedObjects is an array of array that the user can add new objects. this objects are movie instances in form of:
The tableview cell has the title of the movie. "in" that title there is a tableview with details about the movie. What i want to do is sort the displayed movies titles in ascending order but my code doesn't seem to work.
displayedObjects is a set of 3 NSStrings and 1 NSNumber. It gets objects form the following class:
#import <Foundation/Foundation.h>
#interface Movie : NSObject
{
NSString *_title;
NSString *_gender;
NSString *_location;
NSNumber *_publicationYear;
}
#property (nonatomic, retain) NSString *location;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *gender;
#property (nonatomic, retain) NSNumber *publicationYear;
+ (id)movieWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
- (id)initWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
#end
Because no one has suggested it yet, and I personally love blocks, I'll suggest the block alternative to the same thing already suggested:
[myArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
...
}];
I made it work by using:
NSSortDescriptor *titleSorter= [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
[movieIndex sortUsingDescriptors:[NSArray arrayWithObject:titleSorter]];
I have an NSMutableArray I am trying to populate using a for-loop and making NSStrings for it. These are to be the data source for my UIPickerView. You'll see some commented out lines where I manually made NSArrays and they showed up fine, but my for-loop NSMutableArray doesn't seem to accept the strings I'm making. The NSLogs show that I am making the string (and an equivalent float) alright, but the NSLogs that pull the values from the NSMutableArray show up as null and 0.0
The interface...
// PoolSizePickerViewController.h
#import <UIKit/UIKit.h>
#define kLengthComponent 0
#define kWidthComponent 1
#define kDepthComponent 2
#protocol PoolSizePickerViewControllerDelegate;
#interface PoolSizePickerViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
UIPickerView *poolSizePicker;
float length, width, depth;
NSMutableArray *lengthStrings, *widthStrings, *depthStrings;
NSMutableArray *lengthFloats, *widthFloats, *depthFloats;
NSString *pickerType;
NSString *pickerDescription;
UIButton *selectButton;
UIButton *cancelButton;
UILabel *pickerTitleLabel;
UITextView *pickerDescriptionLabel;
id <PoolSizePickerViewControllerDelegate> delegate;
}
#property (nonatomic, retain) IBOutlet UIPickerView *poolSizePicker;
#property float length, width, depth;
#property (nonatomic, retain) NSMutableArray *lengthStrings, *widthStrings, *depthStrings;
#property (nonatomic, retain) NSMutableArray *lengthFloats, *widthFloats, *depthFloats;
#property (nonatomic, retain) NSString *pickerType;
#property (nonatomic, retain) NSString *pickerDescription;
#property (nonatomic, retain) IBOutlet UIButton *selectButton;
#property (nonatomic, retain) IBOutlet UIButton *cancelButton;
#property (nonatomic, retain) IBOutlet UILabel *pickerTitleLabel;
#property (nonatomic, retain) IBOutlet UITextView *pickerDescriptionLabel;
#property (assign) id <PoolSizePickerViewControllerDelegate> delegate;
- (IBAction)selectedSelectButton;
- (IBAction)selectedCancelButton;
#end
#protocol PoolSizePickerViewControllerDelegate <NSObject>
#optional
- (void)poolSizePickerViewController:(PoolSizePickerViewController *)controller
didSelectLength:(float)length
andWidth:(float)width
andDepth:(float)depth;
- (void)poolSizePickerViewController:(PoolSizePickerViewController *)controller
didSelectCancel:(BOOL)didCancel;
#end
And the implementation...
// PoolSizePickerViewController.m
#import "PoolSizePickerViewController.h"
#implementation PoolSizePickerViewController
#synthesize poolSizePicker;
#synthesize length, width, depth;
#synthesize lengthStrings, widthStrings, depthStrings;
#synthesize lengthFloats, widthFloats, depthFloats;
#synthesize delegate;
#synthesize pickerType, pickerDescription;
#synthesize selectButton, cancelButton;
#synthesize pickerTitleLabel;
#synthesize pickerDescriptionLabel;
- (IBAction)selectedSelectButton {
NSInteger lengthRow = [poolSizePicker selectedRowInComponent:kLengthComponent];
NSInteger widthRow = [poolSizePicker selectedRowInComponent:kWidthComponent];
NSInteger depthRow = [poolSizePicker selectedRowInComponent:kDepthComponent];
length = [[self.lengthFloats objectAtIndex:lengthRow] floatValue];
width = [[self.widthFloats objectAtIndex:widthRow] floatValue];
depth = [[self.depthFloats objectAtIndex:depthRow] floatValue];
if ([self.delegate respondsToSelector:#selector (poolSizePickerViewController:didSelectLength:andWidth:andDepth:)]) {
[self.delegate poolSizePickerViewController:self didSelectLength:length andWidth:width andDepth:depth];
}
}
- (IBAction)selectedCancelButton {
if ([self.delegate respondsToSelector:#selector (poolSizePickerViewController:didSelectCancel:)]) {
[self.delegate poolSizePickerViewController:self didSelectCancel:YES];
}
}
- (void)viewDidLoad {
for (int footIndex = 6; footIndex < 40; footIndex ++) {
for (int inchIndex = 0; inchIndex < 2; inchIndex ++) {
[self.lengthStrings addObject:[NSString stringWithFormat:#" %d' %d\"", footIndex, inchIndex * 6]];
NSLog(#" %d' %d\"", footIndex, inchIndex * 6);
NSLog(#" -%#", [self.lengthStrings objectAtIndex:footIndex - 6]);
[self.lengthFloats addObject:[NSNumber numberWithFloat:(float)footIndex + (float)inchIndex * 0.5f]];
NSLog(#" %1.1f", (float)footIndex + (float)inchIndex * 0.5f);
NSLog(#" -%1.1f", [[self.lengthFloats objectAtIndex:footIndex - 6] floatValue]);
}
}
for (int footIndex = 6; footIndex < 40; footIndex ++) {
for (int inchIndex = 0; inchIndex < 2; inchIndex ++) {
[self.widthStrings addObject:[NSString stringWithFormat:#" %d' %d\"", footIndex, inchIndex * 6]];
[self.widthFloats addObject:[NSNumber numberWithFloat:(float)footIndex + (float)inchIndex * 0.5f]];
}
}
for (int footIndex = 1; footIndex < 16; footIndex ++) {
for (int inchIndex = 0; inchIndex < 2; inchIndex ++) {
[self.depthStrings addObject:[NSString stringWithFormat:#" %d' %d\"", footIndex, inchIndex * 6]];
[self.depthFloats addObject:[NSNumber numberWithFloat:(float)footIndex + (float)inchIndex * 0.5f]];
}
}
// lengthStrings = [NSArray arrayWithObjects:#" 6' 0\"", nil];
// lengthFloats = [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], nil];
// widthStrings = [NSArray arrayWithObjects:#" 6' 0\"", nil];
// widthFloats = [NSArray arrayWithObjects:[NSNumber numberWithFloat:2.0], nil];
// depthStrings = [NSArray arrayWithObjects:#" 1' 0\"", nil];
// depthFloats = [NSArray arrayWithObjects:[NSNumber numberWithFloat:3.0], nil];
UIImage *buttonImageNormal = [UIImage imageNamed:#"whiteButton.png"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[selectButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
[cancelButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:#"blueButton.png"];
UIImage *stretchableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[selectButton setBackgroundImage:stretchableButtonImagePressed forState:UIControlStateHighlighted];
[cancelButton setBackgroundImage:stretchableButtonImagePressed forState:UIControlStateHighlighted];
pickerTitleLabel.text = [NSString stringWithFormat:#"Select a Pool %#", pickerType];
pickerDescriptionLabel.text = self.pickerDescription;
self.poolSizePicker.showsSelectionIndicator = YES;
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#pragma mark -
#pragma mark Picker Data Source Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 3;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
switch (component) {
case kLengthComponent:
return [self.lengthStrings count];
break;
case kWidthComponent:
return [self.widthStrings count];
break;
default:
return [self.lengthStrings count];
break;
}
}
#pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component {
switch (component) {
case kLengthComponent:
return [self.lengthStrings objectAtIndex:row];
break;
case kWidthComponent:
return [self.widthStrings objectAtIndex:row];
break;
default:
return [self.depthStrings objectAtIndex:row];
break;
}
}
#end
Are you initializing your arrays somewhere? I don't see an [[NSMutableArray alloc] init] anywhere. Sending a message to a null object is a no-op, so it's likely that those addObjects are being sent to a null and aren't doing anything.
My issue is then I retrieve my NSArray of Store objects, all my NSString properties are causing BadAccess errors. The int and double properties work fine!
store.h
#interface Store : NSObject<NSCoding> {
NSString *Name;
NSString *Address;
NSString *Phone;
double GeoLong;
double GeoLat;
int ID;
}
#property (nonatomic, retain) NSString *Name;
#property (nonatomic, retain) NSString *Address;
#property (nonatomic, retain) NSString *Phone;
#property (nonatomic) double GeoLat;
#property (nonatomic) double GeoLong;
#property (nonatomic) int ID;
#end
store.m
#implementation Store
#synthesize Name;
#synthesize ID;
#synthesize Address;
#synthesize Phone;
#synthesize GeoLat;
#synthesize GeoLong;
/** Implentation of the NSCoding protocol. */
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeInt:ID forKey:#"ID"];
[encoder encodeDouble:GeoLat forKey:#"GeoLat"];
[encoder encodeDouble:GeoLong forKey:#"GeoLong"];
NSLog(#"Name in encode: %#", Name); //WORKS!
[encoder encodeObject:Name forKey:#"Name"];
[encoder encodeObject:Phone forKey:#"Phone"];
[encoder encodeObject:Address forKey:#"Address"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
// Init first.
if(self = [self init]){
ID = [decoder decodeIntForKey:#"ID"];
GeoLat = [decoder decodeDoubleForKey:#"GeoLat"];
GeoLong = [decoder decodeDoubleForKey:#"GeoLong"];
Name = [decoder decodeObjectForKey:#"Name"];
NSLog(#"Name in decode: %#", Name); //WORKS! logs the name
Address = [decoder decodeObjectForKey:#"Address"];
Phone = [decoder decodeObjectForKey:#"Phone"];
}
return self;
}
- (void)dealloc
{
[Name release];
[ID release];
[Address release];
[Phone release];
[super dealloc];
}
#end
Here is my code for storing and retriving the array.
//streams contains the data i will populate my array with.
for (ndx = 0; ndx < streams.count; ndx++) {
NSDictionary *stream = (NSDictionary *)[streams objectAtIndex:ndx];
Store *item = [[Store alloc] init] ;
item.Name = [stream valueForKey:#"Name"];
item.Address = [stream valueForKey:#"Address"];
item.Phone = [stream valueForKey:#"Phone"];
item.GeoLat = [[stream valueForKey:#"GeoLat"] doubleValue];
item.GeoLong = [[stream valueForKey:#"GeoLong"] doubleValue];
item.ID = [[stream valueForKey:#"ID"] intValue];
[listToReturn addObject:item];
}
}
//test to check if it works
for(int i = 0; i < [listToReturn count]; i++){
Store *item = (Store *)[listToReturn objectAtIndex:i];
NSLog(#"Name: %#", item.Name); //works
}
//save
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:listToReturn] forKey:#"stores"];
// retrieve
NSMutableArray *stores = [NSMutableArray new];
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:#"stores"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
stores = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
stores = [[NSMutableArray alloc] init];
}
if ([stores count] > 0) {
NSMutableArray * annotations = [[NSMutableArray alloc] init];
for(int i = 0;i< [stores count]; i++){
Store *store = [stores objectAtIndex: i];
CLLocationCoordinate2D location;
if(store.GeoLat != 0 && store.GeoLong != 0){
location.latitude = store.GeoLat;
location.longitude = store.GeoLong; //works
NSLog(#"Adding store: %#", store.Name); //DONT WORK!! <-- MAIN PROBLEM
}
}
}
Feels like I tried everything but can't figure out how it works in the decode but not when in loop the array after I put it into a array.
Anyone have any ideas?
You're not retaining the properties in initWithCoder.
Name = [decoder decodeObjectForKey:#"Name"];
is not using the setter of the (retaining) property you've defined. You're just setting the ivar. That means you don't acquire ownership and it can be deallocated.
Here are two ways you can retain the properties in your case:
self.Name = [decoder decodeObjectForKey:#"Name"];
Name = [[decoder decodeObjectForKey:#"Name"] retain];
I have a problem.
I try to initialize a variabile in a classViewController created inside a xib file.
I try with the code below but when i append a object to array, these array isn't initialized.
Can you help me?
thanks and sorry for my english.
#import <UIKit/UIKit.h>
#interface AccelerometroViewController : UIViewController <UIAccelerometerDelegate, UITextFieldDelegate, UIAlertViewDelegate>{
//.....
NSMutableArray *arrayPosizioni;
NSMutableArray *arrayPosizioniCorrenti;
NSString *nomePosizioneCorrente;
}
-(IBAction)salvaPosizione;
//...
#property (nonatomic, assign) NSMutableArray *arrayPosizioni;
#property (nonatomic, assign) NSMutableArray *arrayPosizioniCorrenti;
#property (nonatomic, assign) NSString *nomePosizioneCorrente;
#end
#import "AccelerometroViewController.h"
#import "Position.h"
#implementation AccelerometroViewController
float actualX;
float actualY;
float actualZ;
#synthesize arrayPosition;
#synthesize arrayCurrentPosition;
#synthesize nameCurrentPosition;
-(id)init {
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayCurrentPosition = [[NSMutableArray alloc]init];
nameCurrentPosition = [NSString stringWithFormat:#"noPosition"];
actualX = 0;
actualY = 0;
actualZ = 0;
}
return self;
}
-(void)updateTextView:(NSString*)nomePosizione
{
NSString *string = [NSString stringWithFormat:#"%#", nameCurrentPosition];
textEvent.text = [textEvent.text stringByAppendingString:#"\n"];
textEvent.text = [textEvent.text stringByAppendingString:string];
}
-(IBAction)savePosition{
Posizione *newPosition;
newPosition = [[Position alloc]init];
if([newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]){
//setValue is a method of Position. I'm sure that this method is correct
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio Posizione" message:#"Posizione salvata con successo" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[arrayPosition addObject:newPosition];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio osizione" message:#"Errore nel salvataggio" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void) initialise {
arrayPosition = [[NSMutableArray alloc] init];
arrayCurrentPosition = [[NSMutableArray alloc] init];
nameCurrentPosition = #"noPosition";
actualX = 0;
actualY = 0;
actualZ = 0;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:bundle]) {
[self initialise];
}
}
In addition to Felix's comment regarding the mis-naming, your properties are wrong too. Objects need to be retained or copied, not assigned (in most cases) so that you're certain their value won't go away. You need to have ownership of them. As such I would use the following:
#property (nonatomic, readwrite, retain) NSMutableArray *arrayPosition;
#property (nonatomic, readwrite, retain) NSMutableArray *arrayCurrentPosition;
#property (nonatomic, readwrite, copy) NSString *nameCurrentPosition;
Then, since you've retained something you're responsible for releasing it. As such you'll need a dealloc method to do that.
-(void)dealloc {
self.arrayPosition = nil;
self.arrayCurrentPosition = nil;
self.nameCurrentPosition = nil;
[super dealloc];
}