Identical names for methods and properties - objective-c

The following code compiles just fine - but are there any issues with it?
I couldn't find any guidelines for Objective-C that would discourage us from using the same identifier for both, properties and method names:
#interface MouseCursorHelper : NSObject
#property (nonatomic, readwrite, retain) NSCursor* rotateCursor;
+ (NSCursor*) rotateCursor;
#end
FWIW, the class is implemented as a singleton modeled after NSCursor to offer app specific cursors.

It could be a little confusing.
The property generates 2 instance methods for you:
- (NSCursor *)rotateCursor;
- (void)setRotateCursor:(NSCursor *)rotateCursor;
And you also have a class method:
+ (NSCursor *)rotateCursor;
It isn't clear from a user point of view what the class method does. Documentation would help.

There's absolutely no problem with what you are doing there at all. All you are doing is saying that both the class object and instances of the class respond to rotateCursor. That's not really conceptually different to instances of NSString responding to intValue and instances of NSNumber responding to intValue. They are just different kinds of object.
In fact, you'll find several instances of Apple doing the same thing in the Cocoa framework e.g.
[NSString class]; // Sending class to the class
[#"foo" class]; // Sending class to an instance of the class.

Related

Setup BOOL property in Model

Customizing an iOS app in objective-c. Not super familiar with the language, and this simple task of setting up a boolean property has taken me too long.
Can anybody offer some advice here?
Video.h
#property (nonatomic, retain) NSNumber * hasCustomThumbnail;
Video.m
#implementation Video
#dynamic hasCustomThumbnail;
#end
OtherFile referencing the video
// have tried these two an many other things...
video.hasCustomThumbnail = [NSNumber numberWithBool:NO];
video.hasCustomThumbnail = #NO;
The error I get no matter how many dozens of ways I've tried this is:
'NSInvalidArgumentException', reason: '-[Video setHasCustomThumbnail:]: unrecognized selector sent to instance 0x60c0004925c0'
Have tried many suggestions including this: Using a BOOL property
I also know the video is referenced correctly because autocomplete suggests "hasCustomThumbnail" as I start typing.
I simply cannot believe how hard OBJ-c is making this :-)
Any suggestions?
The issue is that you have declared it as #dynamic. Just remove this line from the Video.m. Xcode will automatically synthesize the getters and setters.
either of this works.
[obj setHasCustomThumbnail:[NSNumber numberWithBool:true]];
obj.hasCustomThumbnail = [NSNumber numberWithBool:true];
#dynamic just tells the compiler that the getter and setter methods
are implemented not by the class itself but somewhere else (like the
superclass or will be provided at runtime).
#synthesize will generate getter and setter methods for your property.
So when you define a property with #dynamic, either your superclass or runtime should provide the necessary getter and setter. here no one has provided anything, that is the reason it is saying the unrecognized selector sent to an instance. This error will come only if it couldn't able to find a proper method for the object. Hope this will clear your doubts.
one practical use of #dynamic is that when you inherit your class from
NSManagedObject, the core data will provide the setter and getters for
the properties.
This problem is not related to BOOL or NSNumber. It is due to your calling setIsCustomThumbnail on class Video.
Either you are doing video.isCustomThumbnail = or [video setIsCustomThumbnail:] but your class does not declare this isCustomThumbnail. From your code seems you mispelled isCustomThumbnail as hasCustomThumbnail.
So make up your mind and use single name.

How does Objective-C handle subclasses and superclasses with the same property name?

In iOS 8 NSManagedObject was given a new property:
#property (nonatomic, getter=isDeleted, readonly) BOOL deleted;
Unfortunately, I have already been using a property of the same name in my subclasses of NSManagedObject to mark objects as soft deleted.
#property (nonatomic, retain) NSNumber *deleted; // BOOL in CoreData model
This results in a ton of compiler warnings:
'getter' attribute on property 'deleted' does not match the property inherited from 'NSManagedObject'
How does Objective-C handle a superclass and subclass having the same property? I obviously plan on renaming this property across the board but there is already multiple versions of this app in the wild and I am curious of the implications.
#property accessors are just regular methods, so they're handled exactly the same way as other methods. In this case, I believe you luck out because the framework (NSManagedObject) getter is -isDeleted rather than -deleted. Since your subclass implements -deleted, there's technically no conflict with the getter.
Now, the real issue will be, if NSManagedObject internally implements the corresponding -setDeleted: setter, your subclasses implementation of that method will be called instead of NSManagedObject's implementation. A quick check using -instancesRespondToSelector: seems to reveal that NSManagedObject does not actually implement -setDeleted: (on OS X, anyway). So, you might be OK.
The actual implications of a conflict like this for your app (assuming a case where you weren't lucky as described above) are not clear to me, not knowing exactly what your app is doing or why. For what it's worth, the -isDeleted method on NSManagedObject is not at all new. It was simply promoted to a declared #property in iOS 8 (presumably to ease Swift interoperability). It was probably always a bad idea to have your own deleted property...

Proper use of Objective-C protocols

I'm using my free time to play with Objective C. I was reading about Protocols but I'm afraid I might be using it wrong, considering I'm using it the same way (almost the same at least hehe) I do with C# code.
So, here is what I got. I have a protocol, a class manager to weakly couple my views and two views that implement the protocol.
#protocol IView <NSObject>
- (void) loadViewToScreen;
#end
#interface ViewManager : NSObject
#property (atomic, weak) id<IView> document;
#property (atomic, weak) id<IView> browser;
//Singleton
+ (id) getInstance;
#end
Then I call one view the views from each other.
ViewManager *vm = [ViewManager getInstance];
[vm.browser loadViewToScreen];
I'm not interested here what the best way to load views into the screen. It's just a mock code to test protocols.
I could not get the manager to use pointers to the protocols. So I'm afraid I'm getting view copies around. Did I get this right?
Thanks,
Lucas
A protocol, concpetually, is just a part of the type of an object or class. You can't get a pointer to a protocol. (Well, actually you can obtain a protocol object, but that's runtime mocking which doesn't seem to be what you want).
Don't be afraid about getting copies, though. Unless you copy an object or assign it to a copy property, you'll get pointers to the same instance.

Unexpected content in default files generated for opengl template in xcode

I was just starting a new opengl project in xcode. When I was going through the default files created, I was confused by this following line of codes in the viewController interface.
#interface RetinaTestViewController ()
#property (nonatomic, retain) EAGLContext *context;
#property (nonatomic, assign) CADisplayLink *displayLink;
- (BOOL)loadShaders;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
- (BOOL)linkProgram:(GLuint)prog;
- (BOOL)validateProgram:(GLuint)prog;
#end
My question is why this is written in the implementation of viewController rather than in the interface itself. This may be very basic but I just started to work with the openGL stuff. Please do help.
I don't think this is really OpenGL related, but Objective-C has something called categories, which allow you to add extra methods to an existing class. You can add them to any class you want, whether you have the source code or not. The syntax looks like:
#interface classname (categoryName)
- (void)extraMethod1;
- (void)extraMethod2;
#end
#implementation classname (categoryName)
- (void)extraMethod1
{
}
- (void)extraMethod2
{
}
#end
And, as I say, you can use that to add methods to any class, including e.g. NSString, NSDictionary and the other Foundation objects.
The brackets after the classname in the interface declaration dictate that this is a category, not a full interface definition. Historically there was no way to add extra storage to a class through a category, so you may not declare member variables in categories. Hence there's no {} section.
In the modern runtime (on 64bit OS X and iOS), you can add extra storage via #properties, as Apple appear to do in the code you've given.
Here Apple are using category methods to create something like private methods — in this case methods that everyone in the class knows are there but which aren't declared externally. That's a design decision, to keep the bits that other people are likely to look at neat and to indicate the programmer's intent.
What's going on is that:
the bits of RetinaTestViewController that Apple want everyone else to know about are declared in the header file
the bits that aren't meant to be exposed are declared only in the implementation file
A well-designed object should expose a public interface and conform to that interface, while doing whatever is necessary internally and keeping its internals secret.
You can read a little more category methods here, here and here (scroll down to number 11).

Objective-C categories: Can I add a property for a method not in my category?

I want to use a category to make a method on the original class available as a property as well.
Class A:
#interface ClassA
- (NSString*)foo;
#end
Class A category
#interface ClassA (Properties)
- (void)someCategoryMethod;
#property (nonatomic, readonly) NSString *foo;
#end
Now when I do this, it seems to work (EDIT: Maybe it doesn't work, it doesn't complain but I am seeing strangeness), but it gives me warnings because I am not synthesizing the property in my category implementation. How do I tell the compiler everything is actually just fine since the original class synthesizes the property for me?
Here's the warning you're getting:
warning: property ‘foo’ requires method '-foo' to be defined - use #synthesize, #dynamic or provide a method implementation
To suppress this warning, have this in your implementation:
#dynamic foo;
If something's declared in your category's interface, its definition belongs in your category's implementation.
I wrote two articles on this, though the concept is slightly different from the question you're asking.
Add properties to categories without touching the base class: http://compileyouidontevenknowyou.blogspot.com/2012/06/adding-properties-to-class-you-dont.html
Access iVars from categories: http://compileyouidontevenknowyou.blogspot.com/2012/06/if-you-want-to-keep-everything-in-your.html
This is a LOT better than method swizzling, at least: way safer.