From the Core Data docs:
A property name cannot be the same as
any no-parameter method name of
NSObject or NSManagedObject—for
example, you cannot give a property
the name “description”
Ok, so -description is blocked for property names. I guess it's because of KVC. But what exactly does "no-parameter" mean? Is that any method which does not take a parameter?
So in other words:
Any property of NSObject or NSManagedObject
ANY method name of NSObject or NSManagedObject, which does not take a parameter
Did I get that right?
Any unary message is a no parameter method name. I.e., -copy, -retain, -release, are all unary messages when sent, and no parameter methods when you define them. An example of a keyword message (or a method with parameters) is: +stringWithString:, etc.
Related
I'm reading through the Swift documentation about type methods and type properties, and I cannot for the life of me figure out why it says this particular thing (in bold):
Within the body of a type method, the implicit self property refers to
the type itself, rather than an instance of that type. For
structures and enumerations, this means that you can use self to
disambiguate between type properties and type method parameters, just
as you do for instance properties and instance method parameters.
More generally, any unqualified method and property names that you use
within the body of a type method will refer to other type-level
methods and properties. A type method can call another type method
with the other method’s name, without needing to prefix it with the
type name. Similarly, type methods on structures and enumerations
can access type properties by using the type property’s name without a
type name prefix.
So, why is this pointing out structures and enumerations being able to do these things when, as far as I know, you can do these things with any kind of type methods/parameters (i.e. classes as well)? It makes me think I'm missing something.
The page in the documentation I'm looking at is here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
Apparently I wasn't the only one with this question. I'm not sure how I didn't see this post before: https://softwareengineering.stackexchange.com/questions/276962/static-properties-and-implicit-self-property-in-structures-and-enumerations-vs
In a Swift method you can access a property using self.property or simply property.
Is there any difference? Is one of these preferred? Is there any style guide published by Apple which requires one or the other?
In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method.
The main exception to this rule occurs when a parameter name for an
instance method has the same name as a property of that instance. In
this situation, the parameter name takes precedence, and it becomes
necessary to refer to the property in a more qualified way. You use
the self property to distinguish between the parameter name and the
property name.
Reference: The Swift Programming Guide from Apple.
How does Swift implement ARC in property attributes? For example, how do I make my String variable use copy instead of strong in Swift?
You can use the #NSCopying attribute when you want the copy behaviour from Objective-C.
From the Swift Book:
Apply this attribute to a stored variable property of a class. This
attribute causes the property’s setter to be synthesized with a copy
of the property’s value—returned by the copyWithZone method—instead of
the value of the property itself. The type of the property must
conform to the NSCopying protocol.
The NSCopying attribute behaves in a way similar to the Objective-C
copy property attribute.
However, in the specific case of String properties, it's not necessary to do so.
Strings are a value type in Swift. As such, when an existing String is assigned to a new variable, the variable actually stores a copy of the String, rather than a reference to the existing one.
Swift’s String type is a value type. If you create a new String value,
that String value is copied when it is passed to a function or method,
or when it is assigned to a constant or variable. In each case, a new
copy of the existing String value is created, and the new copy is
passed or assigned, not the original version.
So, the #NSCopying attribute is to be used when you have properties of a reference type that you want to set using the copy behaviour.
I have a class called AbstractBook, which has a property:
#property(strong) AbstractPage *page;
Now say I have a subclass of AbstractBook called WhiteBook and a subclass of AbstractPage called WhitePage. I want the WhiteBook class to inherit the page object, but in this class, I want it to be the specific WhitePage class instead of AbstractPage.
So, in WhiteBook, I just redeclared the property as WhitePage:
#property(strong) WhitePage *page;
However, I am getting a warning: WhitePage is incompatible with AbstractPage inherited from AbstractBook. What is the right way to implement what I'm going for?
What you want to do is fundamentally impossible. Don't forget that this:
#property(strong) AbstractPage *page;
declares a getter and a setter.
Generally speaking (this is for OO programming generally, not just Objective-C), there is no problem with an override getter returning a subclass of the return type of the super class implementation because this does not break the API contract. In your case, an instance of WhitePage is also an AbstractPage.
However, the setter is different. You can't restrict the type of the parameter because your subclass must be useable anywhere where an AbstractBook is used, so code that invokes the setter on something that it thinks is an AbstractBook is entitled to pass in an instance of any AbstractPage subclass, because that is what the API says.
I think what I would do is add a method to AbstractBook called something like
-(bool) isLegalPage: (AbstractPage) aPage;
that returns true always in the base class but true only for white pages in WhiteBook. Then I would manually implement the setter as follows:
-(void) setPage: (AbstractPage*) aPage
{
if (![self isLegalPage: aPage])
{
// throw an exception or do other error notification
}
else
{
Do the assignment according to reference count/ARC/GC model
}
}
Document that the setter will throw an exception if the page is not legal and that people should use the isLegalPage: method to test this.
The alternative id to have a read only property and use different setters in the base class and subclass, or don't have a setter at all in the base class.
There is no property type covariance in Objective C, so if you want a property returning a subclass of AbstractPage, you need to define a separate property, say whitePage, in your WhiteBook subclass. You can return the same value from your page property, too, and it would work. Moreover, if your users call methods on the AbstractPage*, they would not even need to cast it to WhitePage*.
Remember to program to the interface not implementation.
======================
Option: 1
If your Whitebook truly is a descendant of AbstractBook you don't need to make WhiteBook have a new property called "page", since your AbstractBook already declares it your WhiteBook gets it for free.
As long as your WhitePage inherits from AbstractPage you should be able to cast your page object as a WhitePage. Then you get all original functionality of AbstractPage, plus that of WhitePage.
So you shouldn't need to re-declare page in Whitebook. If you go to your Whitebook.h file and delete this line
#property(strong) WhitePage *page;
Then go into your Whitebook.m file and type self.page you shouldn't get any compile warnings. Then you can cast page as WhitePage and you should be good to go.
WARNING: This means you will need to cast page as a WhitePage where ever you use it, which is not ideal.
======================
Option: 2
You may also try leaving the code as you have it, but make sure to synthesize the "page" prop again in WhiteBook.
======================
Option: 3
You may also try leaving the code as you have it, but make sure to use #dynamic for the "page" prop in WhiteBook. Then implement the getter yourself and return a WhitePage instead of an AbstractPage.
How to override a superclass' property with more specific types?
Normally if you use #synthesize in your AbstractBook class and #dynamic in your WhiteBook class, it should work fine (unless, of course, you use the AbstractPage synthesized method to assign a non-WhitePage to page).
Tried many ways based on other questions asked here but could not get a method call to another class to compile.
I'm writing a dedicated class to process arithmetic, for example class Arithmetic. It has no class variables. It subclasses no class (though I tried NSObject with failure). It will have methods of the type:
+ (NSString *)calculateEnergy:(NSString *)weight;
that I want to call from another class, in a static-method way, like:
self.label.text=[arithmetic calculateEnergy:#"8.0"];
where 'Arithmetic *arithmetic' is declared and given a retain property (synthesised etc.) in the header and implementation of the class wanting to access the calculateEnergy method.
I've tried various suggestions, such as variations on:
[(Arithmetic *) arithmetic calculateEnergy:#"8.0"];
every time getting an "Accessing unknown 'calculateEnergy' getter method"
Thank you so much in advance!
Though I don't have the complete picture, your method definition is for a class-level, static method, as opposed to an instance method. You would want to call it as
self.label.text = [Arithmetic calculateEnergy:#"8.0"];
You also would not need to create an instance of Arithmetic to call the method you have there.
Is arithmetic not an instance of Arithmetic? If instead you try self.label.text=[Arithmetic calculateEnergy:#"8.0"]; you should be OK.