Convert a CFNumberRef to NSInteger - objective-c

#import "someClass.h"
#implementation someClass
- (NSInteger *)checkWakeOnLan {
SCDynamicStoreRef ds = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("myapp"), NULL, NULL);
CFDictionaryRef dr = SCDynamicStoreCopyValue(ds, CFSTR("State:/IOKit/PowerManagement/CurrentSettings"));
CFNumberRef wol=CFDictionaryGetValue(dr, CFSTR("Wake On LAN"));
CFRelease(dr);
CFRelease(ds);
here my problem, how to convert CFNumberRef to NSInteger,
i tryed again and again, but got anytime
"makes integer from pointer without cast"
NSInteger *value = [... ?];
return value;
}
- (IBAction)doStuff:(NSButton *)sender {
[myBevelButton setState:[self checkWakeOnLan]]; //setState takes NSInteger
//myBevelButton defined elsewhere, shows different icons
}
#end

Use this:
//assuming you want to convert wol to NSNumber and then to NSInteger
NSNumber *nsnumber = (NSNumber*)wol;
NSInteger value = [nsnumber integerValue];
*NOTE: You rarely need an NSInteger pointer. In your case you can quite easily use NSInteger. Also you need to change the method as - (NSInteger)checkWakeOnLan

Related

ObjC NSNumber stores pointer to Object instead of returned Value

I wrote my own Objective C class for dealing with 2D Vectors.
#interface Vector2D : NSObject {
struct _vecdata {
double x;
double y;
double x_norm;
double y_norm;
} _data;
}
#property(nonatomic) double x; //custom getter + setter
#property(nonatomic) double y; //custom getter + setter
#property(nonatomic, readonly) double xNormed; //custom getter
#property(nonatomic, readonly) double yNormed; //custom getter
+ (id)vectorWithX:(double)x_ext andY:(double)y_ext;
- (id)initWithX:(double)x_ext andY:(double)y_ext;
[...]
- (double)length;
#end
#import <math.h>
#implementation Vector2D
+ (id)vectorWithX:(double)x_ext andY:(double)y_ext{
return [[self alloc] initWithX:x_ext andY:y_ext];
}
- (id)initWithX:(double)x_ext andY:(double)y_ext {
if ((self = [super init])) {
_data.x = x_ext;
_data.y = y_ext;
[self normalize];
}
return self;
}
- (void)setX:(double)x {
_data.x = x;
[self normalize];
}
- (double)x {
return _data.x;
}
- (double)xNormed {
return _data.x_norm;
}
//setters and getter for y omitted (same as for x)
[...]
- (void)normalize {
double abs = [self length];
if (abs != 0) {
_data.x_norm = _data.x/abs;
_data.y_norm = _data.y/abs;
}
}
- (double)length {
return sqrt(_data.x*_data.x + _data.y*_data.y);
}
#end
Now I need to wrap the result of a call to an Vector2D instances length call to an NSNumber.
NSNumber* aNSNum = #([[Vector2D vectorWithX:someXValue andY:someYValue] length]);
Since I display the value of aNSNum later on, I noticed, that all the values (of all NSNumbers created that way) are around 1.40537252E+14 (since i call [aNSNum floatValue] later on).
So I recompiled and rerun the app and suddenly all the values were around 4.73280427E+14.
So I wondered, since the length of the Vectors should be in the range 0 to 20000, but not more.
I started playing around in the debugger to understand whats happening and got the following results:
(lldb) po [[Vector2D vectorWithX:someXValue andY:someYValue] length]
0x0000000000000001
(lldb) po (double)[[Vector2D vectorWithX:someXValue andY:someYValue] length]
84.693565280958623
(lldb) po (unsigned long)[[Vector2D vectorWithX:someXValue andY:someYValue] length]
1
(lldb) po #([[Vector2D vectorWithX:someXValue andY:someYValue] length])
84.69356528095862
(lldb) po #((double)[[Vector2D vectorWithX:someXValue andY:someYValue] length])
84.69356528095862
(lldb) po #((unsigned long)[[Vector2D vectorWithX:someXValue andY:someYValue] length])
1
(lldb) po aNSNum
140537282189312
(lldb) po [aNSNum floatValue]
1.40537286E+14
(lldb) po (unsigned long)[aNSNum doubleValue]
<Vector2D: 0x7fd162c85800>
(lldb) po (double)[(unsigned long)[aNSNum doubleValue] length]
84.693565280958623
So the really intresting part is about the second last line. So why is the pointer adress to the Vector2D Object stored in the NSNumber and not the value of the return value of the call to -length?
Since then I tried to change the bogus line of code to the following variants: (with no sucess)
NSNumber* aNSNum = #((double)[[Vector2D vectorWithX:someXValue andY:someYValue] length]);
NSNumber* aNSNum = #([((Vector2D *)[Vector2D vectorWithX:someXValue andY:someYValue]) length]);
NSNumber* aNSNum = #((double)[((Vector2D *)[Vector2D vectorWithX:someXValue andY:someYValue]) length]);
What worked so far was the following:
static SEL lengthSEL;
static IMP lengthIMP;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
lengthSEL = #selector(length);
lengthIMP = class_getMethodImplementation([Vector2D class], lengthSEL);
});
Vector2D* vec = [Vector2D vectorWithX:someXValue andY:someYValue];
double len = ((double (*) (id,SEL))lengthIMP)(vec,lengthSEL);
NSNumber* aNSNum = #(len);
But hope someone could help me to bring it back again to a one-liner. Or has a clue where it gets wrong...
Edit:
The compiler gets confused because the return type of
+ (id)vectorWithX:(double)x_ext andY:(double)y_ext;
is id; It does not know til runtime which length method it will get. Change the declaration to
+ (instancetype )vectorWithX:(double)x_ext andY:(double)y_ext;
and watch how much nicer things get.
Learn more at apple docs
You are relying on the literal syntax #(someNumber) to detect the type of someNumber and handle it properly, in this case, the (double) return value of your length method. The rules for number literals are here.
I think the safe thing to do, rather than typecast your variable and hope that the compiler picks up on it, is to create the number with explicit typing, that is,
NSNumber* aNSNum = [NSNumber numberWithDouble:[[Vector2D vectorWithX:someXValue andY:someYValue] length]];
NSNumber literals are great shorthand for constants and the like, but this seems a case where they make the code harder to understand instead of easier.

how do I set the values of an array in Objective-C using .notation?

Sorry I'm new to Objective-C and I'm still figuring out how to set properties using dot notation. I have 3 files as follows... towards the end(in main), I've set the radius property and the logged it, but I'm not sure how to set the center property because it's not a float (like radius) it's an array. I originally tried something like—
ball.center = {12, 14, 16} does not work.
My class .m file is:
#implementation Sphere
-(void)setCenter:(NSArray *)center radius:(float)radius {
_center = center;
_radius = radius;
}
#end
my class .h file is:
#interface Sphere : NSObject
#property (nonatomic) float radius;
#property (nonatomic, strong) NSArray *center;
-(void)setCenter:(NSArray *)center radius:(float)radius;
#end
and my main file is:
int main(int argc, const char * argv[])
{
#autoreleasepool {
Sphere *ball = [[Sphere alloc] init];
ball.radius = 34;
**// ball.center = an array, so how do we set that?**//
**//do I have to set the values of the array first?//**
NSLog(#"\nball radius %f\n", ball.radius);
**//I want to be able to log the values of the array the way I logged the radius.**
}
return 0;
}
I'll reply to your question "how I can create an array with numbers", but it looks like you don't need an array at all (read all the answer :-))
The first thing that you need is to initialize your array, for example:
NSArray *array = [NSArray arrayWithObjects:object1, object2, object3, nil];
There is also the literal that allows you to do the same thing with a friendly synthax
NSArray *array = #[object1, object2, object3];
Note that you can only insert objects in an NSArray and not primitives, so you need some NSNumber (a NSNumber is an object that represents a number).
You can use a class method to create a NSNumber
NSNumber *one = [NSNumber numberWithInt:1];
Or the literal synthax (usually preferred for its brevity)
NSNumber *one = #(1);
So, something like this will do
NSArray *array = #[#(1), #(2), #(3)];
However, I see that you want to represent the center, usually to do it, you don't use an array of objects, you use a CGPoint, that is not an array, it is a struct that contains 1 point (i.e. X and Y), and it is perfect to represent the center!
So the code will look like:
#implementation Sphere
-(void)setCenter:(CGPoint)center radius:(float)radius {
_center = center;
_radius = radius;
}
#end
and to use it:
Sphere *ball = [[Sphere alloc] init];
ball.center = CGPointMake(10, 20);
NSLog(#"my ball center x:%d y:%d", ball.center.x, ball.center.y);

How to add all decimal numbers in an NSMutableArray

I have a NSMutableArray which have some NSDecimalNumber in it, like (500,50.80,70,8000)
Now I want to add all those decimal numbers together.
I've tried to use
for (NSDecimalNumber *number in self.numbersArray)
{
NSDecimal *sum += [number decimalValue]
}
But failed.
A simple way to add all NSNumbers in an array is (similar to what #Mahonor said in a comment):
NSArray *myArray = ... // array of NSNumber (or NSDecimalNumber) objects
NSNumber *sum = [myArray valueForKeyPath:#"#sum.self"];
Contrary to what the Collection Operators: sum states, the numbers in the array are not converted to double, but to NSDecimal. Therefore, no precision is lost when adding decimal numbers. Even NSNumber objects which are not decimal numbers are converted to NSDecimal for the addition. The result of the summation is an instance of NSDecimalValue.
I verified (or tried to) that in two different ways. First, I ran this code
NSNumber *a = [NSNumber numberWithDouble:1.2];
NSNumber *b = [NSDecimalNumber decimalNumberWithString:#"-5.7"];
NSArray *myArray = #[a, b];
id sum = [myArray valueForKeyPath:#"#sum.self"];
and activated Objective-C message logging by setting the environment variable "NSObjCMessageLoggingEnabled=YES". As can be seen in the created "/tmp/msgSends-NNNN" file, decimalNumber (and not doubleValue) is sent to both number objects.
Second, I created a custom class implementing both decimalValue and doubleValue, and applied #sum.self to an array of objects of the custom class:
#interface MyClass : NSObject
#property (nonatomic, assign) double value;
#end
#implementation MyClass
- (NSDecimal)decimalValue
{
return [[NSNumber numberWithDouble:self.value] decimalValue];
}
- (double)doubleValue
{
return self.value;
}
#end
MyClass *a = [MyClass new]; a.value = 1.2;
MyClass *b = [MyClass new]; b.value = -5.7;
NSArray *myArray = #[a, b];
id sum = [myArray valueForKeyPath:#"#sum.self"];
By setting breakpoints in both methods, it is seen that only decimalValue is used for the summation (and valueForKeyPath:#"#sum.self" throws an exception if the class does not implement decimalValue).
One can also see that decimalValue is called from
-[NSArray(NSKeyValueCoding) _sumForKeyPath:]
and the assembler code for this method shows that NSDecimalAdd is uses to add the numbers.
Use - (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber
Take a look at NSDecimalNumber Class Reference
NSDecimalNumber *lNumber = [NSDecimalNumber zero];
for (NSDecimalNumber *number in self.numbersArray)
{
lNumber = [lNumber decimalNumberByAdding:number];
}
Manohar's suggestion in the comments is not bad. You can indeed use KVC collection operators to make a one-liner out of this: [myArray valueForKeyPath:#"#sum.doubleValue"];, but you potentially lose precision (depending on the numbers you have stored).
You're basically looking for "reduce" functionality; you need to chain calls to decimalNumberByAdding: so that each call has the succeeding element of the array as its argument. Doing this on an NSArray is easy enough, using performSelector:withObject:
#implementation NSArray (Reduce)
- (id)reduceUsingSelector: (SEL)sel
{
id res = [self objectAtIndex:0];
for( id obj in [self subarrayWithRange:(NSRange){1, [self count]-1}] ){
res = [res performSelector:sel withObject:obj];
}
return res;
}
#end
Use this like so: NSDecimalNumber * sum = [myArray reduceUsingSelector:#selector(decimalNumberByAdding:)];
The code you have isn't successful because NSDecimal is a struct, not an object; it shouldn't be declared as a pointer, and if it wasn't, you wouldn't be able to add it. That's not the right route to a solution.

How could I check for a particular property at runtime, along with its return type?

Since property named "age" would always have a selector named "age" as well, I could use respondsToSelector as this question suggests and that will tell me if a particular selector exists at runtime in any given object.
If a property named "age" exists, I can verify that. How could I know if that selector (the read method for that property) returns an object (id) or non-object (int)?
Is such type determination possible at runtime, or is the Objective-C way to always assume that someone implemented that method using the type I'm hoping it used, or can I also verify the return type?
This is using the latest Objective-C version (LLVM 4.1) in XCode 4.5.
Update: This is the utility-category-on-NSObject that I came up with:
- (NSString*) propertyType: (NSString*)propname
{
objc_property_t aproperty = class_getProperty([self class], [propname cStringUsingEncoding:NSASCIIStringEncoding] ); // how to get a specific one by name.
if (aproperty)
{
char * property_type_attribute = property_copyAttributeValue(aproperty, "T");
NSString *result = [NSString stringWithUTF8String:property_type_attribute];
free(property_type_attribute);
return result;
}
else
return nil;
}
While looking into this question I also wrote this handy-dandy utility method that
can list all the properties on this object:
- (NSArray*) properties;
{
NSMutableArray *results = [NSMutableArray array];
#autoreleasepool {
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char * aname=property_getName(property);
[results addObject:[NSString stringWithUTF8String:aname]];
//const char * attr= property_getAttributes(property);
//[results addObject:[NSString stringWithUTF8String:attr]];
}
if (properties) {
free(properties);
}
} // end of autorelease pool.
return results;
}
You could use class_copyPropertyList to get a list of properties declared in a class.
class_copyPropertyList
Describes the properties declared by a class.
And then property_getAttributes:
property_getAttributes
Returns the attribute string of an property.
Here you can find some more concrete hints and examples.
As a side note, the following statement:
Since property named "age" would always have a selector named "age" as well
is not correct, since a property can have custom getter and/or setter:
#property (nonatomic, getter=isImmediate) BOOL immediate;
EDIT:
Some sample code I found in another S.O. post:
const char * type = property_getAttributes(class_getProperty([self class], "myPropertyName"));
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString components separatedByString:#","];
NSString * typeAttribute = [attributes objectAtIndex:0];
NSString * propertyType = [typeAttribute substringFromIndex:1];
const char * rawPropertyType = [propertyType UTF8String];
if (strcmp(rawPropertyType, #encode(float)) == 0) {
//it's a float
} else if (strcmp(rawPropertyType, #encode(int)) == 0) {
//it's an int
} else if (strcmp(rawPropertyType, #encode(id)) == 0) {
//it's some sort of object
} else ....
One approach you can take, assuming you know the property name already, is to use the class_getProperty function. You can also use the property_copyAttributeValue() function to get just a particular attribute by name:
objc_property_t number_property = class_getProperty([MyClass class], "number");
char *number_property_type_attribute = property_copyAttributeValue(number_property, "T");
NSLog(#"number property type attribute = %s", number_property_type_attribute);
Will log:
2013-01-14 14:45:37.382 RuntimeFun[61304:c07] number property type
attribute = i
Assuming MyClass looks something like:
#interface MyClass : NSObject
#property (nonatomic) int number;
#end
#implementation MyClass
#end
One you have your type attribute string, you can then compare it to the various Objective-C type encodings. Once you're done with your comparison, be sure to call free() on your attribute string.

Get property name as a string

I need a way to pass a property and get the name assigned to it. Any suggestions?
#property (nonatomic, retain) MyObject *crazyObject;
NSString *str = SOME_WAY_TO_GET_PROPERTY_NAME(crazyObject);
// Above method should return #"crazyObject"
You can try this:
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([self class], &propertyCount);
NSMutableArray * propertyNames = [NSMutableArray array];
for (unsigned int i = 0; i < propertyCount; ++i) {
objc_property_t property = properties[i];
const char * name = property_getName(property);
[propertyNames addObject:[NSString stringWithUTF8String:name]];
}
free(properties);
NSLog(#"Names: %#", propertyNames);
It's as simple as this...expanding upon what Chuck already mentioned:
#ifndef STR_PROP
#define STR_PROP( prop ) NSStringFromSelector(#selector(prop))
#endif
You then use it like so:
NSString *strProp = STR_PROP(myProperty);
Background
Keep in mind that properties are really just, to quote Apple, "a syntactical shorthand for declaring a class’s accessor methods." In fact, by itself, the #property declaration doesn't even work. Your #synthesize statement translates the #property into the equivalent of two methods:
- (void)setCrazyObject:(MyObject *)something;
- (MyObject *)crazyObject;
Which one is used depends on the context surrounding your self.crazyObject. (#synthesize also creates a matching instance variable if you didn't do it yourself.) The offshoot of all this is that you can't really translate to and from a property with one single method.
Proposed Solution
You can use what Apple already provides:
NSString *foo = NSStringFromSelector(#selector(myClassProperty));
Or do something custom:
Given that self.crazyObject really translates to either [self crazyObject] or [self setCrazyObject:foo] by the time your code is running, ou'll probably need two methods, like:
- (NSString *)setterStringForProperty:(SEL)prop;
- (NSString *)getterStringForProperty:(SEL)prop;
You might then want at least 2 companion methods such as:
- (SEL)setterForPropertyName:(NSString *)propString;
- (SEL)getterForPropertyName:(NSString *)propString;
Within these methods, you can use the Foundation functions NSStringFromSelector and NSSelectorFromString to convert back and forth between SEL and NSString. Use whatever string manipulations you like to convert back and forth between your setter string (setCrazyObject) and your property name (crazyObject).
A complete solution is hard to provide without knowing the exact use case, but hopefully this provides some more clues for anyone trying to accomplish something similar. There might even be some useful things made possible by combining this approach with Oscar's answer.
Here is a function that returns the name of an ivar, so basically it not only returns the properties but any ivar of the class. I haven't found a way to get the property directly so I used the ivar trick.
#import <objc/objc.h>
/// -----
- (NSString *)nameOfIvar:(id)ivarPtr
{
NSString *name = nil;
uint32_t ivarCount;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
if(ivars)
{
for(uint32_t i=0; i<ivarCount; i++)
{
Ivar ivar = ivars[i];
id pointer = object_getIvar(self, ivar);
if(pointer == ivarPtr)
{
name = [NSString stringWithUTF8String:ivar_getName(ivar)];
break;
}
}
free(ivars);
}
return name;
}
After searching and debugging i find solution for me...
Added #import <objc/runtime.h>
Methods object_getIvar(id obj, Ivar ivar) send bad access and app crashes. i modify some code and it worked great:
+(NSString*)stringWithProperty:(id)property withClass:(id)controller
{
NSString *name = nil;
uint32_t ivarCount;
Ivar *ivars = class_copyIvarList([controller class], &ivarCount);
if(ivars)
{
for(uint32_t i=0; i<ivarCount; i++)
{
Ivar ivar = ivars[i];
name = [NSString stringWithUTF8String:ivar_getName(ivar)];
if ([controller valueForKey:name] == property)
{
break;
}
}
free(ivars);
}
return name;
}
Modifying the solution, it works when your object is allocated already, otherwise it returns nil:-
NSString * NSStringFromProperty(NSObject* property, NSObject* class)
{
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([class class], &propertyCount);
NSString *name = nil;
for (unsigned int i = 0; i < propertyCount; ++i)
{
name = [NSString stringWithUTF8String:property_getName(properties[i])];
NSObject *object = [class valueForKey:name];
if (object != nil && object == property)
{
break;
}
else
{
name = nil;
}
}
free(properties);
return name;
}
You can use
NSString *str = NSStringFromSelector(#selector(crazyObject));
The good thing about this approach is that:
Xcode will autocomplete word crazyObject for you.
When later on you will change the property name from crazyObject to myCrazyObject, Xcode will add a warning saying "unrecognized selector!" -- pretty good for debugging.
I use this method so often, that I even created a function, which allows to write less letters:
NSString * __nonnull sfs(SEL __nonnull theSelector)
{
if (!theSelector)
{
abort();
}
return NSStringFromSelector(theSelector);
}
Now your final solution can look like this:
NSString *str = sfs(#selector(crazyObject));
From Get property name as string, without using the runtime reference library, just define:
#define propertyKeyPath(property) (#""#property)
#define propertyKeyPathLastComponent(property) [[(#""#property) componentsSeparatedByString:#"."] lastObject]
And then you can do something like this:
NSLog(#"%#", propertyKeyPathLastComponent(appleStore.storeLocation.street)); //result: street
You may check my approach at Gist to get the string for a property with autocompletion and compile-time check.
How to use:
Get the property name for a class:
#interface AnyClass : NSObject
#property (strong) NSData *data;
#end
// == My approach ==
// C string for a class
PropertyNameForClass(AnyClass, data); // ==> "data"
// NSString for a class
PropertyStringForClass(AnyClass, data); // ==> #"data"
// Bad approach (no autocompletion; no compile-time check):
NSString *propertyName = #"data";
Get the property name for a protocol:
#protocol AnyProtocol
#property (strong) NSDate *date;
#end
// C string for a protocol
PropertyNameForProtocol(AnyProtocol, date); // ==> "date"
// NSString for a protocol
PropertyStringForProtocol(AnyProtocol, date); // ==> #"date"
Unconventional, hacky, ugly, late, but... as strong-named as it gets and works like a charm:
#define SOME_WAY_TO_GET_PROPERTY_NAME(p) p == p ? [[[[[[[NSString alloc] initWithCString:#p encoding:NSUTF8StringEncoding] componentsSeparatedByString:#"."] lastObject] componentsSeparatedByString:#" "] lastObject] stringByReplacingOccurrencesOfString:#"]" withString:#""] : #""
Sample usage:
NSLog(SOME_WAY_TO_GET_PROPERTY_NAME(self.customer.surname)); // surname
NSLog(SOME_WAY_TO_GET_PROPERTY_NAME([[self customer] birthDate])); // birthDate
...