So this is the code I have:
[dataCenter.tempPalette replaceObjectAtIndex:9 withObject:selectedColour];
Object 9 does exist, and it's currently an int (not sure if that matters). selectedColour is also an int. dataCenter.tempPalette is a NSMutableArray.
The error it gives me is this:
Passing argument 2 of 'replaceObjectsAtIndex:withObject:' makes pointer from integer without a cast.
Any ideas?
ints aren't objects. If you want to store integers in an NSMutableArray, you'll need to turn them into NSNumbers first using +[NSNumber numberWithInt:]. The error message is complaining that you're passing an int where a pointer (to an object) is required.
The second param of replaceObjectAtIndex needs to be a valid pointer to an object. From your description, it sounds like you are trying to pass in an int value ( selectedColour ), which is not a valid reference to an object.
I believe, instead of passing in the selectedColour int value, you want to pass a reference to the actual color object. This would probably be a reference to a UIColor object.
Also keep in mind, if you are trying to store many objects representing the same color. For purposes of using memory efficiently, you will probably want to store in your tempPallette array references pointing to the same color object for those entries that use the same color.
Hope this helps. Good Luck.
Related
I'm pretty new to iOS development, and I want to figure out if there's a good way to handle this issue. Basically, I'm making a technical calculator that returns some product specifications based on user input parameters. The product in question has specs for some, but not all user parameters, so I . In a constants file, I have a bunch of ATTEN_SPEC_X variables which are const double or const NSString *. Now, it's perfectly okay to be missing a spec, so my plan was to leverage NSArray's ability to hold different types and use introspection later to handle strings vs doubles before I report the returned specs.
Here's an incomplete example of one method I'm implementing. It's just a big conditional tree that should return a two-element array of the final values of spec and nominal.
- (NSArray *)attenuatorSwitching:(double *)attenuator{
double spec, nominal;
{...}
else if (*attenuator==0){
spec=ATTEN_SPEC_3; //this atten spec is a string!
nominal=ATTEN_NOM_3;
}
{...}
return {array of spec, nominal} //not actual obj-c code
So instead of making spec and nominal doubles, can I make them some other general type? The really important thing here is that I don't want to use any special handling within this method; another coder should be able to go back to the constants file, change ATTEN_NOM_3 to a double, and not have to retool this method at all.
Thanks.
The problem you'll run into is that NSArrays can't directly handle doubles. However, you can get around this if you start using NSNumber instances instead - you can return an NSArray * containing an NSString * and an NSNumber * with no problems. If you need even more general typing, the Objective-C type id can be used for any object instance (though still not with primitives; you can't make a double an id).
Later, when you get an array, you can use the NSObject method -isKindOfClass: to determine the type of object you're pulling out of the array, and deal with the string or number depending on the resultant type. If you need to convert your NSNumber back to a double, just use the NSNumber instance method -doubleValue to unbox your double. (+[NSNumber numberWithDouble:] goes the other way, giving you an NSNumber out of a double.)
If you're using a recent enough version of Xcode, you can even make these things literals, rather than having to litter calls to +numberWithDouble: all over the place:
return #[ #3, #"number of things" ]
Using Core-Data to hold various information, one of which is a 'number' attribute (Int(16)). I try to take it out of the database using:
number = (int)[info valueForKey:#"number"];
Unfortunately, this always gives some awful result, like 2895891275 when it should be returning 3.
Would appreciate any help, thanks!
valueForKey returns an object, not an int. The fact that you're having to cast it explicitly should be a warning sign. Try:
number = [[info valueForKey:#"number"] intValue];
To expand on #duskwuffs answer:
All values in Core Data are objects. When you set an attribute type to, say, Int16, Core Data will create an NSNumber object.
This code:
number = (int)[info valueForKey:#"number"]
... gives you a huge number because [info valueForKey:#"number"] returns an instance of NSNumber, an object, which you cast to an int. When you cast an object to an int you actually cast it's address in memory to an int and so end up with a large nonsensical number.
I need to use non-copyable objects as keys in the NSMutableDictionary which, by default, is not allowed. I understand the reasons for this not being allowed (retaining the key object, unlike the value object, is undesirable), but it seems like in my particular situation there could be a way around this.
The thing is that I'm only need to query the dictionary using the key's address, i.e. having the lookup predicate
if (providedKey == storedKey)
instead of
if ([providedKey isEqual:storedKey])
would be perfectly sufficient.
Is there a way of extracting the object's reference address (or other form of identity) as a copyable comparable object which I could use as a dictionary key instead of the object itself?
It seems that +[NSValue valueWithPointer:] might be what you want. It stores the pointer itself in an object that conforms to NSCopying, so that you can use it as a dictionary key. Retrieve the pointer using pointerValue.
You could use [NSString stringWithFormat:#"%p", someObject] as your key.
This will create a string with the object's address as a hex value.
You could use an nsnumber that represents the hash of the object.
you can drop down to the CoreFoundation APIs and define you own callbacks (among other things).
NSMutableDictionary is a CFMutableDictionary.
specifically, you want to create a CFMutableDictionary, and define your own CFDictionaryKeyCallBacks.
I want to do performSelector:withObject: but where the object is a CGFloat. So it's not actually an object. How can I do this?
the object I am performing the selector on is not mine, I can't modify it.
eg
[xyz performSelector:#selector(setOffset:) withObject:2];
(after posting I changed what I need to slightly to this:
[xyz performSelector:#selector(setOffset:) withObject:CGSizeMake(2,0)];
If you're trying to invoke an arbitrary selector against an object you don't have control over, you could use an NSInvocation to set up the selector, target, and arguments, and obtain the return value after the method has been executed.
Generally, though, there are simpler solutions.
try use IMP (A pointer to the start of a method implementation.)
SEL setOffsetSEL = #selector(setOffset:);
IMP setOffsetIMP = [XYZClass instanceMethodForSelector:setOffsetSEL];
setOffsetIMP(xyz, setOffsetSEL, 2);
You need an object to message. When I've needed to do something like this, I'll create a simple container class, shove the data in an instance and then perform a selector (often #selector(doIt:)) when needed.
If you can target 4.x, you can use blocks for this, too, typically.
(Without knowing more about what exactly you are trying to do, hard to get any more specific.)
object passed is a CGFloat. So it's not actually an object.
As you wrote immediately after, if you're passed an object, it can't be a CGFloat, as CGFloat is a typedef'ed primitive (float or double).
If you've been passed a number value as an object, likely you were passed an NSNumber somehow.
With zero context to your question, there's no way to be sure.
You can use:
[NSNumber numberWithFloat:(float)value]
I've been reading that when conforming to the NSCoding protocol and implementing the methods like -encodeWithCoder:, and encoding objects with i.e.
[coder encodeObject:self.someObject forKey:kSomeConstantToIdentifyFields];
this constant is used to keep track of that object. So later, with help of that constant, the appropriate "field" or whatever can be mapped to that object again (in this case an property).
But: Isn't this funny constant actually a random value when defined like this?
#define kSomeConstantToIdentifyFields #"fieldFooBar"
How does the system manage it to always assign the same value to that constant? Or did I get some stuff about this constants wrong? Is the value actually "fieldFooBar" and not some random number?
The key is a string - a name, if you will - that identifies a field in a dictionary. In this case, the dictionary is what will be written, or read from the archive that was created via the NSCoding protocol.
When you define the key like that, it's not necessarily constant, because it could be changed at some point (but only deliberately, not randomly by the system). As long as you don't change the #"fieldFooBar" string, it'll stay like that throughout the life of the program.
Keys are defined like this, not to be constant, but to be able to flag up compiler warnings and errors, such as spelling mistakes.
If you define the key once, and then refer to it by it's preprocessor symbol, if you mispell it, the compiler will throw an error saying it can't find that symbol. If you just used a string in it's place each time, then the compiler wouldn't know and wouldn't be able to warn you about it. Then you'd be on your own trying to figure out why your field isn't being decoded - because you're asking for the wrong key name.
Before your application compiles, a pre-compilation process occurs. The #define key value directive tells the pre-compiler "whenever you see key, replace it with value". It's not only that they're constants; it's as if you wrote #"fieldFooBar" all over your application yourself.
The reason not to do it yourself is to avoid mistakes, and I think Jasarien gave a great explanation for that in his answer.
Better way to define string constants is to use
static NSString *kSomeConstantToIdentifyFields = #"fieldFooBar";
That would same you some memory. Also, I suppose that isEqual: chects the object pointer, so having all constants point to one place is good.
Do constants always keep the same
value?
I believe that's why they're called constants. ;o)