__attribute__((const)) is a GCC attribution to check purity of the function execution.
I think this is being supported on Clang, but when I put this to a method, it doesn't seem to work.
#interface C1
- (id)method1 __attribute__((const));
#end
int a = 0;
#implementation C1
- (id)method1 __attribute__((const))
{
a++;
return nil;
}
#end
The code above doesn't generate any warning or error.
Is this attribution working on Clang? Or what should I do to make this to work?
The const attribute doesn't check the purity of the function. It declares the purity of the function, so the optimizer can eliminate calls to the function. It's up to you to actually make sure the function is pure.
Declaring a method const can not work in Objective-C because it contradicts the runtime's message passing mechanism. The documentation for const says:
Note that a function that has pointer arguments and examines the data pointed to must not be declared const.
Every Objective-C method has at least one (implicit) pointer argument: self. It is always examined as part of message passing (objc_msgSend()). That's what makes Objective-C dynamic.
Related
During a talk at the #Scale 2014 conference (around 32:30), Facebook presented their implementation of a declarative UI approach. The slides for a more detailed version of the talk can be found here.
Basically they presented a function call like this (I made my own simplified example from the example in the talk):
[CPInsetComponent
newWithStyle:{
.margin = 15
}
];
My question is: Is this valid ObjC code? I tried to implement this myself
typedef struct {
uint margin;
} CPInsetComponentStyle;
#interface CPInsetComponent : NSObject
+ (SomeOtherStruct) newWithStyle:(CPInsetComponentStyle)style;
#end
but I still get an "expected expression" error on the newWithStyle:{ line. Could you give me a hint how the method declaration would look like?
No, that's not valid Objective-C code. A C99 compound literal of struct type looks like this:
(TheStructType) { .field1 = initializer1, .field2 = initializer2 }
where the field designators are optional.
I can imagine that the code they were presenting was actually Objective-C++. In C++11, the compiler can insert implicit calls to constructors taking an initializer list if certain conditions are met; hence, often you can pass just an initializer list to a function.
The compiler probably doesn't know if your literal struct declaration is of the correct type. For compound literals you need to provide the type in parenthesis followed by a brace-enclosed list of initializers.
[CPInsetComponent newWithStyle:(CPInsetComponentStyle){
.margin = 15
}];
Why the compiler gives an error in this case of method declaration -
-(void) someMethod (void);
But approves this -
-(void) someMethod;
(SomeClass.h)
I've read that it is better to declare (void) in parameters than not declaring, but probalby I miss some point.
You cannot do this for Objective-C.
In Objective-C, every parameter must be after : e.g.
- (void)someMethod:(int)i;
- (void)someMethod:(int)i withString:(NSString *)string;
- (void)someMethod:(int)i :(int)i2 :(int)i3; // you can do this but is bad style
and it does not make sense to make something like
- (void)someMethod:(void)what_goes_here;
so if you want a method without parameter:
- (void)someMethod;
However you can do it in C/C++
void someMethod(void);
And I didn't see any benefit of declare void parameters (explicitly declare things is not always good).
Expanding on #xlc's answer
The answer is a difference in syntax between Objective-C and "normal" C/C++.
Way back in the origins of Unix and C days, late 60's/early 70's, when declaring (not defining) a function, you didn't need to specify how many arguments it accepted, or what types they needed to be. Nor did you need to specify whether or not it returned a value.
Later, folks realized that this would be a good idea, both for better error detection at compile time and for greater efficiency of generated code. So implementers added the ability to specify argument types in the function declaration. This was standardized as part of ANSI C in the late 80's.
However, there was a need to retain backwards compatibility with existing code. So a function declaration of foo() couldn't be assumed to mean "function with no arguments". To solve this, the void keyword was introduced. That allowed you to say foo(void) to mean "function named foo which takes no arguments".
When Objective-C was invented in the 90's, they added a new syntax for defining methods. Because there was no legacy code to deal with, they simply said that a method has to declare all its arguments; if there are none, then the method takes no arguments.
Objective-C still uses the void keyword to indicate that a method returns no value, though.
Clang adds a keyword instancetype that, as far as I can see, replaces id as a return type in -alloc and init.
Is there a benefit to using instancetype instead of id?
Yes, there are benefits to using instancetype in all cases where it applies. I'll explain in more detail, but let me start with this bold statement: Use instancetype whenever it's appropriate, which is whenever a class returns an instance of that same class.
In fact, here's what Apple now says on the subject:
In your code, replace occurrences of id as a return value with instancetype where appropriate. This is typically the case for init methods and class factory methods. Even though the compiler automatically converts methods that begin with “alloc,” “init,” or “new” and have a return type of id to return instancetype, it doesn’t convert other methods. Objective-C convention is to write instancetype explicitly for all methods.
Emphasis mine. Source: Adopting Modern Objective-C
With that out of the way, let's move on and explain why it's a good idea.
First, some definitions:
#interface Foo:NSObject
- (id)initWithBar:(NSInteger)bar; // initializer
+ (id)fooWithBar:(NSInteger)bar; // class factory
#end
For a class factory, you should always use instancetype. The compiler does not automatically convert id to instancetype. That id is a generic object. But if you make it an instancetype the compiler knows what type of object the method returns.
This is not an academic problem. For instance, [[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData] will generate an error on Mac OS X (only) Multiple methods named 'writeData:' found with mismatched result, parameter type or attributes. The reason is that both NSFileHandle and NSURLHandle provide a writeData:. Since [NSFileHandle fileHandleWithStandardOutput] returns an id, the compiler is not certain what class writeData: is being called on.
You need to work around this, using either:
[(NSFileHandle *)[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData];
or:
NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardOutput];
[fileHandle writeData:formattedData];
Of course, the better solution is to declare fileHandleWithStandardOutput as returning an instancetype. Then the cast or assignment isn't necessary.
(Note that on iOS, this example won't produce an error as only NSFileHandle provides a writeData: there. Other examples exist, such as length, which returns a CGFloat from UILayoutSupport but a NSUInteger from NSString.)
Note: Since I wrote this, the macOS headers have been modified to return a NSFileHandle instead of an id.
For initializers, it's more complicated. When you type this:
- (id)initWithBar:(NSInteger)bar
…the compiler will pretend you typed this instead:
- (instancetype)initWithBar:(NSInteger)bar
This was necessary for ARC. This is described in Clang Language Extensions Related result types. This is why people will tell you it isn't necessary to use instancetype, though I contend you should. The rest of this answer deals with this.
There's three advantages:
Explicit. Your code is doing what it says, rather than something else.
Pattern. You're building good habits for times it does matter, which do exist.
Consistency. You've established some consistency to your code, which makes it more readable.
Explicit
It's true that there's no technical benefit to returning instancetype from an init. But this is because the compiler automatically converts the id to instancetype. You are relying on this quirk; while you're writing that the init returns an id, the compiler is interpreting it as if it returns an instancetype.
These are equivalent to the compiler:
- (id)initWithBar:(NSInteger)bar;
- (instancetype)initWithBar:(NSInteger)bar;
These are not equivalent to your eyes. At best, you will learn to ignore the difference and skim over it. This is not something you should learn to ignore.
Pattern
While there's no difference with init and other methods, there is a difference as soon as you define a class factory.
These two are not equivalent:
+ (id)fooWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
You want the second form. If you are used to typing instancetype as the return type of a constructor, you'll get it right every time.
Consistency
Finally, imagine if you put it all together: you want an init function and also a class factory.
If you use id for init, you end up with code like this:
- (id)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
But if you use instancetype, you get this:
- (instancetype)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
It's more consistent and more readable. They return the same thing, and now that's obvious.
Conclusion
Unless you're intentionally writing code for old compilers, you should use instancetype when appropriate.
You should hesitate before writing a message that returns id. Ask yourself: Is this returning an instance of this class? If so, it's an instancetype.
There are certainly cases where you need to return id, but you'll probably use instancetype much more frequently.
There definitely is a benefit. When you use 'id', you get essentially no type checking at all. With instancetype, the compiler and IDE know what type of thing is being returned, and can check your code better and autocomplete better.
Only use it where it makes sense of course (i.e. a method that is returning an instance of that class); id is still useful.
Above answers are more than enough to explain this question. I would just like to add an example for the readers to understand it in terms of coding.
ClassA
#interface ClassA : NSObject
- (id)methodA;
- (instancetype)methodB;
#end
Class B
#interface ClassB : NSObject
- (id)methodX;
#end
TestViewController.m
#import "ClassA.h"
#import "ClassB.h"
- (void)viewDidLoad {
[[[[ClassA alloc] init] methodA] methodX]; //This will NOT generate a compiler warning or error because the return type for methodA is id. Eventually this will generate exception at runtime
[[[[ClassA alloc] init] methodB] methodX]; //This will generate a compiler error saying "No visible #interface ClassA declares selector methodX" because the methodB returns instanceType i.e. the type of the receiver
}
You also can get detail at The Designated Initializer
**
INSTANCETYPE
**
This keyword can only be used for return type, that it matches with return type of receiver. init method always declared to return instancetype.
Why not make the return type Party for party instance, for example?
That would cause a problem if the Party class was ever subclassed. The subclass would inherit all of the methods from Party, including initializer and its return type. If an instance of the subclass was sent this initializer message, that would be return? Not a pointer to a Party instance, but a pointer to an instance of subclass. You might think that is No problem, I will override the initializer in the subclass to change the return type. But in Objective-C, you cannot have two methods with the same selector and different return types (or arguments). By specifying that an initialization method return "an instance of the receiving object," you would never have to worry what happens in this situation.
**
ID
**
Before the instancetype has been introduced in Objective-C, initializers return id (eye-dee). This type is defined as "a pointer to any object". (id is a lot like void * in C.) As of this writing, XCode class templates still use id as the return type of initializers added in boilerplate code.
Unlike instancetype, id can be used as more than just a return type. You can declare variables or method parameters of type id when you are unsure what type of object the variable will end up pointing to.
You can use id when using fast enumeration to iterate over an array of multiple or unknow types of objects. Note that because id is undefined as "a pointer to any object," you do not include an * when declaring a variable or object parameter of this type.
The special type instancetype indicates that the return type from the init method will be the same class as the type of object it is initializing (that is, the receiver of the init message). This is an aid for the compiler so that it can check your program and flag potential
type mismatches—it determines the class of the returned object based on context; that is, if you’re sending the init message to a newly alloc’ed Fraction object, the compiler will infer that the value returned from that init method (whose return type has been declared as type instancetype) will be a Fraction object. In the past the return type from an initialization method was declared as type id. This new type makes more sense when you consider subclassing, as the inherited initialization methods cannot explicitly define the type of object they will return.
Initializing Objects, Stephen G. Kochan, Programming in Objective-C, 6th Edition
I could redo this method using proper Obj-C syntax, but I was wondering how to call this from Obj-C. The method looks like this
#interface YarMidiCommon : NSObject
static
MIDIPacketList *makePacketList(Byte *packetBuffer, const UInt8 *data, UInt32 size);
#end
but I have no idea how to call that method. I have tried
Byte packetBuffer[size+100];
MIDIPacketList *packetList = makePacketList(packetBuffer, bytes, size);
but the error is "has internal linkage but is not defined." Is this possible without resorting to "proper" Obj-C syntax?
For the record, the method that I want to emulate would be something like
+ (MIDIPacketList*) makePacketListWithPacketBuffer:(Byte*)packetBuffer data:(const UInt8 *)data size:(UInt32)size;
which is verbose and annoying, seeing as everything here is C anyway.
This is related to this other answer I got today.
Since the function is a C function you need to remove the static keyword or else it will not be visible outside of its translation unit. Once you do that the first example you have will work. Also since it is a C function placing its declaration inside or outside of the #interface and definition inside or outside of the #implementation makes no difference on how you will call it.
Consider the declaration as being equivalent to static C function in the global scope. This is much unlike C++ or Java. There is no class scope or external linkage for this function.
As such, the #interface scope would not be a good place to declare makePacketList. The message means the definition is not visible when you use it.
You need to move the function to the .m (makes sense if you use it from this file only) or remove the static keyword.
(New to Objective-C, but well versed in C/C++).
Presently I have an Objective-C class and a number of its member variables will be function pointers. These function pointers will only be modified by the class itself, but may be used by other classes.
I'm not sure how to set up access to said function pointers.
The solution I currently envision is to declare said function pointers #public, which as I understand it will allow me to call them using the -> operator. This seems fairly unsatisfactory to me, since the function pointers are left open to meddling, and it flies in the face of sound OOP.
My next inclination is toward using #property, and declaring them read only. This seems more sane. I assume I'd call them using the dot operator, as the idea of using to getter to get the function pointer and then call it seems entirely ludicrous.
Can one use function pointers as properties? If so, how would I go about declaring these to be properties:
void (*sort)(SET, int) ;
char *(*toASCII)(CARD) ;
I have a feeling I'm missing a slight nuance to declaring these as properties.
I believe you should be able to use function pointers as properties. You'd do it like this:
#property (nonatomic, readonly) char *(*toASCII)(CARD);
And then in your implementation:
#synthesize toASCII;
Then
object.toASCII();
In your #interface:
#property(readonly) void (*sort)(SET, int);
#property(readonly) char *(*toASCII)(CARD);
In your #implementation:
#synthesize sort, toASCII;
In your init method (or wherever else you want to set the function pointers):
sort = someFunction;
toASCII = someFunction;
On modern versions of iOS, you don't even need to add an ivar (it gets added automatically for you when you do #synthesize).