Safe casting in Objective C - objective-c

Is there anything like C++s safe casts in Objective-C?
I know that they are in Objective C++, but I am unsure about possible side effects. Using Objective C++ may slow compilation time - are there any other reasons not to use it?

Objective-c does have C++ safe casts. Alternatively, we can use runtime reflection:
id myOb=[someObject getObject];
NSAssert([myOb isKindOfClass:[MyClass class]], #"Return value is not of type MyClass as expected.");
MyClass * newOb= (MyClass *)myOb;
References:
Cocoa with Love:

You can turn on compiler flags to warn you in cases like this. This particular mistake would be caught by the -Wconversion flag.

Which feature of C++ do you think will help you cast a 64-bit long to a 32-bit int?

Related

Objective C : can't operate download issue

i'm new to Xcode objective-c and I have a task to make a newsletter that downloadable.
So, I got some source code and tweak a bit but I got some error that said
"Implicit conversion loses integer precision : 'long' to 'int'
here are my code
-(void)downloadIssue:(IssueInfo*)issueInfo{
NewsstandDownloader* downloader = [[AppDelegate instance] newsstandDownloader];
downloader.delegate = self;
long index = [self.publisher indexOfIssue:issueInfo];
[downloader downloadIssue:issueInfo forIndexTag:index]; <-- Error
}
Please help me.
Thank you.
That's just a compiler warning and a mild one at that. If you were dealing with a document that had more than, say, 32000 pages then you might need to be concerned about it.
The way to solve the problem is to either change the declaration of the function you're calling to something like:
[downloader downloadIssue:(IssueInfo *)issueInfo forIndexTag:(long)index]
or, simply use a cast:
int index = (int)[self.publisher indexOfIssue:issueInfo];
"int" isn't usually a good thing to use in Objective C as there are different lengths and capacities to it on different platforms (32 bit versus 64 bit, iOS vs MacOS, etc.). It's better to use something more Objective-C specific, like NSInteger or NSUInteger.

Why isn't there a 'nonnil' attribute for clang?

nonnull works for C functions but not obj-c methods. To be clear, I am suggesting this
- (void)doSomethingWithRequiredString:(NSString * __attribute((nonnil)))requiredString
bar:(NSString *)optionalString);
or (more like nonnull)
- (void)doSomethingWithRequiredString:(NSString *)requiredString
bar:(NSString *)optionalString)
__attribute((nonnil(0)));
I have puzzled over whether or not there is a good technical reason. I understand that clang could only really use the attribute for a compile time check or static analysis, but that seems orthogonal. Is there some strong reason not to have this?
You totally can. The only thing you're doing wrong is thinking that method parameters are 0-indexed, when in fact they're 1-indexed (oh, and it's nonnull, not nonnil):
- (void)doSomethingWithRequiredString:(NSString *)requiredString
bar:(NSString *)optionalString
__attribute((nonnull(1)));
Now when you try to use that:
id thing = ...;
[thing doSomethingWithRequiredString:nil bar:#"42"];
Xcode will warn you with a by saying "Null passed to a callee which requires a non-null argument".
Also, if you leave out the "(1)" portion of the __attribute, it's assumed that the non-nil requirement applies to all parameters.
Clang recognizes the GCC attributes, and GCC's definition of the nonnull attribute is here: http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html#index-g_t_0040code_007bnonnull_007d-function-attribute-1733
Update: As of Xcode 6.3 a cleaner syntax is supported.
In properties and methods the keywords are nullable, nonnull and null_unspecified.
So your method signature would become this:
- (void)doSomethingWithRequiredString:(nonnull NSString *)requiredString
bar:(nullable NSString *)optionalString;
In the Xcode 6.3 beta new Objective-C features have been added to express (non)nullability in headers: https://developer.apple.com/swift/blog/?id=22
Yes there is.
You may code like this:
- (nullable AAPLListItem *)itemWithName:(nonnull NSString *)name;
- (NSInteger)indexOfItem:(nonnull AAPLListItem *)item;
https://developer.apple.com/swift/blog/?id=25

Can the underlying type of an Objective-C enum be specified?

I was surprised to discover that Xcode does not issue an error for the following code, which is invalid in C:
typedef enum : NSUInteger {
FLAG_A = 1,
FLAG_B = 2,
FLAG_C = 4
} MyFlags;
This appears to make NSUInteger the underlying type of the MyFlags enum, very similar to C#'s syntax for setting the underlying type of an enum.
Does this syntax do what it appears, or does it mean something else?
It is a feature borrowed from C++11 used to ensure a specific size of the enum. It allows to use enums in the public API of frameworks without having to fear that the ABI will eventually break.
Clang implements this feature and allows its use in Objective-C as a language extension.
This will work fine in objective c. you can set any value for these params in an enum.

Why is it a pointer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
objective c difference between id and void *
why most of the objects we create in iphone are pointers
According to Stanford university course, 2010/2011
Lecture 3
The guy made something strange there (at least for me), which is that
NSString *digit = sender.titlelabel.text;
Why is digit a pointer?
The type of your digit is id, which is just basically just a C pointer to a certain struct. All references to objects in Objective-C have this primitive type, regardless of the Class of the object. So the answer to your question is, unfortunately, because that's the way Objective-C works.
So whether you're declaring an NSString*, or an UITableViewController*, or MyClass*, your variable has type id. This is the primary means by which the language implements polymorphism. So, for example, the following declarations are equivalent:
NSString *digit;
id digit;
And it's true of method prototypes as well. These are equivalent:
-(UITableViewCell *)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath;
A variable of type id is not an object itself, it is a pointer to an object. It is the handle with which you manipulate an object. Objective-C does all of the class compatibility work at runtime.
Hope this helps. Any questions?
Updates
That's right: int, float, double, char, void, and the pointer combinations, are all C primitive types. You can and will still use these quite a bit, and they are just what they are in a C program. But Objective-C adds the id type as a way to bridge the gap between the primitive typing of C and the very high-level typing of objects by the Objective-C system. id itself is typedef'd as a pointer to a simple struct in objc.h. At the level of the compiler and the language itself, there really isn't too much meaning to the type. For example, you'll almost never declare an array of ids, certainly never perform any arithmetic with them.
In fact, it's not too far a stretch to say that Objective-C is just plain vanilla C with some added syntax (particularly, the square-bracket notation for method invocation), a few extra primitive types (id, IMP, SEL), and a big runtime library. It's this runtime library that handles all things Object-Oriented.
Anyway, to answer your question, when you're actually programming, you will most often (99% of the time) just use class names to declare your variables - NSString *, NSData *, UITableViewController *, and so on. And the compiler will know what you're talking about, and issue a warning if you write code that clearly tries to put an NSString* where an NSData* is expected. But the actual meaning of those types really exists only at runtime.
I've digressed a little, but I'm not sure where your understanding is failing you, so I thought I'd just explain things a bit. You might want to read Apple's The Objective-C Programming Language to get a feel for the language.
NSString is an Objective-C class and all object references in Objective-C are pointers. I would suggest reading through some of the documentation such as Learning Objective-C A Primer:
Notice the * in the first declaration. In Objective-C, object
references are pointers. If this doesn’t make complete sense to you,
don’t worry—you don’t have to be an expert with pointers to be able to
start programming with Objective-C. You just have to remember to put
the * in front of the variable names for strongly-typed object
declarations. The id type implies a pointer.
It's not a digit, it's the "text" from the label, which is (I'm guessing) a string of integers and such to express the time.
So, all NSString types are declared as pointers in Obj-c.
sender.titlelabel.text;
Returns a NSString *
Remember, it's the same as:
NSString *str = [sender.titlelabel getText];
Because text is too. Or more preceisly, because the getText message returns a pointer.
You can find an intersting about why it has to be a pointer:
NSString and Pointers
I Hope it will help you to understand it in a Objective-C way.

Operator 'overloading' equivalent with #define in C/Objective-C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Operator overloading in C
If I have a struct:
typedef struct myStruct {
...
} myStruct;
myStruct myStructAdd(myStruct a, myStruct b);
I need something like this:
#define myStruct a + myStruct b myStructAdd(a, b)
// NOTE this code does NOT WORK. This is what the question is asking.
To make this syntax valid:
myStruct a;
myStruct b;
myStruct c = a + b;
Is there any way to use a #define to do this?
EDIT:
I'm not asking for alternatives to the + syntax. What I'm asking is if, and how, the preprocessor can be used to rewrite the plus syntax to standard C syntax on compile.
i.e. something like #define myStruct a + myStruct b myStructAdd(a, b) which turns myStructA + myStructB into myStructAdd(myStructA, myStructB) on compile.
Operator overloading simply isn't a feature of C or Objective-C. C++ allows you to define arbitrary behaviour for operators and custom types. In Objective-C, if two objects can be added together, then usually there is a method for that:
Foo *result = [foo1 fooByAddingFoo:foo2];
Or, if the class is mutable:
Foo *foo1 = [Foo fooWithBar:bar];
[foo1 addFoo:foo2];
If operator overloading is a must-have feature, use C++ instead, or use Objective-C++ (but keep in mind that C++ classes and Objective-C objects are totally and fundamentally different).
Edit:
The C proprocessor is conceptually very simple, and it knows very, very little about C's syntax, and nothing at all about C's types. If you wanted to overload an operator using the preprocessor, then it would have to learn every type (including custom types) used in your code, and it would have to perform static type checking in order to determine which function to invoke, and this is something that is way out of the scope of the preprocessor.
It's an interesting idea, but it's simply not possible.
There is no way for you to do that using the preprocessor. Also, as far as I known, there is no other feature that would provide this in objective C.
However, if you would use C++ (or objective-C++, which give you all features of both Objective C and C++) you could define an operator+, as follows:
struct myStruct
{
myStruct operator+(myStruct const & other)
{
return ...;
}
}
If you limit your question to the preprocessor then the answer is that it is impossible due to the fact that to define a macro that takes in arguments you have to have a parentheses macro like
#define __DO_STH(par1,par2)
Operator overloading the way you think of it does not use parentheses so you can not create any such macros
The only way to do that would be to make a simple parser which would be reading your code and whenever it encountered the structs you need being added with a plus sign spit out C code that replaces that with the function, but why do that and not use C++ where it's natively supported?
Also unless you are asking for purely academic purposes, it is my honest opinion that operator overloading always does more bad than good and is better avoided.
The only way I know is to use Objective-C++. To do this, give your implementation file the extension "mm" and you're good to go.