I could not able to get the value for the key.
I have a structure pt(which is the value) and a wTiId,wTiId1(which is the key).
I am sure that something wrong i'm doing in the below code but i could not figure out what
it is.
Timers.h
---------
#import <Foundation/Foundation.h>
struct session {
int a;
char c;
}pstruct;
#interface Timers : NSObject {
unsigned short wTiId;
unsigned short wTiId1;
}
-(void)timer;
#end
Timers.m
--------
#import "Timers.h"
#implementation Timers
-(id)init
{
if (self=[super init]) {
wTiId=71;
wTiId1=72;
}
return self;
}
-(void)dealloc
{
[super dealloc];
}
-(void)timer
{
struct session* pt = &pstruct;
pt->a=12;
pt->c='L';
CFDictionaryValueCallBacks cbvs = {0,NULL,NULL,NULL,NULL};
CFMutableDictionaryRef cfmdict = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks,&cbvs);
NSLog(#"Dict size:%d\n",((CFIndex)CFDictionaryGetCount(cfmdict)));
CFNumberRef tiId = CFNumberCreate(NULL,kCFNumberShortType,&wTiId);
CFNumberRef tiId1 = CFNumberCreate(NULL,kCFNumberShortType,&wTiId1);
CFDictionarySetValue(cfmdict,tiId,pt);
NSLog(#"Dict size:%d\n",((CFIndex)CFDictionaryGetCount(cfmdict)));
CFDictionarySetValue(cfmdict,tiId1,pt);
NSLog(#"Dict size:%d\n",((CFIndex)CFDictionaryGetCount(cfmdict)));
NSLog(#"The value is:%s",(CFDictionaryGetValue(cfmdict,tiId)));
CFRelease(tiId);
CFRelease(tiId1);
}
#end
main.m
------
#import <Foundation/Foundation.h>
#import "Timers.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Timers* time = [[Timers alloc]init];
[time timer];
[pool drain];
return 0;
}
output
------
2011-05-15 14:52:54.857 timer[3511:a0f] Dict size:0
2011-05-15 14:52:54.861 timer[3511:a0f] Dict size:1
2011-05-15 14:52:54.861 timer[3511:a0f] Dict size:2
2011-05-15 14:52:54.862 timer[3511:a0f] The value is:
I tried with the format specifier "%#" also.Nothing gets printed when CFDictionaryGetValue
() function is called.The return type of this function is const void*.
The result of CFDictionaryGetValue is what you put in the dictionary.
You have to cast the result of CFDictionaryGetValue to the right pointer type to access the structure members:
struct session *value = (struct session *) CFDictionaryGetValue(cfmdict,tiId);
NSLog(#"The value is %d and %c", value->a, value->c);
You cannot store structs in CFDictionarys, only pointers to structs will work. You cannot print the contents of the struct with the %s format specifier.
Related
Here's a little experiment:
#interface Model : NSObject
#property (copy) NSString *value;
-(instancetype)initWith:(NSString *)value;
#end
#implementation Model
-(instancetype)initWith:(NSString *)value {
self = [super init];
self.value = value;
return self;
}
#end
#import <Foundation/Foundation.h>
#import "Model.h"
void experiment(Model *m);
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Model *ma = [[Model alloc] initWith:[[NSUUID UUID] UUIDString]];
experiment(ma);
NSLog(#"yyy %#", [ma value]);
}
return 0;
}
void experiment(ModelA *m) {
NSString *testValue = nil;
testValue = [m value];
NSLog(#"xxx %#", testValue);
}
When run, this produces the following:
Hello, World!
xxx 6005A7B0-F71C-4755-B1BF-792D6296B716
yyy 6005A7B0-F71C-4755-B1BF-792D6296B716
Program ended with exit code: 0
But suppose I make this line:
testValue = [m value];
part of a breakpoint:
And this changes everything:
Hello, World!
(__NSCFString *) $0 = 0x000000010071e220 #"1C0DCB39-BFBB-4E67-A041-E6B58615BDFD"
xxx 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
yyy 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
*** -[CFString release]: message sent to deallocated instance 0x10071e220
And a crash. I see what's happening--the string is released once we exit the function scope, and the second time when the Model object is destroyed, which is an overrelease. But why doesn't the breakpoint (or more precisely, the lldb expression inside the breakpoint) handle the reference count correctly?
I'm trying to dynamically create a class with data loaded from JSON. I have successfully created the class, but still stuck at how to add several constants with the values loaded from the JSON.
For example, the JSON below:
"Josh": {
"age": 10
}
I want a class like
class Josh {
int age = 10;
}
However, I can only achieve
class Josh {
int age;
}
with the following code:
Class Josh = objc_allocateClassPair([NSObject class], "Josh", 0);
class_addIvar(Josh, "age", sizeof(int), rint(log2(sizeof(int))), #encode(int));
objc_registerClassPair(Josh);
// Below is the desired result
Josh j = [[Josh alloc] init];
NSLog([j age]); // prints 10
So can anybody answer me, how to add the primitive value 10 to this Ivar I've added? Thank you
What you are doing is almost certainly madness and you shouldn't be messing with it.
That said, the code you wrote doesn't even compile.
So let's fix it.
You can't declare Josh j, because Josh is a variable, not a type. Instead you can use id, which means “any Objective-C object”.
id j = [[Josh alloc] init];
You also can't say [j age] unless you declare an age method somewhere, so stick this somewhere:
#protocol Dummy <NSObject>
- (int)age;
#end
You also can't say NSLog([j age]) because [j age] returns an int, not an NSString *. So do this instead:
NSLog(#"%d", [j age]);
Now you'll find that you get an “unrecognized selector” error, because you didn't add an age method to your Josh class. To do that, you first have to import the Objective-C runtime:
#import <objc/runtime.h>
Then you can add an age method like this:
Ivar ageIvar = class_getInstanceVariable(Josh, "age");
ptrdiff_t ageIvarOffset = ivar_getOffset(ageIvar);
IMP ageImp = imp_implementationWithBlock(^int(id self) {
void *base = (__bridge void *)self;
return *(int *)((unsigned char *)base + ageIvarOffset);
});
class_addMethod(Josh, #selector(age), ageImp, "v#:");
Here's the complete, compilable, non-crashing program:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#protocol Dummy <NSObject>
- (int)age;
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Class Josh = objc_allocateClassPair([NSObject class], "Josh", 0);
class_addIvar(Josh, "age", sizeof(int), rint(log2(sizeof(int))), #encode(int));
Ivar ageIvar = class_getInstanceVariable(Josh, "age");
ptrdiff_t ageIvarOffset = ivar_getOffset(ageIvar);
IMP ageImp = imp_implementationWithBlock(^int(id self) {
void *base = (__bridge void *)self;
return *(int *)((unsigned char *)base + ageIvarOffset);
});
class_addMethod(Josh, #selector(age), ageImp, "v#:");
objc_registerClassPair(Josh);
// Below is the desired result
id j = [[Josh alloc] init];
NSLog(#"%d", [j age]); // prints 10
}
return 0;
}
But it still just prints “0“:
2018-06-25 15:07:53.179809-0500 madness[35050:5762222] 0
Program ended with exit code: 0
If you want to initialize age to 10, you need to override init in your Josh class. If you were writing the init method normally, it would look like this:
- (instancetype)init {
if (self = [super init]) {
_age = 10;
}
return self;
}
But we can only send to super in something the compiler recognizes as a method body, and a block (like we'll pass to imp_implementationWithBlock) doesn't count as a method body. So we have to do the [super init] part the hard way, by calling objc_msgSendSuper. To do that, we have to import another header:
#import <objc/message.h>
Then we can write the block that implements init:
IMP initImp = imp_implementationWithBlock(^id(id self) {
struct objc_super superInfo = {
.receiver = self,
.super_class = NSObject.self
};
id (*msgSendSuper)(struct objc_super *, SEL) = (id (*)(struct objc_super *, SEL))objc_msgSendSuper;
self = msgSendSuper(&superInfo, #selector(init));
if (self) {
void *base = (__bridge void *)self;
*(int *)((unsigned char *)base + ageIvarOffset) = 10;
}
return self;
});
class_addMethod(Josh, #selector(init), initImp, "##:");
Here's the complete program:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
#protocol Dummy <NSObject>
- (int)age;
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Class Josh = objc_allocateClassPair([NSObject class], "Josh", 0);
class_addIvar(Josh, "age", sizeof(int), rint(log2(sizeof(int))), #encode(int));
Ivar ageIvar = class_getInstanceVariable(Josh, "age");
ptrdiff_t ageIvarOffset = ivar_getOffset(ageIvar);
IMP ageImp = imp_implementationWithBlock(^int(id self) {
void *base = (__bridge void *)self;
return *(int *)((unsigned char *)base + ageIvarOffset);
});
class_addMethod(Josh, #selector(age), ageImp, "v#:");
IMP initImp = imp_implementationWithBlock(^id(id self) {
struct objc_super superInfo = {
.receiver = self,
.super_class = NSObject.self
};
id (*msgSendSuper)(struct objc_super *, SEL) = (id (*)(struct objc_super *, SEL))objc_msgSendSuper;
self = msgSendSuper(&superInfo, #selector(init));
if (self) {
void *base = (__bridge void *)self;
*(int *)((unsigned char *)base + ageIvarOffset) = 10;
}
return self;
});
class_addMethod(Josh, #selector(init), initImp, "##:");
objc_registerClassPair(Josh);
// Below is the desired result
id j = [[Josh alloc] init];
NSLog(#"%d", [j age]); // prints 10
}
return 0;
}
And here's the output:
2018-06-25 15:31:41.837748-0500 madness[35369:5786038] 10
Program ended with exit code: 0
New to Objective-C and trying to complete a final project for a class. I have created a method to set a date based on user input and am running into some trouble with the setter. User will first have to select option to add new entry and then program should ask user to enter a date and set date based on that input.
#import <Foundation/Foundation.h>
#interface Planner : NSObject {
NSNumber *date;
}
-(void) setDate:(NSNumber *)newDate;
-(NSNumber *) date;
#end
#implementation Planner
-(void) setDate:(NSNumber *) newDate
{
date = [[NSNumber alloc] initWithInt: newDate];
NSLog(#"Enter date");
scanf("%i", newDate);
}
-(NSNumber *) date;
{
return date;
}
#end
int main (int argc, const char * argv[])
{
int userAction;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Planner *newPlanner = [[Planner alloc] init];
NSLog(#"Please enter 1 to add a new entry and 2 to update an existing entry");
scanf("%i", userAction);
if (userAction == 1) {
[newPlanner setDate];
}
else
NSLog(#"will update");
[pool drain];
return 0;
}
-(void) setDate:(NSNumber *) newDate;
setDate is supposed to receive an argument of type NSNumber*. But you are calling the method with out passing any parameter.
[newPlanner setDate]; // [newPlanner setDate: shouldPassNSNumberArgument];
Like -
[newPlanner setDate:[NSNumber numberWithInt:10] ];
I'd like to pass a C function as an argument to an Objective-C method, to then act as a callback. The function has type int (*callback)(void *arg1, int arg2, char **arg3, char **arg4).
I keep getting the syntax wrong. How do I do this?
As a slightly more complete alternative to KKK4SO's example:
#import <Cocoa/Cocoa.h>
// typedef for the callback type
typedef int (*callbackType)(int x, int y);
#interface Foobar : NSObject
// without using the typedef
- (void) callFunction:(int (*)(int x, int y))callback;
// with the typedef
- (void) callFunction2:(callbackType)callback;
#end
#implementation Foobar
- (void) callFunction:(int (*)(int x, int y))callback {
int ret = callback(5, 10);
NSLog(#"Returned: %d", ret);
}
// same code for both, really
- (void) callFunction2:(callbackType)callback {
int ret = callback(5, 10);
NSLog(#"Returned: %d", ret);
}
#end
static int someFunction(int x, int y) {
NSLog(#"Called: %d, %d", x, y);
return x * y;
}
int main (int argc, char const *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Foobar *baz = [[Foobar alloc] init];
[baz callFunction:someFunction];
[baz callFunction2:someFunction];
[baz release];
[pool drain];
return 0;
}
Basically, it's the same as anything else, except that without the typedef, you don't specify the name of the callback when specifying the type of the parameter (the callback parameter in either callFunction: method). So that detail might have been tripping you up, but it's simple enough.
The following peice of code worked,absolutely fine . just check
typedef int (*callback)(void *arg1, int arg2, char **arg3, char **arg4);
int f(void *arg1, int arg2, char **arg3, char **arg4)
{
return 9;
}
-(void) dummy:(callback) a
{
int i = a(NULL,1,NULL,NULL);
NSLog(#"%d",i);
}
-(void) someOtherMehtod
{
callback a = f;
[self dummy:a];
}
I am not getting the correct output.
data.m
---------
#implementation data
- (id) initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize
{
//if(self=[super init])
//{
// Initialize the member variables
m_uSessionId = 0x00;
m_chSequenceChar= 0;
// Initialize values from derived class
m_nMessageId = uMessageId;
m_pData = (int*)pData;
m_uDataSize = (int)uDataSize;
//}
return self;
}
- (BOOL) TxCreateImage:(id) pData withLen:(id)uLen
{
sprintf((char *)pData,"%x%d%d%d",ASCII_STX,m_uSessionId,m_chSequenceChar,m_nMessageId);
//uLen = ENCODED_MSG_DATA_OFFSET;
NSLog(#"%s",pData);
return YES;
}
- (void)dealloc
{
[super dealloc];
}
#end
data_derived.m //derived class of data
--------------------
#implementation requestSession
- (id)init
{
char* pData[4096];
size_t asize = sizeof(st);
self=[super initWithID:ID withData:(id)pData withSize:asize];
if (self) {
data* dat = [[data alloc]init];
[dat TxCreateImage:self withLen:self];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
#end
test2.m
---------
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
requestSession* session = [[requestSession alloc]init];
[pool drain];
return 0;
}
remote.h
-----------
#import <Foundation/Foundation.h>
struct RMH_REQUEST_SESSION_MSG //Message Data
{
int uDeviceID;
int uProtocolVersion;
int uReserved[5];
};
typedef enum
{
RM_REQUEST_SESSION = 0x11 //Message ID
} REMOTE_MESSAGE_ID;
#interface remote : NSObject {
}
#end
data.h
---------
#import <Foundation/Foundation.h>
#import "remote.h"
#interface data : NSObject {
#public
int m_nMessageId; //Message ID
int m_uSessionId; //Session ID
int m_chSequenceChar; //Sequence ID
int* m_pData; //Integer buffer to carry data
int m_uDataSize; //Datasize
}
- (id)initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize;
- (void)dealloc;
- (BOOL) TxCreateImage:(id) pData withLen:(id)uLen;
//+ (id)CreateMessage:(REMOTE_MESSAGE_ID)nMessageNumber;
//+ (id)CreateMessage:(const int*)szMessageName;
#end
data_derived.h
---------------------
#import <Foundation/Foundation.h>
#import "data.h"
#define DECLARE_RS232_NEWMSG(ClassID)\
enum \
{ \
ID = ClassID \
}; \
#interface requestSession : data {
#public
DECLARE_RS232_NEWMSG(RM_REQUEST_SESSION);
struct RMH_REQUEST_SESSION_MSG st;
int size;
}
-(id)init;
-(void)dealloc;
#end
The expected output is
2 0 0 17
. But its printing me
2 0 0 0
.
I need to pass the values assigned in
initWithData method
in data.m to
TxCreateMessage
in data.m.
My answer was irrelevant since I missed something in your question. the problem is that you are casting a int * to char *, pointer casting is the root to many many issues (in this case, it's probably an endianess problem.)
If you want to use sprintf, use it on char*, not int*:
- (BOOL) TxCreateImage:(id) pData withLen:(id)uLen
{
char printStr[30];
sprintf(printStr,"%x%d%d%d",ASCII_STX,m_uSessionId,m_chSequenceChar,m_nMessageId);
//uLen = ENCODED_MSG_DATA_OFFSET;
NSLog(#"%s",printStr);
return YES;
}