I'm doing my first steps in objective-c (after a long, long time away from it) by translating some Java code I wrote for an Android game. It seems like there is no container that can take an object, without casting it to id first? Or is there?
Specifically this is the code I'm trying to work with:
NSMutableArray *touchedBodies = [[NSMutableArray alloc] init];
// some additional code
if(![touchedBodies containsObject:(id)body]) {
[touchedBodies addObject:(id)body];
}
The containsObject line passes fine, but on the touchedBodies addObject:(id)b I'm getting a "bad access" error. The body I'm trying to add is a legitimate Box2D b2Body.
When I tried to add the body directly, without casting it:
[touchedBodies addObject:body];
the compiler complains "Cannot initialize a parameter of type id with an lvalue of type b2Body* '
What am I missing?
First of all you never need to cast to an id type just because you can consider id as the Object class in Java: it's an implicit upcast that doesn't need to be explicit.
In second instance the problem occurs because 2dBody is a C++ class, not an Objective-C class. While you can mix Objective-C++ and C++ code (the former is a superset of the latter), you can't mix objects from these two languages without some workarounds.
You have mainly three solutions:
if 2dBody is a pointer, wrap it inside an NSValue: [touchedBodies addObject:[NSValue valueWithPointer:body]], this introduces some overhead with object allocations and you will need to cast it when you use it, 2dBody *b = (2dBody*)[value pointerValue]
if 2dBody is not a pointer then you could use an NSData: [NSData dataWithBytes:.. length:..], this introduces overhead, problems with memory management (unless you use noCopy variants), it introduces problems if the layout of the class is not standard, and you will need to cast it in any case
forget cocoa collections and use STL collections, they're more performant and they will manage everything seamlessly: vector<2dBody> touchedBodies; touchedBodies.push_back(body);.
I strongly suggest using STL collections, I personally use this approach
Related
I'm quite blank when it comes to swift, I've been developing using Obj-c. But a tutorial that I've been following uses Swift. Can anyone help me convert the following line of Swift into Objective-C. It's basically to load a String onto an Array.
self.iDArray.append(objectIDs[i].valueForKey("objectId") as! String)
self.iDArray.append(objectIDs[i].valueForKey("objectId") as! String)
Should be
[self.iDArray append: [objectIDs[1].valueForKey: #"objectID"]]
However, the Swift code is force-casting [objectIDs[1].valueForKey: #"objectID"] to type String (A Swift string).
That suggests to me that self.iDArray may be a Swift array. Swift arrays normally contain only a single type. You create an array of String objects, or an array of Dictionary objects. You can also create an array of AnyObject.
NSArray is an array of id type.
I'm not 100% positive how to force-cast to String type in Objective-C. maybe:
[self.iDArray append: (String) [objectIDs[1] valueForKey: #"objectID"]]
On the surface, objectIDs[x] appears to be a dictionary, and the compiler will give you a break on types if you dereference it that way. So naive to parse, a usable syntax would be:
[self.iDArray append:objectIDs[1][#"objectId"]];
But that's incorrect semantically for parse, since the implication is that the objectIDs array is implied to contain parse objects (named confusingly with the "IDs" suffix). If it's really parse objects, then the collection style reference for objectId won't work, and should be instead
[self.iDArray append:((PFObject *)objectIDs[1]).objectId];
Or more readably:
PFObject *object = objectIDs[1];
NSString *objectId = object.objectId;
[self.iDArray append:objectId];
But, along the same lines semantically, the implication of the code is that it's adding to an NSMutable array, so it probably should be -- for any of the above suggestions:
[self.iDArray addObject: .....
Stop reading here if you care only about compiling and executing without a crash.
But, even if all that's right, which I think can be inferred from the code, it's indicative of bad design in my opinion. Swift developers in particular seem to have a penchant for saving off objectIDs and passing them around as proxies for object, and in so doing, loosing all of the other valuable stuff in the PFObject.
My practice is, wherever possible, just keep and pass the whole PFObject. You can always ask it for its objectId, later. More strongly, my rule of thumb when reading code is: show me parse.com code that refers much to objectIds -- except for things like equality tests -- and I'll show you a design error.
In Objective-C, is there any way to run a specific selector automatically every time an object is instantiated? (I know about +initialize but I need an instance method).
Specifically, I am writing a custom string class (that inherits from my own root class with a similar interface to NSObject) and I am trying to make it 'play nicely' with Objective-C constant strings. To do this, I have the following class definition (as required by the runtime):
// 1) Required Layout
#interface MYConstantString : MYObject {
//Class isa; inherited from MYObject
char *c_string;
unsigned int length;
}
Now, I want to implement my string class by using a pointer to a C-struct inside the class (this "C object" is already well implemented so I basically just want to wrap it in an Objective-C class). Ideally therefore, my Objective-C class would look like this:
// 2) Desired Laout
#interface MYConstantString : MYObject {
// Class isa;
StringObject *string;
}
And then the class and instance methods would just wrap C function calls using that StringObject.
So because I can't have the desired ivar layout (2), I wish to hack around the required ivar layout (1) to work for me. For example:
- (void)fixup {
// Pseudocode
temp = copystring(c_string);
c_string = (void *)StringObjectNewWithString(temp); // Fudge pointer
length = ... // I can do something else with this.
}
So, to return to the question, is there a way to call -fixup automatically, rather than having to do the following every time I make write an Objective-C constant string?
MYConstantString *str = #"Constant string";
[str fixup];
I know this is an obscene hack, and Objective-C constant string interoperability isn't totally crucial for what I need, but it would be nice to be able to use the #"" syntax and make the code more 'naturally' Objective-C.
I'm guessing you left out an important fact: you're using -fconstant-string-class=MYConstantString when building to have the compiler use your class for constant string objects (#"...").
Given that, then, no. There are two significant problems. First, "instance creation" for constant strings happens at compile time, not run time. The reason that there's a required layout is that the compiler does nothing but lay out the string's data in a data section with a reference to the appropriate class object where the isa pointer goes. It doesn't invoke any custom code. It is not necessarily even aware of such custom code at compile time. A given translation unit may not include the constant string class. The reference to that is resolved at link time.
Second, the constant string instance is almost certainly laid out in a read-only data section. There's a good chance that even calling your -fixup method manually as in your question would encounter an access violation because you'd be modifying read-only memory.
You should consider using a class cluster. Make MYConstantString one concrete subclass of an abstract base class. Make it conform to the required layout and just use the character pointer and length ivars as they are. If it would be convenient to translate to StringObject at various points, do that at those points. Implement other, separate concrete subclasses to use StringObject internally, if desired.
MYConstantString *str = #"Constant string";
That can't work because #"..." is an NSString, and it's not only a problem of layout but of instance sizes. If you want 0-copy or anything like that, what you have to do is have something like:
MYConstantString *str = [MyConstantString stringWithNSString:#"Constant string"];
and let -stringWithNSString: recognize when the passed string is a constant one (I'm pretty sure the concrete class of constant strings is easy to recognize, and probably hasn't changed ever for backward compatibility reasons) and then hack it around to grab the pointer to the bytes and similar things.
This seems like a very strange interaction to me but at the same time it not only works but throws no warnings or errors in the process. Just looking to get some better understanding of blocks in general and why something like this could be right or wrong.
Is there any reason why something like this shouldn't be done?
NSArray *array = [NSArray arrayWithObjects:^{NSLog(#"Block 1");}, ^{NSLog(#"Block 2");}, ^{NSLog(#"Block 3");}, nil];
for (id block in array) {
[block invoke];
}
Putting Blocks into NSArrays is fine; they're objects. In fact, they inherit from NSObject.
You do need to copy, them, however. Those Blocks are created on the stack and need to be moved to the heap in order to live past the end of the current method. If you're using ARC, this is easy:
NSArray *array = [NSArray arrayWithObjects:[^{NSLog(#"Block 1");} copy], ...
Under MRR, you need to balance that copy, so you have two unpleasant options: use temps, or enumerate the array right after creating it and send release to all its members.
Sending invoke, on the other hand, isn't completely kosher, because that's a private method. The only fully-API-compliant way to invoke a Block is with function-call syntax:
typedef GenericBlock dispatch_block_t;
for( GenericBlock block in array ){
block();
}
Sure, that's fine. Why wouldn't it be fine?
In languages like JavaScript this technique is commonplace when registering event handlers.
object.clickHandlers.push(function() { doStuff() });
object.clickHandlers.push(function() { doMoreStuff() });
I see no reason that similar techniques couldn't be used with ObjC blocks, as they are real objects.
The more interesting question to me though, is if this pattern is the best choice for whatever your goal is. Which you haven't really told us.
Blocks in Objective-C are "first-class citizen" objects. Whatever you can do to a regular object, be it passing as a parameter, storing in an array or a dictionary, and so on, you can do it to block objects as well.
For example, an array of block objects may be useful to encode a sequence of actions that is not known at compile time; a dictionary of block objects keyed by strings could be useful in implementing a scripting language, and so on.
The best way to call a block retrieved from a collection is casting it to its proper type, and using the regular block invocation syntax on it.
I'm trying to wrap my head around some of the differences in usage and syntax in C vs. Objective-C. In particular, I want to know how (and why) the usage differs for the dot operator and the arrow operator in C vs. Objective-C. Here is a simple example.
C Code:
// declare a pointer to a Fraction
struct Fraction *frac;
...
// reference an 'instance' variable
int n = (*frac).numerator; // these two expressions
int n = frac->numerator; // are equivalent
Objective-C Code:
// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];
...
// reference an instance variable
int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator??
So, seeing how frac is the same in both programs (i.e. it is a pointer to a Fraction object or struct), why are they using different syntax when accessing properties? In particular, in C, the numerator property is accessed with frac->numerator, but with Objective-C, it is accessed using the dot operator, with frac.numerator. Since frac is a pointer in both programs, why are these expressions different? Can anyone help clarify this for me?
frac is actually not the same in both programs.
A C Fraction is a struct, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C is with the dot (.) operator. Objective-C maintains this operator when you use structs. For convenience, you can perform a dereference-and-dot operation using the arrow (->) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing structs.
An Objective-C Fraction in your example, however, is probably (one would assume) a pointer of at least type id, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject or NSProxy. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.
One of the most basic operations is objc_msgSend. When we operate on these types of objects, the Objective-C compiler interprets a dot (.) operator or the square bracket syntax ([object method]) as an objc_msgSend method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.
The arrow (->) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]-> and then bring up the method completion list, you see this:
Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]). These particular items, however, are the C fields that store the values of their respective Objective-C properties.
So, you can roughly think of it like this:
Dot operator on a C object
(at run time) Return value of the field
Arrow operator on a C object (pointer)
Dereference pointer
Return value of the field
Dot operator/square brackets on an Objective-C object (pointer)
(at compile time) Replace with call to objc_msgSend
(at run time) Look up Obj-C class definition, throw exception if something went wrong
Dereference pointer
Return value of the field
Arrow operator on an Objective-C object (pointer)
(at run time) Dereference pointer
Return value of the field
Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.
Dot-notation is a design choice. Since we always deal with pointers to objc instances, I'd guess the designers wanted something familiar, which also would not break existing programs. It was introduced in ObjC 2 - just a few years ago. Before that, you always had to use brackets for messaging.
Dot notation makes a difference though - it is not direct access, but a message.
That is:
obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;
val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;
You can still write obj->ivar to access a pointer to object's members (if visible).
In your first example, Fraction is a struct.
In your second example, Fraction is an Objective-C class (and in iOS would likely be a subclass of NSObject).
C++ does not allow overloading of operator .. Therefore without additional information you can deduce that the dot notation you're seeing is an additional language construct integrated into Objective-C, rather than a C/C++ defined or overloaded operator.
As it happens, the dot notation is simply a design feature the implementors chose as shorthand for property access, entirely equivalent to the square bracket getter:
myObjCVar.prop == [myObjCVar prop];
The dot operator on objects is a special syntax for accessing objects' properties. It calls the property's getter or setter behind the scenes. So, for example, [#"hello" length] and #"hello".length are equivalent*. For all other types, the dot is the same as the C dot, and the arrow is always the same.
* Note: The accessor method won't always be named the same as the property. If it's a declared property and the declaration designates a special getter or setter method, that one will be used instead.
The dot and arrow notation are equally the same in C as it is in Objective-C (strict superset of ). I think the fundamental difference that needs to be distinguished is the difference between a struct and an Objective-C object.
The dot notation used for objects in Objective-C are used for properties that was introduced in Objective-C 2.0. However, with structs, the -> and dot notation between Objective-C and C are the same.
I am fairly new to Objective-C. Currently porting my own library from C#/Java to objective C.
I now run into a very strange problem for me.
I have a NSArray with several Note objects. I want to transpose on of these notes:
//Note.h
- (Note *) transpose: (int) semitones;
//Main
NSArray *notes = [get it from somewhere];
Note *transposedNote = [[notes objectAtIndex:0]transpose:1]; //Doesn't compile
Note *transposedNote = [(Note*)[notes objectAtIndex:0]transpose:1]//Does compile
Is this happening because there is already a transpose method available in the general libraries?
I thought due to the dynamic nature of objective-C at runtime it would be checked which class objectAtIndex returns and then sends the message to it?
It is my understanding that there is no runtime type checking for the assignment operator in Objective C. Since an array can contain a mixture of types, there is no way for the system to know what objectAtIndex returns.
How about
Note *transposedNote = [notes objectAtIndex:0]; // first line
[transposedNote transpose:1]; // second line
? Notice in the reference that objectAtIndex: returns an id, you will see it is pretty obvious:
In the code above, because id can fit into any object, the first line doesn't need to cast it into Note. In the second line I'm just calling a method on a Note so the compiler is happy.
In your code you are calling methods on the returned id object, so the compiler doesn't understand what you are trying to do. Just assign it to a Note reference and it will be fine.
Yes, the error is because there's already a transpose: method in AppKit. And you're also right that it normally doesn't cause an error when you have two unrelated classes implementing methods with the same name. The reason you get an error is because the two methods either return incompatible types or take incompatible types as arguments. In your particular case, you're seeing both problems:
-[NSResponder transpose:] takes an id and returns void
-[Note transpose:] takes an int and returns an id
These are totally incompatible types, and the compiler does need to know the types involved even if it doesn't know what exact method is going to be called.
It does compile unless you have -Werror set to treat warnings as errors.
It might produce a warning if the compiler doesn't already know about the selector or if the selector is declared in more than one class. In the former case, it should be necessary only to import the interface containing the selector. In the latter case, you'll need to do the cast to suppress the error.