I am not sure why I am getting the following error:
the height doesn't complain anything, it's just the width... why?
Here's my code:
#interface Embed : RKObject {
NSString * _url;
NSString * _original;
NSNumber * _width;
NSNumber * _height;
}
#property (nonatomic, retain) NSString * url;
#property (nonatomic, retain) NSString * original;
#property (nonatomic, retain) NSNumber * width;
#property (nonatomic, retain) NSNumber * height;
#end
#implementation Embed
#synthesize url = _url;
#synthesize original = _original;
#synthesize width = _width;
#synthesize height = _height;
+ (NSDictionary*) elementToPropertyMappings {
return [NSDictionary dictionaryWithKeysAndObjects:
#"url", #"url",
#"original", #"original",
#"width", #"width",
#"height", #"height",
nil];
}
- (void)dealloc
{
[_url release];
[_original release];
[_width release];
[_height release];
[super dealloc];
}
#end
not sure why it's a CGFloat, never convert it to CGFloat anywhere else
The error message would imply that it thinks the 'width' message, as posted to the objectAtIndex:0 returns a CGFloat, not an NSNumber.
It's possible it has made an incorrect guess about the thing you're calling width on, so assuming you have your object defined correctly you probably just need to give the compiler the correct hint, e.g. (broken down to make it clear where the cast goes):
[
[
(MyCorrectType *)[
[
[postsObject objectAtIndex:indexPath.row]
embeds]
objectAtIndex:0] // cast goes with the result of this
width]
floatValue]
The barely discernable error leads me to think that your -width method is returning a CGFloat rather than an NSNumber*.
Related
Starting over. I am fairly new to objective C. I have created the following class and I can't figure out how to initialize the array.
Can anyone provide any guidance on how to initialize the NSArray?
StatusPost.m
#import "StatusPost.h"
#implementation StatusPost
#synthesize messageId, fromName, friendId, message, choice2, choice3, choice4, picture, fbImage, commentCount, commentArray;
-(id)initWithMessageId:(NSString*) rMessageId
fromName:(NSString*) rFromName
friendId:(NSString*) rFriendId
message:(NSString*) rMessage
choice2:(NSString*) rChoice2
choice3:(NSString*) rChoice3
choice4:(NSString*) rChoice4
picture:(NSString *) rPicture
fbImage:(UIImage *)rfbImage
commentCount:(NSString*) rCommentCount
commentArray:(NSArray*) rCommentArray
{
if (self = [super init]) {
commentArray = [NSArray new];
self.messageId = rMessageId;
self.fromName = rFromName;
self.friendId = rFriendId;
self.message = rMessage;
self.choice2 = rChoice2;
self.choice3 = rChoice3;
self.choice4 = rChoice4;
self.picture = rPicture;
self.fbImage = rfbImage;
self.commentCount = rCommentCount;
self.commentArray = rCommentArray;
}
return self;
}
- (void)dealloc {
[messageId release];
[fromName release];
[friendId release];
[message release];
[picture release];
[fbImage release];
[commentCount release];
[commentArray release];
[super dealloc];
}
#end
StatusPost.h:
#import
#interface StatusPost : NSObject {
NSString* messageId;
NSString* fromName;
NSString* friendId;
NSString* message;
NSString* choice2;
NSString* choice3;
NSString* choice4;
NSString* picture;
UIImage* fbImage;
NSString* commentCount;
NSArray* commentArray;
}
#property (nonatomic, retain) NSString* messageId;
#property (nonatomic, retain) NSString* fromName;
#property (nonatomic, retain) NSString* friendId;
#property (nonatomic, retain) NSString* message;
#property (nonatomic, retain) NSString* choice2;
#property (nonatomic, retain) NSString* choice3;
#property (nonatomic, retain) NSString* choice4;
#property (nonatomic, retain) NSString* picture;
#property (nonatomic, retain) UIImage* fbImage;
#property (nonatomic, retain) NSString* commentCount;
#property (nonatomic, retain) NSArray* commentArray;
-(id)initWithMessageId:(NSString*) rMessageId
fromName:(NSString*) rFromName
friendId:(NSString*) rFriendId
message:(NSString*) rMessage
choice2:(NSString*) rChoice2
choice3:(NSString*) rChoice3
choice4:(NSString*) rChoice4
picture:(NSString*) rPicture
fbImage:(UIImage*) rfbImage
commentCount:(NSString*) rCommentCount
commentArray:(NSArray*) rCommentArray;
#end
It is likely that you aren't ever initializing the array, so when you try to add an object, you are just sending a message to nil. In the custom class's init method, add the line:
commentArray = [NSMutableArray new];
[NSArray new] is shorthand for [[NSArray alloc] init], so, technically speaking, that statement "inits" the NSArray.
However, your code looks a bit peculiar. You have the following statements in your init:
commentArray = [NSArray new];
self.commentArray = rCommentArray;
The first statement is setting the instance variable commentArray to the address of the newly alloced/inited NSArray while the second is setting the property commentArray to a parameter value. However, you have (through the #synthesize) made the instance variable commentArray the "backing store" for the property commentArray, so when you execute the second line the effect of the first line is overwritten (and the NSArray you created is "leaked").
(But if your real question is how to "load" an NSArray with values, you should ask that question -- and you'll get different answers.)
Hello I'm new to iPhone development.
I try to add move data from NSDictionary to data member of calls that i created.
When i "setWeightMeasure" nothing happened.
any suggestions?
the code that don't work:
NSDictionary *responseBodyProfile = [responseBody objectFromJSONString];
NSLog(#"%#",responseBodyProfile);
// the output is :
"{ "profile": {"goal_weight_kg": "77.0000", "height_cm": "179.00",
"height_measure": "Cm", "last_weight_date_int": "15452",
"last_weight_kg": "99.0000", "weight_measure": "Kg" }}""
[responseBody release];
if (responseBodyProfile != nil ){
NSDictionary *profile =[responseBodyProfile valueForKey:#"profile"];
NSLog(#"%#\n",[profile objectForKey:#"weight_measure"]);// Output : "kg"
[self.myUser setWeightMeasure:[profile objectForKey:#"weight_measure"]];
NSLog(#"%#", [self.myUser WeightMeasure]); // Output : "(null)"
}
the H file properyty:
#property (nonatomic, retain) UserData* myUser;
UserData.h:
#import <Foundation/Foundation.h>
#interface UserData : NSObject{
NSString* Weight;
NSString* Height;
NSString* GolWeight;
NSString* WeightMeasure;
}
#property (nonatomic, retain) NSString* Weight;
#property (nonatomic, retain) NSString* Height;
#property (nonatomic, retain) NSString* GolWeight;
#property (nonatomic, retain) NSString* WeightMeasure;
#end
UserData.m
#import "UserData.h"
#implementation UserData
#synthesize Weight, Height, GolWeight, WeightMeasure;
-(id)init{
self.Weight = #"0";
self.Height = #"0";
self.GolWeight = #"0";
self.WeightMeasure = #"0";
return self;
}
-(void)dealloc{
[Weight release];
[Height release];
[GolWeight release];
[WeightMeasure release];
[super dealloc];
}
#end
Use valueForKey instead of objectForKey in this line:
[self.myUser setWeightMeasure:[profile objectForKey:#"weight_measure"]];
like this:
[self.myUser setWeightMeasure:[profile valueForKey:#"weight_measure"]];
You might also want to use, since the values could be read as NSNumbers
[self.myUser setWeightMeasure:[[profile valueForKey:#"weight_measure"] stringValue]];
And why do you use strings instead of floats? Wouldn't that make your life easier when you'd need to perform some comparisons?
Also check if you have allocated memory for "myUser", that might be the case as well.
As Eugene mentioned, you should use valueForKey instead of objectForKey
The other thing is you might wanna use property and dot notation whenever you reference your object members, as Apple recommend. It is generally good for you to manage memory.
The previous answer about not initialize your string members in your -init() was totally wrong, if that cause some confusion, I do apologize for it.
For some reason, I can't access any of my variables after the first IF Statement in the following code. For instance, if index path is [0,0], then the variable phoneText spits out a phone number. But if its [1,0] or [2,0], I get a "null" return. Why is my variable being erased?
The following function in mapviewcontroller.m sets the values. I do actually have an error here that says "instance method setDetails not found".
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
//this determines what kind of item was selected
if ([control isKindOfClass:[UIButton class]]) {
NSLog(#"Trying to load VenueIdentifier...");
FinderAnnotation *clicked = view.annotation;
FinderViewController *fvi = [self.storyboard instantiateViewControllerWithIdentifier:#"FinderDetail"];
NSString* latitude = [NSString stringWithFormat:#"%f",clicked.coordinate.latitude];
NSString* longitude = [NSString stringWithFormat:#"%f",clicked.coordinate.longitude];
NSLog(#"lat: %#",latitude);
NSLog(#"lon: %#",longitude);
[fvi setDetails:clicked.title phone:clicked.phone address:clicked.address beersavailable:clicked.beersavailable latitude:latitude longitude:longitude];
[self.navigationController pushViewController:fvi animated:YES];
}
}
Then my finderdetail.h creates these variables:
#interface FinderDetail : UITableViewController{
UITableViewCell *phone;
UITableViewCell *address;
UITableViewCell *directions;
UILabel *venueLabel;
NSString *phoneText;
NSString *addressText;
NSString *venueText;
NSString *beersavailable;
NSString *latitudeText;
NSString *longitudeText;
}
#property (nonatomic, retain) IBOutlet UITableViewCell *phone;
#property (nonatomic, retain) IBOutlet UITableViewCell *address;
#property (nonatomic, retain) IBOutlet UITableViewCell *directions;
#property (nonatomic, retain) IBOutlet UILabel *venueLabel;
#property (nonatomic, retain) NSString *phoneText;
#property (nonatomic, retain) NSString *addressText;
#property (nonatomic, retain) NSString *venueText;
#property (nonatomic, retain) NSString *beersavailble;
#property (nonatomic, retain) NSString *latitudeText;
#property (nonatomic, retain) NSString *longitudeText;
#end
Lastly, finderdetail.m grabs these values, assigns them to the variables, and spits them into the table:
#implementation FinderDetail
#synthesize venueLabel, phone, address, directions;
#synthesize phoneText, addressText, venueText, beersavailble, latitudeText, longitudeText;
NSString *notlisted;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)setDetails:(NSString *)v phone:(NSString *)p address:(NSString *)a beersavailable:(NSString *)ba latitude:(NSString *)lat longitude:(NSString *)lon
{
NSLog(#"venue: %#",v);
NSLog(#"phone: %#",p);
NSLog(#"address: %#",a);
NSLog(#"beersavailable: %#",ba);
NSLog(#"%#",lat);
NSLog(#"%#",lon);
latitudeText = lat;
longitudeText = lon;
phoneText = p;
addressText = a;
venueText = v;
beersavailble = ba;
NSLog(#"%#", latitudeText);
NSLog(#"%#", longitudeText);
notlisted = #"Not Listed";
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Latitude: %#", latitudeText);
NSLog(#"Longitude: %#", longitudeText);
phone.detailTextLabel.text = phoneText;
address.detailTextLabel.text = addressText;
self.venueLabel.text = venueText;
if(phoneText == nil){
phone.detailTextLabel.text = notlisted;
}
if(addressText == nil){
address.detailTextLabel.text = notlisted;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
if(section ==0)
return 1;
else
if(section ==1)
return 1;
else
if(section ==2)
return 1;
else
return 0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",indexPath);
if((indexPath.section==0) && (indexPath.row ==0))
{
NSLog(#"%#",phoneText);
}
if((indexPath.section==1) && (indexPath.row ==0))
{
NSLog(#"%#",addressText);
}
if((indexPath.section==2) && (indexPath.row ==0))
{
NSLog(#"%#",latitudeText);
NSLog(#"%#",longitudeText);
}
}
The initial phoneText will display in an NSLog, but the addressText and latitudeText and longitudeText return null. I can put phoneText in one of those lower if statements and it too returns null. Thanks!!!
You aren't actually using your #property when you are doing the following:
latitudeText = lat;
longitudeText = lon;
phoneText = p;
addressText = a;
venueText = v;
beersavailble = ba;
Also, you are leaking memory every time those assignments are performed after the initial time (when they were still nil).
What you really want is:
self.latitudeText = lat;
self.longitudeText = lon;
self.phoneText = p;
self.addressText = a;
self.venueText = v;
self.beersavailble = ba;
Also, with a NSString (also NSData, NSSet, etc.) #property, it is better to define them as a copy, since it would be perfectly valid to pass in a NSMutableString instead (since it is a subclass of NSString), which then the contents could be altered externally of this object:
#property (nonatomic, copy) NSString *phoneText;
#property (nonatomic, copy) NSString *addressText;
#property (nonatomic, copy) NSString *venueText;
#property (nonatomic, copy) NSString *beersavailble;
#property (nonatomic, copy) NSString *latitudeText;
#property (nonatomic, copy) NSString *longitudeText;
Finally, the fact that you get (NULL) outputted by NSLog suggests the ivars are getting set to nil (and most likely released), and you are using ARC (Automatic Reference Counting), instead of manual retain/release/autorelease.
In setDetails you need to use the properties in order to retain the objects and release previous objects. Assigning directly to the ivars subverts the properties setters/getters and the memory management they provide is lost. Basically if properties are defined use them every time.
Since the objects are not being retained their memory can be reused and unpredictable results can occur such as the values becoming nil.
One way to find such problems is to turn on NSZombies in the simulator runs. I do this occasionally even when I am not having problems just as a check.
To fix the problem rewrite setDetails as:
-(void)setDetails:(NSString *)v phone:(NSString *)p address:(NSString *)a beersavailable:(NSString *)ba latitude:(NSString *)lat longitude:(NSString *)lon
{
self.latitudeText = lat;
self.longitudeText = lon;
self.phoneText = p;
self.addressText = a;
self.venueText = v;
self.beersavailble = ba;
self.notlisted = #"Not Listed";
}
One way to insure that properties are not inadvertently not used is to define the ivars with a slightly different name than the properties. The synthesize statement supports this. Here is how:
in the #interface:
NSString *_latitudeText;
...
#property (nonatomic, retain) NSString *latitudeText;
in the #implementation
#synthesize latitudeText = _latitudeText;
I am currently building an app for the iPhone and cannot figure out why I keep getting a memory leak to appear in the Leaks Instrument tool.
Here is the code and I have added comments to two places of where it is happening.
NSString *pathname = [[NSBundle mainBundle] pathForResource:self.toUseFile ofType:#"txt" inDirectory:#"/"];
//Line below causes a leak
self.rawCrayons = [[NSString stringWithContentsOfFile:pathname encoding:NSUTF8StringEncoding error:nil] componentsSeparatedByString:#"\n"];
self.sectionArray = [NSMutableArray array];
for (int i = 0; i < 26; i++) [self.sectionArray addObject:[NSMutableArray array]];
for(int i=0; i<self.rawCrayons.count; i++)
{
self.string = [self.rawCrayons objectAtIndex:i];
NSUInteger firstLetter = [ALPHA rangeOfString:[string substringToIndex:1]].location;
if (firstLetter != NSNotFound)
{
NSInteger audio = AUDIONUM(self.string);
NSInteger pictures = PICTURESNUM(self.string);
NSInteger videos = VIDEOSNUM(self.string);
//Line below causes a leak
[[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];
}
[self.string release];
}
Thanks in advance!
Edit
Here are my property declarations.
#property (nonatomic, retain) NSArray *filteredArray;
#property (nonatomic, retain) NSMutableArray *sectionArray;
#property (nonatomic, retain) UISearchBar *searchBar;
#property (nonatomic, retain) UISearchDisplayController *searchDC;
#property (nonatomic, retain) NSString *toUseFile;
#property (nonatomic, retain) NSArray *rawCrayons;
#property (nonatomic, retain) NSString *string;
#property (nonatomic, retain) TermViewController *childController;
Here are the leaks that are occurring after follow Nick Weaver's fixes.
Here is an expanded version of one of the NSCFString.
And another image.
Image with the Responsible Caller:
Also, because this may be useful, here are the properties for Term:
#property (nonatomic, retain) NSString *name;
#property (nonatomic) NSInteger numberAudio;
#property (nonatomic) NSInteger numberPictures;
#property (nonatomic) NSInteger numberVideos;
And the implementation:
#implementation Term
#synthesize name, numberAudio, numberPictures, numberVideos;
- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
self.name = [toSetName retain];
self.numberAudio = audio;
self.numberPictures = pictures;
self.numberVideos = videos;
return self;
}
- (NSString*)getName
{
return [[name retain] autorelease];
}
-(void)dealloc
{
[name release];
[super dealloc];
}
#end
Ok, try this changed Version of Temp. I've deleted the getter because you have already one by synthesizing. You cann use the getter like this for name:
term.name
The problem was how you set the name: you want a copy of the name and setting it with the synthesized setter without calling a retain should do the trick. You could, of course, have set it with the retained property of name but you should have left out retain, like this self.name = toSetName;. The setter will retain it for you.
#property (nonatomic, copy) NSString *name;
#property (nonatomic) NSInteger numberAudio;
#property (nonatomic) NSInteger numberPictures;
#property (nonatomic) NSInteger numberVideos;
#implementation Term
#synthesize name, numberAudio, numberPictures, numberVideos;
- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
self.name = toSetName;
self.numberAudio = audio;
self.numberPictures = pictures;
self.numberVideos = videos;
return self;
}
-(void)dealloc
{
[name release];
[super dealloc];
}
Adding an object to an array will retain the instance, so the retain is 2 because you call
[[Term alloc] initToCall..
Do something like
Term *term = [[Term alloc] initToCall..];
[theArray addObject:term];
[term release];
1. See the arrow in the first line in the address column? Click it!
2. After clicking :)
Hard to tell you why the first one is leaking, because we don't know what the property is declared as. Is it retain? copy? assign? what?
The last one is fairly self explanatory though, you're taking ownership of a Term object, and not releasing it when it's added. addObject: retains its argument, meaning if you don't need that Term anymore, you need to give up ownership. I.e., pass -autorelease to the result of your initToCall:::: (which btw is a very bad name for a method)
Change:
[[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];
to:
Term *tempTerm = [[Term alloc] initToCall:NAME(self.string):audio:pictures:videos];
[[self.sectionArray objectAtIndex:firstLetter] addObject:tempTerm];
[tempTerm release];
By alloc'ing an object you are responsible for it's release.
I do not understand why i am getting this error. Here is the related code:
Photo.h
#import <CoreData/CoreData.h>
#class Person;
#interface Photo : NSManagedObject
{
}
#property (nonatomic, retain) NSData * imageData;
#property (nonatomic, retain) NSNumber * Latitude;
#property (nonatomic, retain) NSString * ImageName;
#property (nonatomic, retain) NSString * ImagePath;
#property (nonatomic, retain) NSNumber * Longitude;
#property (nonatomic, retain) Person * PhotoToPerson;
#end
Photo.m
#import "Photo.h"
#import "Person.h"
#implementation Photo
#dynamic imageData;
#dynamic Latitude;
#dynamic ImageName;
#dynamic ImagePath;
#dynamic Longitude;
#dynamic PhotoToPerson;
#end
This is a mapViewController.m class i have created. If i run this, the CLLocationDegrees CLLat and CLLong lines:
CLLocationDegrees CLLat = (CLLocationDegrees)photo.Latitude;
CLLocationDegrees CLLong = (CLLocationDegrees)photo.Longitude;
give me the error : pointer value used where a floating point value was expected.
for(int i = 0; i < iPerson; i++)
{
//get the person that corresponds to the row indexPath that is currently being rendered and set the text
Person * person = (Person *)[myArrayPerson objectAtIndex:i];
//get the photos associated with the person
NSArray * PhotoArray = [person.PersonToPhoto allObjects];
int iPhoto = [PhotoArray count];
for(int j = 0; j < iPhoto; j++)
{
//get the first photo (all people will have atleast 1 photo, else they will not exist). Set the image
Photo * photo = (Photo *)[PhotoArray objectAtIndex:j];
if(photo.Latitude != nil && photo.Longitude != nil)
{
MyAnnotation *ann = [[MyAnnotation alloc] init];
ann.title = photo.ImageName;
ann.subtitle = photo.ImageName;
CLLocationCoordinate2D cord;
CLLocationDegrees CLLat = (CLLocationDegrees)photo.Latitude;
CLLocationDegrees CLLong = (CLLocationDegrees)photo.Longitude;
cord.latitude = CLLat;
cord.longitude = CLLong;
ann.coordinate = cord;
[mkMapView addAnnotation:ann];
}
}
}
NSNumber is not a float type, but a pointer, so you need to do this to convert it:
CLLocationDegrees CLLat = (CLLocationDegrees)[photo.Latitude doubleValue];
CLLocationDegrees CLLong = (CLLocationDegrees)[photo.Longitude doubleValue];