Expected method to read array element not found on object of type 'NSArray *' - xcode4.4

+ (UIColor*)hll_backgroundColorForIndex:(NSUInteger)index
{
index = index % [self hll_backgroundColors].count;
UIColor *color = [self hll_backgroundColors][index];
NSAssert(nil != color, #"nil color");
return color;
}
this is my code showing error at [self hill backgroundColors][index]

Is the array empty? Log it with NSLog(). Plus, I would put [self hll_backgroundColors] in an array variable within the method, I don't know whether you do some magic in the getter method.

Related

How should I be sending a message with a field of the same object as its value?

In Objective-C, the compiler is complaining about the following line of code:
if ([self getLength(self.identifier)] < givenWidth * kMarginAllowance)
This is getting the error "Expected ']'", and the caret below the text is on the parenthesis exactly after "getLength".
My suspicion is that my [self getLength(self.identifier)] is wrong in how it combines things.
What I want to say is "Fetch this object's identifier, and call this object's getLength() method."
I've tried a couple of permutations, and I don't think I'm using correct syntax.
What is the correct syntax for this type of thing?
--
My code is:
-(float)getLength:(NSString *)text
{
UIFont *font = [UIFont fontWithName:#"Scurlock" size:20];
CGSize size = [text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]];
return size.width;
}
-(void)getFormattedString:(float)givenHeight width:(float)givenWidth
{
NSMutableArray *workbench = [NSMutableArray array];
if (getLength(self.identifier) < givenWidth * kMarginAllowance)
{
[workbench addObject:self.identifier];
}
else
{
// [Under development]
}
}
The included .h file has:
-(float) getLength:(NSString *)text;
There is a yellow warning in Xcode that indicates that the call to getLength() is an invalid implicit declaration. The character it specifically points to is the beginning of the getLength() call. If I try to run it, I get an "Apple Mach-O Linker Error", because _getLength is referenced and presumably doesn't turn anything up.
What is the root problem I'm causing here? Inlining the method might do what I want, but I'd rather fix it, and understand what the correct approach is.
Try
[self getLenght:self.identifier]
So it would be like this:
if ([self getLenght:self.identifier] < givenWidth * kMarginAllowance)
getLenght: is an Objective-C method but you're trying to call it as a C function.
Hope this helps!
if ( getLength(self.identifier) < (givenWidth * kMarginAllowance))
If getLength is an instance method
// calls getLength method on self.identifier
if ([self.identifier getLength] < givenWidth * kMarginAllowance)
if it is a C style function
if (getLength(self.identifier) < givenWidth * kMarginAllowance)

Detect string or integer in Core Data

I have built in some Core Data support into my app from the Core Data Books example. The example uses Dates and Strings. However I have tried adding the ability to add and edit an Integer value.
//If the value is a string
if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) {
textField.hidden = NO;
datePicker.hidden = YES;
textField.text = [editedObject valueForKey:editedFieldKey];
textField.placeholder = self.title;
[textField becomeFirstResponder];
}
//If the value is a number
else {
textField.hidden = NO;
datePicker.hidden = YES;
textField.text = [[editedObject valueForKey:editedFieldKey] stringValue];
textField.placeholder = self.title;
[textField becomeFirstResponder];
}
The first if statement is the in example code (without the check if its a string, I added that) and I added the else statement to run when its not a string but an integer. It works, however now when I edit a string it skips the if statement, so the line: if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) isn't working somehow.
If you do look at the CoreDataBooks example from Apple, my code is the same, only I added a field which takes an Integer 16.
Edit
When putting a breakpoint on the first if statement and returning po [editedObject valueForKey:EditedFiledKey] in the console I get: Can't print the description of a NIL object.
I assume this is because it's before the object is made? This happens when the view appears (the view to enter a new string).
It's upon pressing the save button that this code is run:
- (IBAction)save {
// Set the action name for the undo operation.
NSUndoManager * undoManager = [[editedObject managedObjectContext] undoManager];
[undoManager setActionName:[NSString stringWithFormat:#"%#", editedFieldName]];
// Pass current value to the edited object, then pop.
if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) {
[editedObject setValue:textField.text forKey:editedFieldKey];
}
else {
[editedObject setValue:[NSNumber numberWithInteger:[[textField text] integerValue]] forKey:editedFieldKey];
}
[self.navigationController popViewControllerAnimated:YES];
}
When this runs, its skips the first if statement and runes the else statement, then crashing and showing the error: Unacceptable type of value for attribute: property = "firstName"; desired type = NSString; given type = __NSCFNumber; value = 0.
firstName is the string attribute in my data model. Im guessing because that first if statement fails, its goes forward an expects an integer? Im really unsure.
OK, so based on the value being nil in the debugger, let me explain what's happening. In Objective-C, any message sent to nil object will simply do nothing, and then return nil (which happens to have exactly the same memory value as 0 and false and NO).
So you're doing this:
if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) {
If editedObject is nil, then valueForKey will do nothing and return nil. Then you're sending isKindOfClass to nil which will also do nothing and return nil. Inside an if statement, nil will evaluate to NO, sending you to the else statement.
Where you do this:
textField.text = [[editedObject valueForKey:editedFieldKey] stringValue];
editedObject is nil, cascading to stringValue returning nil, and therefore you are trying to set the text field's value to nil, which is invalid and will crash your app.
The solution is to restructure your code to check for nil. Here's how I would write your code:
// don't do anything for a nil value note this will detect editedObject being nil, or the result of valueForKey: being nil.
if (![editedObject valueForKey:editedFieldKey]) {
return;
}
// figure out the string value
NSString *textFieldValue = [editedObject valueForKey:editedFieldKey];
if ([textFieldValue isKindOfClass:[NSNumber class]]) {
textFieldValue = [(NSNumber *)textFieldValue stringValue]
}
// update the text field
textField.hidden = NO;
datePicker.hidden = YES;
textField.text = textFieldValue;
textField.placeholder = self.title;
[textField becomeFirstResponder];
I tackled the same problem with more Core Data app. I also adapted the Core Data Books app. If you notice, in the original app, they use a BOOL variable (editingDate) to decide whether to show the date picker or not. I created a second BOOL variable, ('editingTextView`) and just change those BOOL variables depending on what needs to be edited. It may not be the most efficient way, but it is easy to program, and easy to follow what is already there in Core Data Books.

Typecasting array object

I struct at a point in my application.I have an array object called time and a global int variable as index..so when I need to use both I need to type cast array object to integer value.How can I do this?Please help..
NSArray *time=[NSArray arrayWithObjects:#"1.08",#"1.12",#"1.14",#"1.18",#"1.20",#"1.24",#"1.25",#"1.29",#"1.30",#"1.34",#"1.45",#"1.50",#"1.51",#"1.55",#"1.56",#"2.00",#"2.01",#"2.06",#"2.07",#"2.11",#"2.12",#"2.16",#"2.17",#"2.21",nil];
index = 0;
[self performSelector:#selector(startAnimation) withObject:self afterDelay:[time objectAtIndex:index]];
This is my code,but it is giving error and telling to typecast
Try [[time objectAtIndex:index] floatValue]. The objects in array are strings and you can get the float value by calling [myStr floatValue]. You can also use doubleValue here.

NSString function

I get a null return when i try out my NSString function.
//Track.m
static NSString* trackUrl;
//static NSString* getTrackNumberUrl;
#implementation Track
- (NSString*)trackUrl {
return #"http://site.com/?a=";
}
- (NSString*)setTrackNumberUrl:(NSString*)trackNumberUrl {
if (trackUrl != trackNumberUrl) {
return [trackUrl stringByAppendingFormat:trackNumberUrl];
}
return #"Error no trackNumber";
}
- (NSString*)getTrackNumberUrl:(NSString*)trackNumber {
return [[[self alloc] setTrackNumberUrl:trackNumber] autorelease];
}
#end
MainView.m, just to show the return answer in NSlog
- (NSString *) trackNumber{
return [track getTrackNumberUrl:#"86147224549XX"];
}
- (void)drawRect:(CGRect)rect {
NSLog(trackNumber);
}
I get a null return answer? Have i miss something? Thanks.
Edit some in Track.m
- (NSString*)setTrackNumberUrl:(NSString*)trackNumberUrl {
if (trackUrl != trackNumberUrl) {
return [trackUrl stringByAppendingString:trackNumberUrl];
}
return #"Error no trackNumber";
}
- (NSString*)getTrackNumberUrl:(NSString*)trackNumber {
return [[[Track alloc] setTrackNumberUrl:trackNumber] init];
}
This is how it should work.
getTrackNumberUrl --> setTrackNumberUrl --> trackUrl (return) --> setTrackNumberUrl + trackNumber --> getTrackNumberUrl (trackNumberUrl = trackUrl + trackNumber)
I have this code to set reference to Track
#class Track;
#interface MainView : UIView {
Track *track;
}
#property (nonatomic, retain) IBOutlet Track *track;
Well if don't should use self alloc, what should i use?
You have a lot of problems with your code.
return [trackUrl stringByAppendingFormat:trackNumberUrl];
You should not use an arbitrary string as a format, because if it contains a format specifier like "%d" then the method will go looking for a variable that isn't there, and will likely crash. You should use stringByAppendingString: instead. However, that doesn't seem to be what you want here, since the method name is setTrackNumberUrl:. If you want to change the value of the trackUrl variable, you can't call stringByAppendingFormat:; all that does is return a new string and leave the original alone. I think you simply want something like
[trackUrl release];
trackUrl = [trackNumberUrl retain];
Another problem:
return [[[self alloc] setTrackNumberUrl:trackNumber] autorelease];
In this context, self is an instance of Track. An instance won't understand the alloc message, that must be sent to a class. It will return a new instance, to which you should send an init message. So you would do something like [[Track alloc] init].
NSLog(trackNumber);
The first parameter to NSLog is a format string, so for the same reasons as above you shouldn't use a variable, you should do something like this: NSLog(#"%#", trackNumber); That line of code prints the value of the variable, trackNumber. Considering that you have a method named trackNumber just above it, I wonder if what you really want to do is call the method and get the result. In that case, you need to write it as [self trackNumber] which will call the method and return an NSString.
Most probably track is nil in the trackNumber - have you set it to a correct reference to a Track object?
Also, this code
- (NSString*)getTrackNumberUrl:(NSString*)trackNumber {
return [[[self alloc] setTrackNumberUrl:trackNumber] autorelease];
}
is incorrect. Why are you using [self alloc]? You're allocating a new Track object (using a static method on an object reference, not on a class name, which is an error), setting it's track number URL, and returning an autoreleased NSString, but you're leaking the Track object you allocated.
return [trackUrl stringByAppendingFormat:trackNumberUrl];
I'm not sure bout this one,
try using it as a format for string.
return [trackUrl stringByAppendingFormat:#"%#",trackNumberUrl];

Simple layer problem [iphone]

Basically I'm sorting through objects in an array by y value (The furthest down the page is at the start of the array) but I'm having a bit of trouble. I assign all of the UIImageViews in an array a value:
for (UIImageView *Blocky in objectsArray){
[Blocky.layer setValue:[NSString stringWithFormat: #"%f",
Blocky.center.y] forKey:#"value"];
}
Because it's a UIImageView I have to put layer after "Blocky" otherwise I get the following error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[<UIImageView 0x3d44880>
setValue:forUndefinedKey:]: this class
is not key value coding-compliant for
the key value.'
My problem is when I'm sorting it I don't know where to put the ".layer" so I get the same problem because UIImageViews can't deal with keys on there own. Here is my sorting code:
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"value" ascending:YES];
[objectsArray sortUsingDescriptors:[NSArray
arrayWithObject:sortDescriptor]];
[sortDescriptor release];
Thanks in advance,
Ozzie
Use the NSMutableArray sortUsingFunction:context: method:
// top of file
static NSInteger compareImageHeights(id image1, id image2, void* context) {
CGFloat temp = ((UIImageView*)image2).center.y - ((UIImageView*)image1).center.y;
return (temp>0)?NSOrderedAscending:(temp<0)?NSOrderedDescending:NSOrderedSame;
}
// within file somewhere
[objectsArray sortUsingFunction:compareImageHeights context:NULL];
The reason the function is required (and you can't just use sortUsingSelector: or sortUsingSortDescriptor:) is that you can't specify a KVC key to identify just the y component only as a sort variable.
Edit: Changed center.y to size.height.
Edit: Oops. Changed size.height back to center.y. Fixed type to UIImageView rather than UIImage. It seems KVC objects can in theory support arbitrary keys, but some will and some won't.
Are you sure CALayer is supposed to accept arbitrary KVC keys? This looks wrong to me.
Shouldn't you extract the heights to a buffer of structures and qsort that?
eg
I think it would be something like this:
//
// before #implementation sections
//
typedef struct __MySortEntry {
UIImageView* image;
CGFloat height;
} MySortEntry, *PMySortEntry;
static int compareMySortEntry (const void * a, const void * b)
{
CGFloat temp =( ((PMySortEntry)a)->height - ((PMySortEntry)b)->height );
return (temp<0)?-1:(temp>0)?1:0;
}
//
// in #implementation section somewhere
//
NSMutableData* mutable = [[NSMutableData alloc] initWithLength:
sizeof(MySortEntry)*objectsArray.count];
PMySortEntry entries = (PMySortEntry)mutable.mutableBytes;
for (int c = 0; c < objectsArray.count; c++) {
entries[c].image = (UIImageView*)[objectsArray objectAtIndex:c];
entries[c].height = entries[c].image.center.y;
}
qsort(entries, objectArray.count, sizeof(MySortEntry), compareMySortEntry);
for (int c=0; c < objectArray.count; c++) {
UIImage* imageInSequence = entries[c].image;
// do something with images **in sequence**
}
[mutable release];
Edit: Changed center.y to size.height.
Edit: Changed size.height back to center.y. Oops.
Edit: Changed UIImage to UIImageView.
Why not set the tag property on each view as you create them based on the height and retrieve them by tag?