NSNumber numberWithBool not an objective-c object - objective-c

I'm need to store some bool values in NSMutableDictionary, so I've founded a solution: using a [NSNumber numberWithBool] to make an object from bool.
It's work fine with value YES, but with NO it sometimes work fine, and sometimes result is "Not an objective-c object".
MyCode:
$ //sometimes fine, but sometimes "not an objective-c object"
$ NSNumber* nsn = [NSNumber numberWithBool:NO];
I'm new to Objective-C, so i'm sorry if this is basic problem, but i really stuck with it.
Thanks for help.

The object returned by numberWithBool and initWithBool seems to be initializing the NSNumber by a string and when you map the object in a dictionary it takes NSValue which indeed is null. Hence the dictionary will say it as null.

Try either of:
NSObject * y1 = #(YES) ;
NSObject * n1 = #(NO) ;
NSObject * y2 = #YES ;
NSObject * n2 = #NO ;
Another example:
NSDictionary * testDict = #{
#"key1": #YES
, #"key2": #NO
} ;
BOOL b = [testDict[#"key1"] boolValue] ;

Dude. Why don't you just create your own class:
#interface Fool
{
bool _amIFool;
}
#property bool amIFool;
#end
#implementation
-(bool)amIFool
{
return _amIFool;
}
-(void)setAmIFool:(bool)amIFool
{
_amIFool = amIFool
}
#end
Then you can shove it in a dictionary. Above code is just an example. You can write something better....
EDIT: You can even write a comparator, so you could directly do comparisons and stuff. And even write a convenience method so it is easy to initialise...
EDIT: Just FYI, my initial implementation was called "Cool". But since I'm not cool, I chose "Fool". You can do either.

Related

Negate a Boolean stored in an NSNumber

I've got a managed object with an NSNumber that's just a Boolean value. When the user clicks a button I want to toggle that.
self.item.completed = [NSNumber numberWithBool:![self.item.completed boolValue]];
Is there a cleaner (or perhaps just more compact) way that I'm missing?
There is little you can do to the process of producing the negated value, but you can make the syntax of invoking it look less bulky by hiding your code in a category:
#interface NSNumber ( NegateBoolean )
-(NSNumber)negateBool;
#end
#implementation NSNumber ( NegateBoolean )
-(NSNumber)negateBool{
return [NSNumber numberWithBool:![self boolValue]];
}
#end
Now you can use the new method like this:
self.item.completed = [self.item.completed negateBool];
You could also set up an NSArray with inversions, and use it as follows:
NSArray *inversions = [NSArray arrayWithObjects:[NSNumber numberWithBool:YES], [NSNumber numberWithBool:NO], nil];
self.item.completed = [inversions objectAtIndex:[self.item.completed boolValue]];
You could consider setting up a "wrapper" getter and setter on self.item for a property, maybe called completedValue, that deals in BOOLs instead of NSNumbers. Might look a little like:
- (BOOL)completedValue {
return [self.completed boolValue];
}
- (void)setCompletedValue:(BOOL)value {
self.completed = [NSNumber numberWithBool:value];
}
Then your call just becomes:
self.item.completedValue = !self.item.completedValue;
Another way to approach this without the use of additional category method on NSNumber is to use the ternary operator and the NSNumber boolean literals:
self.item.completed = self.item.completed.boolValue ? #NO : #YES;
This should work with any recent version of Xcode but in particular it requires LLVM v4.0 or clang v3.1.

Cannot Get Data from Custom Class

I looked around for an answer to this because it seems simple but I could not seem to find something that suffised. I am trying to test a program I have with fake data. I created a StudentData class that possesses a attributes for a student and also has an array to hold them all.
When another class needs them they call a getStudent method (which is the only public part of this class thus far) and sends an ID number to get the name of that student back.
My problem is that I cannot figure out how to parse through the student array to match the student ID numbers with the one that was passed in. Holding the same problem, I cannot figure out how to pull the name out of a student object either.
Here is my code so far:
// StudentData.m
#import "StudentData.h"
#interface StudentData() {
NSString *ID;
NSString *firstName;
}
#property (nonatomic, strong) NSMutableArray *studentArray;
#end
#implementation StudentData
#synthesize studentArray = _studentArray;
- (NSMutableArray *)studentArray {
if(!_studentArray) _studentArray = [[NSMutableArray alloc] init];
return _studentArray;
}
- (void)awakeFromNib {
NSArray *idA = [NSArray arrayWithObjects:#"111", #"685", nil];
NSArray *fnA = [NSArray arrayWithObjects:#"Mark", #"Sam", nil];
for(int i = 0; i < idA.count; i++) {
StudentData *tempCurrentStudent = [[StudentData alloc] init];
ID = [idA objectAtIndex:i];
firstName = [fnA objectAtIndex:i];
[self.studentArray addObject:tempCurrentStudent];
}
}
- (NSString *)getStudentsFirstName:(NSString *)studentID {
NSString *firstName;
for(int i = 0; i < self.studentArray.count; i++) {
if([studentID isEqualToString:[[self.studentArray objectAtIndex:i] self.firstName]]) { // ERROR
fN = [[self.studentArray objectAtIndex:i] self.firstName]; // ERROR
}
}
return firstName;
}
#end
The Error I keep getting is: Expect ']' and the error is pointing to the "self.firstName" lines.
If I use "[self.studentArray objectAtIndex:i].firstName;" I get the error: Property 'firstName' not found on object of type 'id' I even get this error if I make "firstName" a property (both local or public). This makes sense because the array is technically filled with 'id' types. I also know that unlike java I cannot use generics or anything like that.
Any help would be much appreciated and if it needs clarification please let me know! By the way this is for an ipod/ipad app if that helps at all.
Thanks!
Two things :
You're having a name conflict here. You are having a local variable called firstName and the parameter passed to your problem function has the same name.
firstNameis NOT a property unless you define it as one. In this case it's just a normal local variabel. Means that you can't access it using self.firstName but just by firstName. That's one of the reason the coding guidelines say that you should name local variables starting with an underscore ( as you are already doing in the studentArrayproperty). This way you can distinguish if it is a local variable or a property.
Best,
Flo

Objective-C accessing float getters with variable names

Let's say I have an NSArray called myArray of NSStrings (#"a0",#"a1",#"a2")
Then in a fast enumeration I loop into my array to build properties according to that NSStrings. I've got a problem accessing that properties.
I'm trying something like that :
#property (nonatomic) float a0propertyLow;
#property (nonatomic) float a0propertyHigh;
#property (nonatomic) float a1propertyLow;
#property (nonatomic) float a1propertyHigh;
..
.. etc.
for (NSString *aPos in myArray) {
NSString *low = [NSString stringWithFormat:#"%#propertyLow",aPos];
NSString *high = [NSString stringWithFormat:#"%#propertyHigh",aPos];
SEL lowSel = NSSelectorFromString(low);
SEL highSel = NSSelectorFromString(high);
if ([self respondsToSelector:lowSel]&&[self respondsToSelector:highSel]) {
id sumPartOne = [self performSelector:lowSel];
id sumPartTwo = [self performSelector:highSel];
float bla = (float)sumPartOne + (float)sumPartTwo;
}
}
I know my code is wrong but I don't know how to make it work.
My problem is that lowSel and highSel are getters which returns float but the perform selector method returns id which is ok for an object but not for floats.
So, how can I access my float getters with variable names ? I'm sure answer must be simple but it seems that my mind is looking for something complicated (and which obviously doesn't work) so I'm asking for help :)
Thank you very much for your help
You can't use performSelector: to call a method that returns a scalar value. The documentation for performSelector: clearly says what you have to do:
For methods that return anything other than an object, use NSInvocation.
An NSInvocation is a little more complex to set up but more flexible regarding arguments and return types.
In your case, it is probably easier to use Key-Value Coding instead:
[self valueForKey:low];
takes the return type into account and will automatically wrap the float in an NSNumber.
If you really need to use these getter methods, you can change your properties to double and use objc_msgSend_fpret():
#include <objc/runtime.h>
#include <objc/message.h>
double arg0 = objc_msgSend_fpret(self, lowSel);
If you can avoid getters (I know, that's not good practice, but anyway, it works for sure with the following method), and use the instance variables directly:
void *object_getIvarPtr(id obj, const char *name)
{
if (!obj || !name)
{
return NULL;
}
Ivar ivar = object_getInstanceVariable(obj, name, NULL);
if (!ivar)
{
return NULL;
}
return ((char *)obj + ivar_getOffset(ivar));
}
float arg0 = *(float *)object_getIvarPtr(self, [lowSel UTF8String]);
Hope this helps.
One way you can do is convert your floats into objects at runtime such as:-
NSString *str=[NSSTring stringWithFormat:#"%f",yourFloatValue];
and then u can retrive it using
[str floatValue];

When putting an Outlet in Xcode into a variable, don't know what kind of pointer to use?

So I was going through Cocoa Programming for Mac OS X for Dummies by Erick Tejkowski. After doing the calculator example, I got the basics of Objective-C in Xcode, since I know basic stuff. I got that to put what's in a text field into a variable, you first have to put the text field as an outlet in the header file like this:
#import <Cocoa/Cocoa.h>
#interface Mah_Application__It_is_awesomeAppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *window;
IBOutlet id hi;
}
- (IBAction)Calculate:(id)sender;
#property (assign) IBOutlet NSWindow *window;
#end
And then you put it in a variable like so:
- (IBAction)Calculate:(id)sender
{
int something;
hi = [hi intValue];
}
However, when I want a Boolean value, like a checkbox or something, or perhaps even a radio group, I don't know what pointer to use in place of intValue. For a moment, assume the variable hi is now a boolean. I tried this:
- (IBAction)Calcluate:(id)sender
{
BOOL something;
something = [hi BOOL];
}
but it says that's not a valid pointer. What should I use, then?
boolValue is defined for NSString and NSNumber, so it depends on what type hi is
- (IBAction)Calcluate:(id)sender
{
BOOL something = [hi boolValue];
}
Edit (I re-read the question and you might want what the other answer from Stew suggested):
BOOL myBool = [#"1" boolValue];
myBool = [someObject boolValue];
These are some of the conversion methods for NSString - Also see the NSString Reference Here:
- (double)doubleValue;
- (float)floatValue;
- (int)intValue;
- (NSInteger)integerValue;
- (long long)longLongValue;
// (boolValue) Skips initial space characters (whitespaceSet),
// or optional -/+ sign followed by zeroes.
// Returns YES on encountering one of "Y", "y", "T", "t", or a digit 1-9.
// It ignores any trailing characters.
- (BOOL)boolValue;
Also, from NSNumber Class Reference:
boolValue Returns the receiver’s value as a BOOL.
- (BOOL)boolValue
Return Value The receiver’s value as a BOOL,
converting it as necessary.
Special Considerations Prior to Mac OS X v10.3, the value returned
isn’t guaranteed to be one of YES or NO. A 0 value always means NO or
false, but any nonzero value should be interpreted as YES or true.
Try this:
[NSNumber numberWithBool:YES]
[NSNumber numberWithBool:NO]
[NSNumber numberWithInt:1]
[NSNumber numberWithFloat:0.25]
// etc...
- (IBAction)Calcluate:(id)sender
{
BOOL something;
something = [hi [NSNumber numberWithBool:BOOL]];
}
NSNumber reference
Since things like BOOL, NSInteger, NSUInteger, etc are not pointers, they cannot do certain things like be values for a dictionary, etc. For this purpose, NSNumber was created. It wraps these types in a class so they can be used as arguments for passing to selectors, or stored in NSDictionary's.
Here is a common thing I do:
[self.myLoadingView performSelectorOnMainThread:#selector(setHidden:) withObject:[NSNumber numberWithBool:YES] waitUntilDone:YES];

Is there a concise way to map a string to an enum in Objective-C?

I have a string I want to parse and return an equivalent enum. I need to use the enum type elsewhere, and I think I like how I'm defining it. The problem is that I don't know a good way to check the string against the enum values without being redundant about the order of the enums.
Is there no option other than a big if/else?
typedef enum {
ZZColorRed,
ZZColorGreen,
ZZColorBlue,
} ZZColorType;
- (ZZColorType)parseColor:(NSString *)inputString {
// inputString will be #"red", #"green", or #"blue" (trust me)
// how can I turn that into ZZColorRed, etc. without
// redefining their order like this?
NSArray *colors = [NSArray arrayWithObjects:#"red", #"green", #"blue", nil];
return [colors indexOfObject:inputString];
}
In Python, I'd probably do something like the following, although to be honest I'm not in love with that either.
## maps url text -> constant string
RED_CONSTANT = 1
BLUE_CONSTANT = 2
GREEN_CONSTANT = 3
TYPES = {
'red': RED_CONSTANT,
'green': GREEN_CONSTANT,
'blue': BLUE_CONSTANT,
}
def parseColor(inputString):
return TYPES.get(inputString)
ps. I know there are color constants in Cocoa, this is just an example.
try this: Map enum to char array
Pseudo code.. untested.
int lookup(const char* str) {
for(name = one; name < NUMBER_OF_INPUTS; name++) {
if(strcmp(str, stats[name]) == 0) return name;
}
return -1;
}
A more objective-c'ish version of the code could be:
// build dictionary
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
for(i=0; i<number_of_strings; i++) {
[dict setObject:[NSNumber numberWithInteger:i] forKey:[NSString stringWithUTF8String:names[i]]];
}
// elsewhere... lookup in dictionary
id obj = [dict objectForKey:name];
if(obj) return [obj intValue];
return -1;
This has already been answered: Converting between C enum and XML
Basically, you wind up defining corresponding strings when you define your enum, and then you use a category on NSArray so that you can do this:
static NSArray* colorNamesArray = [[NSArray alloc] initWithObjects:colorNames];
//colorNames is a nil-terminated list of string literals #defined near your enum
NSString* colorName = [colorNamesArray stringWithEnum:color];
//stringWithEnum: is defined with a category
Sure, the #define is a little ugly, but the code above, which is what you'll work with most of the time, is actually pretty clean.
I was never satisfied with any of the suggestions. (But I appreciate the effort that went into them.) I tried a few of them but they didn't feel good or were error-prone in practice.
I ended up created a custom dictionary to map integers to strings which feels a lot better because it's Cocoa through and through. (I didn't subclass NSDictionary in order to make it harder to misuse.)
#interface ZZEnumDictionary : NSObject {
NSMutableDictionary *dictionary;
}
+ (id)dictionary;
+ (id)dictionaryWithStrings:(id)firstString, ...;
- (NSString *)stringForInt:(NSInteger)intEnum;
- (NSInteger)intForString:(NSString *)stringEnum;
- (BOOL)isValidInt:(NSInteger)intEnum;
- (BOOL)isValidString:(NSString *)stringEnum;
- (BOOL)stringEquals:(NSString *)stringEnum intEnum:(NSInteger)intEnum;
- (BOOL)setContainsString:(NSSet *)set forInt:(NSInteger)intEnum;
- (NSArray *)allStrings;
#end
#interface ZZEnumDictionary ()
- (void)setInt:(NSInteger)integer forString:(NSString *)string;
#end