ObjC: proper use of property and synthesize? - objective-c

Does anyone know why this code is running into compilation errors? I'm compiling it on Catalina using clang. I posted a similar issue here but that was when I was trying to compile using clang on Linux. I thought getA and setA are auto-generated by synthesize. Thanks!
#import <Foundation/Foundation.h>
#interface A: NSObject
#property int a;
#end
#implementation A
{
int a;
}
#synthesize a;
#end
int main (int argc, char * argv[])
{
#autoreleasepool {
A *a = [[A alloc] init];
[a setA:99];
int v = [a getA];
NSLog (#" %d\n", v);
}
return 0;
}
Compilation:
$ clang -framework Foundation otest0.m -o hello
otest0.m:23:16: warning: instance method '-getA' not found (return type defaults
to 'id') [-Wobjc-method-access]
int v = [a getA];
^~~~
otest0.m:3:12: note: receiver is instance of class declared here
#interface A: NSObject
^
otest0.m:23:9: warning: incompatible pointer to integer conversion initializing
'int' with an expression of type 'id' [-Wint-conversion]
int v = [a getA];
^ ~~~~~~~~
2 warnings generated.

The getter/setter pair is synthesized as
-(int)a;
-(void)setA:(int)val;
So you need:
int main (int argc, char * argv[])
{
#autoreleasepool {
A *a = [[A alloc] init];
[a setA:99];
int v = [a a];
NSLog (#" %d\n", v);
}
return 0;
}

Declaring a property with name a produces a getter with name a, not getA.
This is what the first warning is about: "instance method '-getA' not found"

This works on my system (macOS):
#import <Foundation/Foundation.h>
#interface A: NSObject
#property int a;
#end
#implementation A {
int a;
}
#synthesize a;
-(int) getMyValue {
return a;
}
#end
int main () {
#autoreleasepool {
A *a = [[A alloc] init];
[a setA:99];
NSLog (#"value = %d", [a getMyValue]);
}
return 0;
}
If file is saved as synth.m the terminal command is: clang synth.m -framework Foundation -o synth && ./synth

Related

How does the Xcode breakpoint system interact with memory management?

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?

Not all references released, 1 still live

I'm learning about retain and release methods for counting references in Objective-C, but Instruments says that is still living 1 reference of MyClass, the code:
#import <Foundation/Foundation.h>
#import "MyClass"
int main(int argc, const char * argv[])
{
#autoreleasepool {
MyClass *obj;
for (int i=0; i < 200000; i++){
obj = [[MyClass alloc] init];
[obj setSomeValue:100];
NSLog(#"itineration %i", i);
[obj release];
}
}//#autoreleapool
}//main
MyClass.h
#interface MyClass : NSObject
#property int someValue;
#end
Why Instruments shows "16LiveBytes" "1#Living" "199999#Transient" "200000#Overall" in MyClass? Should be 0 right?

Passing function as argument to Objective-C method

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];
}

CFDictionaryGetValue()

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.

I am trying to use respondsToSelector but unable to get expected output can anyone find what is wrong in my code?

#import "movie.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
movie *obj = [[movie alloc]init];
[obj findinterestofnum1:(int)200 num2:(int)4 num3:(int)5];
SEL suf = #selector(findinterestofnum1: num2:num3:);
BOOL sul = [obj respondsToSelector:suf];
if(sul)
{
NSLog(#"It is implememted");
}
else
{
NSLog(#" It is not implemented");
}
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
********-----
#interface movie : NSObject {
#private
}
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r;
#end
*******-------
#import "movie.h"
#implementation movie
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r
{
int a ;
a= (p*n*r/100);
NSLog(#"interest value is =%d",a);
}
- (void)dealloc
{
[super dealloc];
}
#end
i am trying to find whether method is implemented and if it is not it should print it is not implemented
#toddler, respondsToSelector just checks if the corresponding object can respond to that particular method. It doesn't do any checks on whether interface has that definition associated with it since it is a runtime check.
If you had removed the code from the implementation file (.m file) and not the interface, you would have got an error while executing it and you would have found that the BOOL sul is FALSE.