Is there such a list?
I'm relatively new to iOS development and I'm think it would be great to study a list of most well-known compiler bugs or gotchas.
EDIT:
Today I spent too much time to understand what's going on with code like this:
in *.h
#interface I : NSObject {
..
NSSMutableArray* var; // typo, should be m_var;
}
#property (nonatomic, readonly) NSMutableArray* var;
in *.m
#implementation I
#synthesize var = m_var; // no warnings or anything
-(id) init
{
self = [super init];
if (self != nil)
{
// no warning or errors
m_var = [NSMutableArray new];
}
return self;
}
And I think it's time to learn some of the well-known Objective-C idiosyncrasies.
Apple’s list of bugs is internal to Apple.
I think that Open Radar is the closest thing you’ll get to a public list of bugs related to Apple products, including Xcode. It is maintained by the community — users are encouraged to post to Open Radar the bug reports that have been submitted to Apple.
The golden rule of debugging: it’s not compiler’s fault. Some behaviours are a bit strange, like the one you show here, but they are by design. As for the “bug” in question, the compiler can synthesize instance variables for you, without them having to be declared:
#interface Foo {}
#property(assign) float bar;
#end
#implementation Foo
#synthesize bar;
- (void) somewhere { bar = 1; }
#end
This is convenient and allows you to move private interfaces into the implementation file. Coming back to your example, you now have two instances variables, var and m_var, the second one acting as a storage for the var property. It’s not exactly something to be happy about, but it makes perfect sense. (Could there be a warning that you have an instance variable that doesn’t act as a store for a property with the same name?)
As this kind of behaviour is mostly by design, you won’t find it in the Radar and would have to look for a list of common Objective-C gotchas. (This is another interesting situation.)
Apple has its own bug tracker, but you can only see you own reports (!?)
Your best bet is then openradar... Which is limited.
EDIT: About your supposed Xcode Bug, even if that's not the question.
Remember that #synthesize is just syntactic sugar that will generate code at compilation.
My guess is that your var property is conflicting with your var member.
I would not say that's a bug, more a predictable issue that could be integrated in clang static analysis.
Anyway, that's obviously a code typo, a human error, tools are just there to help us, or we would write assembly bytecode directly :)
Related
Quick question. I've got a project with a class with no implementation file.
Then in the AppDelegate I've got:
#import "AppDelegate.h"
#import "SomeClass.h"
#interface AppDelegate ()
#property (nonatomic, strong) SomeClass *myProperty;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.myProperty hello];
// self.myProperty = [[SomeClass alloc] init]; // uncomment and fails as expected.
return YES;
}
Shouldn't somebody tell me that there is no implementation file ? Some sort of warning or anything?
If I do an alloc] init] it'll not compile as expected.
That code actually compiles.
Here is the project in github.
https://github.com/nmiyasato/noImplementation
Thanks
No. This isn't detectable at compile time or at link time in Objective-C.
First, the compiler knows exactly nothing about "header files" or "implementation files." (This is changing a little with the new module system, but that's not what we're discussing here.)
#import is not handled by the compiler. It's handled by the pre-processor. It takes the file SomeClass.h and splats it into AppDelegate.m as text before the compiler even sees line one. So all the compiler has to work with is this one giant file with all the text of all the headers plus this implementation (while there is "whole module optimization" now, that's a link step, not a compile step). It doesn't have any access to the rest of the project.
So the compiler has no way to know that you haven't provided an implementation. And in ObjC, even if the compiler looked at all the code, it couldn't actually know that there's no implementation anywhere because you can add implementations at runtime. In fact, it's pretty common to do this. It's how all of Core Data works. The implementations also may be linked in via a shared framework (which is very common), and may even be linked in at runtime on OS X. Or the implementations may be in a static library, so lacking a .m is still unhelpful.
It's even possible that the result of self.myProperty is random "other thing" that is only pretending to be SomeClass. Yeah, I know that sounds crazy. Welcome to class clusters with Core Foundation bridging. That's a thing. So there might not even be an implementation in the way you're thinking. Objective-C is a pretty insanely dynamic language.
As an example, the following is legal ObjC (it even works):
#interface NSString (Hello)
- (void)hello;
#end
#implementation NSString (Hello)
- (void)hello {
NSLog(#"I'm string's Hello!");
}
#end
...
self.myProperty = (SomeClass *)#"";
[self.myProperty hello];
You'd think maybe the linker could figure it out, but by the time we get to the linker, all object types are id and all methods are just selectors and method signatures. Most of the type information is gone.
So why does this fail to link if you call [[SomeClass alloc] init]? First note that it does compile, it just doesn't link. The reason is that [self.myProperty hello] is a message to an object. The linker doesn't know or care about the type of the object. It just needs a pointer to the instance. But [SomeClass alloc] is a message to a class. In order to link it, the linker has to have a pointer to the class. You'll find that any message to a class that isn't implemented will create a linker error (try [SomeClass initialize]).
In your code nothing happens at runtime because self.myProperty is nil, so there's no error. That would be the same even if you had an implementation. In the vast majority of cases the lack of an implementation file is going to be caught during link because somewhere in your system you probably call +alloc. So in practice, this shouldn't come up often at all, and this rare case is extremely difficult to detect without breaking a lot of legitimate ObjC.
This is a newbie question. I have an object that looks like the following (e.g. MyObject.h).
#import <Foundation/Foundation.h>
#import "JSONModel.h"
#protocol MyObject
#end
#interface MyObject : JSONModel
#property (strong,nonatomic) NSString* name;
#end
And the implementation looks like the following (e.g. MyObject.m).
#import "MyObject.h"
#implementation MyObject
#end
In my code elsewhere, I then define a NSMutableArray as follows.
NSMutableArray<MyObject>* list;
list = [[NSMutableArray alloc] init];
And I get this warning.
Incompatible pointer types assigning 'NSMutableArray<MyObject> ' from 'NSMutableArray'
I know from generics aren't supported out-of-the-box by Objective-C for collections (and that is not what I am trying to do here either), but my NSMutableArray is defined with such a protocol MyObject because I am trying to follow the examples from "JSONModel's" GitHub page.
The code still compiles, but with the warning above. How do I
make the warning go away, or
allocate/initialize NSMutableArray correctly?
Update:
I continued to search how to get rid of that warning, and it turns out if I create a NSMutableArray like the following, the warning goes away (and project compiles without errors). I will write a unit test and see if it works as expected.
list = (id)[NSMutableArray new];
NSMutableArray<MyObject>*
This does not mean what you think this means. This is not "an NSMutableArray of things that conform to <MyObject>." This is "a subclass of NSMutableArray that itself conforms to <MyObject>."
I have no idea what the link you provided is trying to achieve. Maybe they subclassed NSArray, or perhaps they've decorated NSArray with a category that tries to conform to the protocol. In either case, that's between a little dangerous and insane. I would talk to them about what they had in mind. My suspicion is that they're doing this as a decoration that appears to mean something and in fact means nothing. (That's not unheard of. Apple does it themselves with CFPropertyListRef, which appears to mean something but is in fact const void*, which can be quite surprising when you expect a warning that never comes.)
To the question of how to get rid of the warning, just get rid of the incorrect protocol decoration. It should be NSMutableArray*, not NSMutableArray<something>*.
BTW, this code gives you between zero and negligible benefit:
NSMutableArray<MyObject>* list = (id)[NSMutableArray new];
It gives you a tiny benefit in that a later call to list = someOtherKindOfList would give a warning, but that's an incredibly unusual operation (and 90% of the time you'll have to cast it anyway, so the warning will almost never catch real errors). Most notably, however, it will not throw a warning if you do [list addObject:someRandomType], which is the most common way to make a mistake here. So there's no point to the decoration.
After reading about properties and ivars in Objective C I'm still confused with MasterDetail template for iOS in XCode.
MasterViewController declares property for DetailViewController:
#class DetailViewController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
And ivar for array of objects:
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
Why is it that way? I just can't get why those two things are declared differently.
Thanks.
Declaring something as a "property" allows other objects to access and work with it. In The case above, adding "detailViewController" as a property to MasterViewController means other objects can access and work with the methods & properties DetailViewController exposes.
While the "_objects" variable is internal (or private) to the MasterViewController.
Apple's documentation is generally excellent. Apple's templates are... sometimes a little challenged. They are also sometimes slow to be updated as the language improves (or they are updated erratically). The objects array should really be a private property rather than an implementation-declared ivar. In any case, don't read too much into this.
Remember, the view controller shouldn't even be holding the data; it should be getting it from the model classes (which the template doesn't provide). Some of this is in order to keep the templates simpler to use (they're not actually example code; they're templates). Some of the weird code is due to limitations in the templating engine. (They didn't used to be able to prefix your classnames, even though they told you that you must prefix your classnames; it was very annoying.)
Unfortunately, seeing something in example code also doesn't necessarily mean it's a correct way to code. Much of Apple's example code would be completely inappropriate in production code (most of their examples lack proper model classes, or fail to handle errors correctly). But again, that's kind of the nature of example code. Focus on the coding guidelines. They're much more useful than learning from templates and examples.
I've been reading a lot of threads and blog articles about how to implement a singleton in objective-c, several of them maybe being a bit deprecated (year 2010 or earlier), and it seems like people have different opinions regarding this issue... Does Apple have documentation about implementing a singleton? I couldn't find it. If so, could somebody tell me where?
I need a singleton for a class that has some both public and private variables. Currently, this is the implementation I have for such class:
#interface MySingleton ()
#property (strong, nonatomic) NSString *state;
#end
#implementation MySingleton
#synthesize state = _state;
#synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
Should be this the recommended way? And how should I initialize the instance variables, public and private?
Another issue I'd like to make clear about singleton is: will this generate a memory leak? Is the use of singletons actually recommended in iOS?
Thanks
The above is correct, along with #miho's comment about includng the static object inside of the sharedInstance method. But there is no reason to override +allocWithZone:. Singletons in ObjC are generally "shared," not forced. You're free to create other instances of a "singleton." If it's illegal to create other instances, then you should make init perform an NSAssert rather than fooling the caller in +allocWithZone:. If your singleton is mutable (and most are), you absolutely should not override +allocWithZone: this way.
Another issue I'd like to make clear about singleton is: will this generate a memory leak?
No. This object will never be released, but it will always be accessible. That is not a leak.
Is the use of singletons actually recommended in iOS?
Yes, and it is a very common pattern, used all over the Cocoa frameworks. That said, there are various other patterns that have started to recently become somewhat popular among developers. Dependency Injection is getting some interest, though I don't see it in practice very often. Reducing your reliance on singletons can improve testability, and I have been experimenting recently with how to eliminate some of them in my code with some success. But they have a long, proud history in Cocoa, and I do not consider them a problem.
EDIT: you have one actual bug in your code. You should be calling [[self alloc] init], not [[super alloc] init]. There's no reason to ever call +allocWithZone:, just use +alloc. (The time when ...WithZone: methods were useful has long passed.)
In Xcode, under 'Search Documentation' enter Creating a Singleton Instance. There are lots of results (but the link above, at the bottom of the page, has example code).
Yes, this is the recommended way. There is only one small difference of how I use it: I define the sharedObject as static variable inside the + (MySingleton *)sharedInstance method, because it shouldn't be possible to access the variable from anywhere else then from the getter method.
And no, you won't create a memory leak. When your app is terminated all reserved memory used by your app will be released anyway and there is no other situation where a static shared instance should get released. In pre-ARC area it even was common to override the release method do prevent accidentally releasing of the object.
A bit of warning using gcd for singletons:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
if the init method for some reason addresses the singleton object directly or indirectly, there will be a deadlock. For this reason I believe that the more appropriate way to write a singleton is through the
+ (void) initialize
method
I am still using the singleton header thingy from CocoaWithLove - may be a bit dated but still works like a charm. It basically does the same as described here referring to Apples documentation and I would assume at least Apple's documentation (bottom of this page) is still valid. There are people assuming it will stay valid indefinitely sine it is the official solution Apple suggested.
Not a complete noob I am quite new to iOS programming and to Ojbective-C. I mainly come from a background of C (DSP, Microcontrollers), Delphi XE2/Pascal , Visual Basic and Java (desktop and Android apps).
I mainly learned Cocoa with the book "Beginning iOS 5 Development", from Apress.
Recently I watched videos of the WWDC 2012 and went through some of their sample code, and I must say that I am confused of what is the proper way of writing my apps and more specifically with the #property/#synthesize words.
In the book most (not to say all) of the sample code uses to define a property as for example
ViewController.h
#property (strong, nonatomic) NSMutableArray *list;
ViewController.m
#synthesize list;
then all the code access synthesize list with
self.list
or even simply
list
Now in every WWDC code sample I read I see that programmers define a property but then, in the .m file they do things like
#synthesize list = _list;
and access sometimes
self.list
or
_list
I am confused. What is the correct practice ? As Apple programmers all use underscore I think I should do it that way but why the book did not ? Is there a difference between list and _list ? And more over, as I am in the same object why sometime use self.list and sometimes list/_list.
Sometimes they don't use #synthesize, I assume it's when they want to re-write their own accessors and mutators (which is never my case up to now).
I have read here and there on the web but nothing was clear enough to set my mind right, so I count on StackOverflow to bring light here.
Last but not least I prefer and answer based on current iOS 6 best practice/programming technique. Useless to tell me how to do it correctly in older iOS.
There is no correct way. There is only your preferred style.
The lastest compilers do an implicit synthesise on the property declaration.
#synthesize list = _list; .
Nothing is ever written in your code. It just happens.
However that doesnt stop you doing this explicitly.
#synthesize list = somethingelse;
So when you ask for a pointer to list via the accessor (self.list) you will get a pointer to somethingelse
In most cases NSMutableArray *thing = self.list is equivalent to NSMutableArray *thing = somethingelse
And just because Apple uses a style doesn't mean that you have to do it. Each company usually has their own coding style.
The main problem with using #synthesize list; is that it poses the risk that you can write either
self.list = thing or list = thing .
The former uses the sythesised setList: accessor while the latter doesn't and put the risk of related bugs in your code , though its not as bad with ARC as you dont get leaks happening for strong properties.
What ever style you use, keep it consistent and be aware of the effects of using an ivar directly list = thing as compared to using its accessor self.list = thing
This is a language feature that has had its usage evolve rapidly over the past few years, which explains the various forms. With the most recent tools, you can choose to ignore #synthesize and have things work reasonably.
The default behavior in that case produces the same effect as #synthesize list = _list;.