Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm new with Objective C and am not an uber programmer anyway but one thing I find odd is that it won't throw errors sometimes when objects are declared not initialized.
I just ran into this again - I had some setup stuff to be done in so I put it in an init function - but the class is a UIViewController that is wired up in the storyboard. So init was never called - and that's my error - (lots of NSObject derived classes in the project and I rushing and just tossed that in to test some things).
But my methods that were making calls to the instance that was supposed to have been set up in int didn't throw errors - it just that the values I was expecting were nil.
Isn't that sort of odd that that sort of stuff would fail silently?
You've got two separate issues here, both quite common for beginners.
Your init was never called because it's the wrong method entirely. It's not the designated initializer for a view controller, and in any case a view controller from a nib or storyboard gets initWithCoder:. So it's up to you to have a sense of what method will be called and when.
Messages to nil return nil with no error. This is a deeply entrenched feature of Objective-C and isn't going to change. There is often quasi-religious debate about it, and there are some clever ways around it, but that's neither here nor there really. Basically it's up to you to use lots of NSLog and lots of nil-checking (NSAssert is a great thing to use for this), especially during early stages.
Not odd at all. That's how Objective-C has always worked. Messages to nil simply do nothing.
It is strange, but that's how Obj-C was designed. Actually, from Obj-C perspective, the code did not fail (silently). Everything was correct.
In Obj-C you can alwyas send messages to ("call methods on") nil.
init is just another message ("method"), not a constructor. It's not needed to create and use an object. You can understand Obj-C only as a thin layer over C language. C language won't report if you haven't called a function on a struct, either.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Ive searched around and can't find any answers that aren't related to C++, which isn't the exact same thing. I have a game and I keep an NSMutableArray of my sprites for certain categories because there are too many of them and they appear/dissapear too often to keep references to every single one of them, and also the number of them varies. so they are stored in an array.
In my didBeginContact method I grab the contact.bodyA.node object and pass it into a mehtod I've written called getSprite which enumerates over the array of objects I have, finds the one that matches and returns that one as an SKSpriteNode so I can use SKSpriteNode-specific methods such as animateWithFrames and such. However, I use this method pretty frequently and I'm wondering if doing something like:
SKSpriteNode *sprite = (SKSpriteNode*)[contact.bodyB.node parent];
Is acceptable as well, and then just using that pointer to refer to my object. It works, but I don't know if it will cause memory leaks or other problems. Any suggestions? (the reason I used the parent method is because the sprite I'm actually after is the parent of the one involved in the collision).
I assume you're using ARC. The local pointer to the object is a strong pointer by default, since you didn't specify anything differently. So that object is guaranteed to not be destroyed during the scope in which your local sprite pointer exists. It will not maintain a strong reference beyond that scope. The NSMutableArray also maintains a strong reference to to the objects it contains, so while they are in that array, the objects will not be destroyed.
As far as memory leaks go, this shouldn't cause any problems. It should also be more performant since it's a direct link back up to the sprite, rather than iterating and searching for the correct sprite. I don't see any reason why you couldn't do that, besides the fact that is might affect future plans for your game since the parent relationship of the object becomes part of the logic when is probably shouldn't be, but if you centralize that code so it's easy to change if you ever change the hierarchy of your sprites it should be fine.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
How can I write code in Xcode max similar to syntax in Java or C++ in particular call functions (messages), static or dynamic? I just want to simply call Objective-C function in C-like syntax.
How to when I write NSString * s = NSString.alloc().init();
(or similar, for example, NSString::alloc().init(), or NSString::alloc.init or (new NSString()).alloc().init() ;))
in Xcode (or another iPhone dev environment), the compiler did not cause an error and it will run.
or code like
NSString * a = NSString.alloc().init(); //or similar
bool b = a.compare("abcdef"); //or bool b = a->compare("abcdef");
will run.
?
Objective-C has C functions. In fact, all valid C code is valid Objective-C code. So yes, you can call functions with C syntax.
However, objects and message sends use Objective-C's syntactic extensions to C, which are not configurable. They are part of the language. You can't change Objective-C's syntax any more than you could make C++ use Smalltalk syntax.
No, there is no way to call Objective-C methods in a different syntax, with one exception:
You can call methods that do not take arguments with a dot notation as in object.method (this is mostly used with properties, which in turn are getter and setter methods that are generated by the compiler).
So the way methods are called in Objective-C ([object method] or [object methodWithArgumentA:someValue argumentB:otherValue]) cannot be changed. This is the syntax chosen by the language designers. And once you've worked with it a little, you'll understand why:
Method names in Objective-C tend to be very descriptive and are used as if Objective-C had named arguments (technically, that's not the case). Like:
[someData writeToFile:aFileName atomically:YES];
How would you transfer this to a dot notation? It might look like this:
someData.writeToFileAtomically(aFileName, YES);
Now, if I see a method just writeToFileAtomically I wouldn't be surprised if it just would take one argument (whether to atomically write to file; but which file?) or no argument (just write to a file atomically; again, which file?). With the Objective-C notation the intention is more clear.
And now consider object.addObserverForKeyPathOptionsContext(o, k, op, c) vs. [object addObserver:o forKeypath:k options:op context:c].
Whether one likes this syntax or not is subjective. You don't seem to like it, as you wouldn't have asked how to get rid of it. But if you want to write Objective-C code you'll have to accept that this is the way it's done and you cannot change it. Embrace it, I found it weird at first as well (also coming from a long C++ and Java background) but now I miss the very verbose way of calling methods with arguments of Objective-C when working in other languages.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
This may be a very simple answer,but I cannot the solution anywhere. I have this object called board that gets passed into a method. I want to change the state of the board inside the method but not affected the board itself. Here is a very simple version of the code that I attempted so far:
- (int) getMove:(Board*)board {
Board* tempBoard = [[Board alloc] initSize:3];
tempBoard.slots = board.slots;
[tempBoard replaceIndex:5 withMark:#"X"];
return 1;
}
If I were to call this method with a board object X, X has the changes made from that method. I'm a noob at pointers so I'm thinking that is the cause of this.
If want to prevent the board to be mutated, you should make the Board class immutable, i.e. not exposing any public method to change its internal state.
If you need also the mutable version, you can have a subclass like MutableBoard which exposes the methods to mutate the object.
So in the end you will be able to do
- (int)getMove:(Board *)board {
[board makeMove]; // compiler error!
return 1;
}
and
- (void)doSomethingOnTheBoard:(MutableBoard *)board {
[board makeMove]; // ok!
}
I would also suggest you implement -mutableCopy on Board in order to support the creation of a mutable instance of it.
Bottom line, you just need to follow the same API design as NSString, NSArray, ... which are immutable, with an immutable subclass (NSMutableString, NSMutableArray...)
Apple has a great guide to the concepts of objects mutability you can read.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
When one uses ARC, this means we can forget about memory management related tasks right? e.g., like deletion/release of the memory we allocated etc.
Two places I know we may need to interfere is retain cycles, and one should use __weak before Outlet ivars in class definitions (if these outlets are not top objects in object hierarchy of the XIB).
Is there something else I have to consider?
Things have changed.
You should still stick to some pattern related to memory managment / ARC. You won't retain, release, autorelease and dealloc any more.
New:
You would still overwrite a dealloc method and nil all strong references. That is not really required but can be done. But you would not call [super dealloc] any more.
You will declare properties as strong or weak depending on whether you take ownership or not.
If you want to get rid of an object in a way that the memory is freed up, then you have to nil all strong references to that very object. Each strong reference corresponds to one retain. But you cannot call retain on those objects.
You cannot call undeclared methods any more (Without ARC this will generate a compiler warning, with ARC it is an error.)
You get warnings when using variable selectos (That is using variables of SEL type and perform those on objects) and you should never do that with methods that might have an implact on the retain count (such as alloc).
And you still have plenty of chances of making errors when you interface with areas of the framework that do not ARC, such as core functions.
So it is far away from "forget about" but applying the ARC patterns is less work and less error prone than the former MRC patterns.
When using ARC you dont have to use dealloc/autorelease. so, YES you can forget deletion release etc.
The only thing to consider is strong reference cycles, like the one you mentioned here.
Another example is when you use delegate objects.
You can also refer apple's documentation
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Today, I got a link to a long list of coding guidelines, proclaiming to be "code commandments". A good read, and full of new insights to me. Among the list, somewhere along 25% of the scrollbar, I come across something new to me: Implicit data member creation.
Although every tutorial, book and video I've read or watched about Objective-C always performs the triad of NSNumber *number | #property NSNumber *number | #synthesize number, these commandments now tell me I can simply omit the first step (data member declaration in the interface) because #synthesize will create one on the fly. Say what!?
With a little disbelief I deleted several of my data member declarations, and indeed, my app still works like a charm. Less typing, less reading, less chance for typos.
Sounds to me like a win-win-win, but is it really good practice?
I'm asking this question out of pure disbelief that all the tutorials, books and videos are teaching the wrong lesson, at least too much of it, or that I've been not paying attention in class...
Cheers,
EP.
Edit: Although I copied the expression "data member" from the linked post, it is more commonly described with the word "ivar", just a good one to have in here for search friendliness. This also takes care of my former confusion over property/ivar/member naming :).
Synthesized instance variables are a feature of the modern Objective-C 2.0 runtime. This means they're available on x86_64, on ARM, and as of Xcode 3.2, on the iPhone Simulator. It means exactly what you suggested - you can omit the ivar declaration, and the #synthesize line will generate the ivar for you. The performance of this is exactly the same as declaring the ivar explicitly, but it has the very important benefit of not polluting your header file with private implementation details.
I have begun the practice of removing synthesized properties from the Objective-C classes I create. The primary reason for this is because there is a distinct difference between:
self.myNSObject = [NSObject new];
and
myNSObject = [NSObject new];
Specifically, if myNSObject is declared as a #property(retain, ...) the former line will result in a retainCount of 2 while the latter will result in a retainCount of 1. This means that unless you are extremely careful about every assignment to myNSObject you run the risk of getting your retain/release balancing wrong.
The other reasons you specify are also very valid. There is a lot going on in the synthesized routines that my brain doesn't account for when I'm reading the code I've written, so a lot is taking place behind the scenes that I'm not thinking of yet am accountable for. It's for very a similar reason I've abandoned Apple's Interface Builder.