Objective-C constants in protocol - objective-c

In my objective-c project, I have a protocol like this:
#protocol MyProtocol
-(id) get:(NSString *) key;
-(void) set:(NSString *) key withValue:(id) value;
-(NSValue *) getSize;
-(void) setSize:(NSValue *) value;
-(NSValue *) getBounds;
-(void) setBounds:(NSValue *) value;
#end
OBJC_EXPORT const NSString *MYPROTOCOL_SIZE;
OBJC_EXPORT const NSString *MYPROTOCOL_BOUNDS;
And basically, those specific methods (getSize, getBounds, setSize, setBounds) are supposed the value that is supposed to be stored in MYPROTOCOL_SIZE and MYPROTOCOL_BOUNDS, respectively.
However, I cannot find an effective way to set those constant strings, by concatenating the results of other methods, because it gives me the error: initializer element is not constant when I try to set them directly. Is there a way I can guarantee that the objects will always be initialized. (e.g. in a classes load method), without having to manually call code when my program runs?

Well first of all, you should learn the naming convention, for accessors you have - (Type); and - (void)set:(Type)value; whereas in your case you did: - (Type)get; and - (void)set:(Type)value;
I advise you to use #property for your size and bounds accessors too.
Now about the "const" in the NSString variable declaration, it doesn't make sense. Const applies to the type on its left and in case it is at the beginning of the line it applies to the token directly on its right. So what you have is a "const NSString" which doesn't make sense because NSString is already immutable, and sending mutating messages to a const object doesn't issue any warning or errors...
What you actually want is "NSString *const" which states that the pointer to your NSString is constant, you can only assign it at initialization and then it doesn't change...
Now about the protocol... Are you sure you want a protocol in your case ? And not an abstract class that would have your 2 NSString as readonly accessors ?

Related

How do I get the Objective-C class of an ivar?

I have a bunch of simple NSManagedObjects I create in a unit test. They just have a single name attribute of type NSString *. I always give my NSManagedObject the same entityName and Class name.
I want to avoid having to write the following code 30 times to set up a unit test:
#interface FooTest : GHTestCase {
Foo *foo;
}
#end
#implementation FooTest
- (void) setUp {
[super setUp];
foo = [NSEntityDescription insertNewObjectForEntityForName:#"Foo"
inManagedObjectContext:managedObjectContext];
foo.name = #"foo";
}
#end
Since foo is an ivar, I would think I should be able to write a macro to grab the type of foo (Foo), and use to create my Foo:
#define InsertManagedObjectByVariable(variable) \
do { \
variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])]; \
variable.name = (NSString *) CFSTR(#variable);
} while(0)
However, this causes the following warning in clang:
variable = [NSEntityDescription insertNewObjectForEntityName:NSStringFromClass([typeof(variable) class])];
^
Expected expression
I also thought I could try to determine the type using the objective-c runtime IVar from Ivar class_getInstanceVariable(Class cls, const char* name), but the only IVar type information available from the type encoding from ivar_getTypeEncoding is id, which isn't enough.
Can someone think of a way to obtain the type information of an IVar either at compile time or runtime?
I haven't tried obtaining class information from an ivar, but I know that #property declarations do encode information about the class. For instance, this property declaration:
#property (copy) NSString *normalString;
results in this attribute string (retrieved using property_getAttributes()) at runtime:
T#"NSString",C,VnormalString
I've written some open source parsing code for this information.
Once you have the class name, you can convert it into an actual Class object using NSClassFromString(), and message the result from there.
Disclaimer: This probably shouldn't be depended upon for production applications, as it is undocumented.
An id is an id. At runtime, all Objective-C objects have the same type (objc_object). This is tied up in the dynamic nature of ObjC. For example, an object can change classes at runtime, new classes can be created, and the class hierarchy can change. You can ask a specific instance what its type is (since this is stored in objc_object), but a pointer to an object is just a pointer to an object. Even less than that: it's really just a pointer to a C struct that happens to have extra memory allocated at the end (to hold subclass ivars).
Your macro seems interesting, but you'll probably need to pass the classname as the second parameter rather than autodetecting it.
Maybe i misunderstand what you are trying to achieve.
To get the class of an iVar, can't you use the class method of the iVar?
like:
NSString *aString = #"random string";
NSLog(#"%#",NSStringFromClass([aString class]));

Objective-C, interface declarations with properties

In the following common sample,
////
#interface MyObject : NSObject
{
#public
NSString * myString_;
}
#property (assign) NSString * myString;
#end
#implementation MyObject
#synthesize myString = myString_;
#end
////
why declare myString_ in the interface at all?
I ask because we can still get and set myString in the implementation using self.myString, [self myString], self.myString = ... and [self setMyString:...] and in fact we must if instead it's being retained.
This is a matter of preference/convention for some. By default, doing:
#property (assign) NSString * myString;
...followed by:
#synthesize myString;
...will give you three things. You get a setter method that can be accessed as self.myString = #"newValue" or [self setMyString:#"newValue"], a getter method that can be accessed as NSString* temp = self.myString or NSString* temp = [self myString], and an instance variable named myString that be be accessed directly inside of your class (i.e. without going through the getter and setter) and used to set and get the property value, and which is used internally to back the property.
If you like you can do #synthesize myString = someOtherVarName, and then you still get the setters and getters just as before, but instead of the myString instance variable the someOtherVarName instance variable is used to back the property, and no myString variable is created.
So why ever use the more verbose syntax? There is never any case that requires that you do so, but some people prefer to do so when dealing with properties that are declared retain or copy. The reason for this being that setting a property declared retain or copy via its generated setter method will affect the retain-count of the object being set/unset. Doing the same thing by accessing the instance variable directly will not.
So by aliasing the instance variable to something else, you can make a distinction in the code along the lines of "anything that does xxx.myString = Y is modifying the retain count, while anything that does someOtherVarName = Y is not". Again, it's not necessary to do this, but some people prefer to.
You should be able to skip it. Modern compilers allow that.
When you define a property, you are actually declaring how the getter and setter methods are constructed for a particular instance variable. Earlier it needed the instance variable to be defined so you declared it. It also allowed the property name to differ from the instance variable name via #synthesize myProperty = myIVar;. Now you don't need to do this as the modern compilers generate the instance variable for you.
The dot syntax is actually a convenience thing as you would've noticed. It doesn't directly refer to the instance variable but the methods myProperty and setMyProperty:. You can even call myArray.count where count isn't a property (I wouldn't recommend it even though lot of people seem to like it).
While there is a difference between the two, the gap seems to be slowly closing.
That's just a problem about point of view. If you access ivar directly, it's you're accessing it internally. If you're using property, you're not accessing ivar (semantically). You're using accessing method of the object. So you're handling the self as like external object which the internal is unknown.
This is encapsulation problem of Object-Oriented paradigm.
And I recommend some tricks when using properties.
The ivar declaration is optional, not required. Compiler will generate it automatically.
You should set the ivar as #protected or #private to encapsulate it correctly. (at least there is no reasonable reason)
I recommend to use nonatomic if you don't need threading lock when accessing the property. Threading lock will decrease performance greatly, and may cause strange behavior in concurrent execution code.
You can use this code to do same thing.
#interface MyObject : NSObject
#property (assign,nonatomic) NSString * myString;
#end
#implementation MyObject
#synthesize myString;
#end
And this will be transformed roughly something like this.
#interface MyObject : NSObject
{
#private
NSString* myString; // Ivar generated automatically by compiler
}
#end
#implementation MyObject
// Methods with thread synchronization locking generated automatically by compiler.
- (NSString*)myString { #synchronized(self) { return myString; } }
- (void)setMyString:(NSString*)newMyString { #synchronized(self){ myString = newMyString; } }
#end
In fact, I'm not sure about synchronization lock with assign behavior directive, but it's always better setting it nonatomic explicitly. Compiler may optimize it with atomic operation instruction instead of locking.
Here is reference document about the properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17
With the modern Obj-C runtime, declaring the ivar is more of a formality than anything else. However, there are some memory management things to keep in mind.
First, the property declaration for an object type is usually retain, or for strings it may be copy. In either case, the new object is retained.
Given the following code:
NSString *string = [[NSString alloc] init];
myString_ = string;
self.myString = string; // If the property was retain or copy
The second assignment would leak; the first would not. This is because the property would retain something that already has a retain count of 1—it is now at 2. When you release the property in dealloc, the count goes to 1, not 0, so it won't be released. With the first option, however, the retain count stays at 1, so dealloc brings it down to 0.
In your example, leaving the property as assign will make the ivar declaration a formality.

Why am I getting "incompatible pointer type"?

I am trying to create a custom object that simply inherits the NSString class and overrides the 'description' method.
When I compile, however, I am getting a warning:
Incompatible pointer types initializing 'OverrideTester *' with an expression of type 'NSString *'
Here is my code:
main.m
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSAutoreleasePool.h>
#import "OverrideTester.h"
int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *str = #"Programming is fun";
OverrideTester *strOverride = #"Overriding is fun";
NSLog (#"%#", str);
NSLog (#"%#", strOverride);
[pool drain];
return 0;
}
OverrideTester.h
#import <Foundation/Foundation.h>
#interface OverrideTester : NSString
-(void) description;
#end
OverrideTester.m
#import "OverrideTester.h"
#implementation OverrideTester
-(void) description
{
NSLog(#"DESCRIPTION!\n");
}
#end
NSString is part of a class cluster. You cannot just create arbitrary subclasses of it, and when you do, you can't assign constant strings to them (which are type NXConstantString). See Subclassing Notes in the NSString documentation. Generally you don't want to subclass NSString. There are better solutions for most problems.
you are assigning an instance of NSString to your variable of type OverrideTester. If you want an instance of your class, you need to instantiate an instance of that class; type-casting will never change the class of an instance.
description is defined as returning an NSString*:
- (NSString *)description;
Do not try to learn about subclassing and overriding methods by subclassing NSString (or any other class cluster). If you want to play with subclassing and such -- a very good idea when new to the language, assuredly -- then subclass NSObject, potentially multiple levels , and play there.
How do you mean to subclass NSObject,
potentially multiple levels? Isn't it
possible NSObject might have
conflicting methods compared to other
class clusters or just not have them
available to override?
If your goal is to figure out how method overrides work (which I thought it was), then you'd be better off doing it entirely yourself.
I may have mis-read your question.
In any case, subclassing NSString is pretty much never done. There are very very few cases where it is useful. Overriding description in anything but custom classes specifically for debugging purposes is useful, yes. Calling description in production code should never be done.
Also, why would description return an
NSString* in this code?
What would happen if something that expects an NSString* return value were to call your version that doesn't return anything?
A crash.
You are declaring a variable named strOverride of type pointer to OverrideTester. But to that variable, you are trying to assign a pointer to an NSString. You cannot assign a superclass to a variable of a subclass. Imagine a generic class TwoWheeled and a derived class Motorbike. A Motorbike can be treated like a TwoWheeled, but not the other way round as the Motorbike has features a normal TwoWheeled might not have like a motor.

NSString inheritance

I'm doing an useless thing for my first step in Obj-C
#interface String : NSString
{
int m_isnull;
}
- (id) init;
- (int) isNull;
#end
#implementation String
- (id) init
{
self = [super init];
m_isnull=1;
return self;
}
- (int) isNull
{
return m_isnull;
}
#end
test :
String *a;
a=#"ok";
Works fine, but just 2 little questions
1) When I'm compiling I have this warning
warning: incompatible Objective-C types assigning 'struct NSString *', expected 'struct String *'
I don't know how to avoid it !?
2) a=#"ok" is a fastest way to initialize a string, but when I'm debugging, I don't stop by at my init constructor why ?
#"ok" is actually a NSString like 1 is an integer. That's why you get this compiler warning.
There are also #"" NSString literals.
It is essentially shorthand for
NSString's +stringWithUTF8String
method. Mac Player
already stated that it is used to
distinguish this sort of string
literal from a char * string literal
in C.
Source http://guides.macrumors.com/Objective-C_Tutorial#The_.40_symbol
Normally you would create a Category in Objective-C to extend the NSString Class.
Take a look at the NSString class reference:
It is possible to subclass NSString (and NSMutableString), but doing so requires providing storage facilities for the string (which is not inherited by subclasses) and implementing two primitive methods. The abstract NSString and NSMutableString classes are the public interface of a class cluster consisting mostly of private, concrete classes that create and return a string object appropriate for a given situation. Making your own concrete subclass of this cluster imposes certain requirements (discussed in “Methods to Override”).
If you really want to add an -isNull method to NSString you would probably be better off adding it as a category.
I think you might also want to try writing -(BOOL) isNotBlank instead. Consider what happens if you call -isNull on a nil pointer, is that the return value you would expect?
#"ok" is an NSString object. You're creating an instance of the superclass and trying to assign it to a subclass pointer. Think of subclassing as an "is-a" relationship. In your example, String is an NSString. NSString is not a String. Therefore, you can't assign an NSString object to a String pointer.

Is there a difference between an "instance variable" and a "property" in Objective-c?

Is there a difference between an "instance variable" and a "property" in Objective-c?
I'm not very sure about this. I think that an "property" is an instance variable that has accessor methods, but I might think wrong.
A property is a more abstract concept. An instance variable is literally just a storage slot, like a slot in a struct. Normally other objects are never supposed to access them directly. A property, on the other hand, is an attribute of your object that can be accessed (it sounds vague and it's supposed to). Usually a property will return or set an instance variable, but it could use data from several or none at all. For example:
#interface Person : NSObject {
NSString *name;
}
#property(copy) NSString *name;
#property(copy) NSString *firstName;
#property(copy) NSString *lastName;
#end
#implementation Person
#synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:#" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:#" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
#end
(Note: The above code is buggy in that it assumes the name already exists and has at least two components (e.g. "Bill Gates" rather than just "Gates"). I felt that fixing those assumptions would make the actual point of the code less clear, so I'm just pointing it out here so nobody innocently repeats those mistakes.)
A property is a friendly way of implementing a getter/setter for some value, with additional useful features and syntax. A property can be backed by an instance variable, but you can also define the getter/setter to do something a bit more dynamic, e.g. you might define a lowerCase property on a string which dynamically creates the result rather than returning the value of some member variable.
Here's an example:
// === In your .h ===
#interface MyObject {
NSString *propertyName;
}
// ...
#property (nonatomic, retain) NSString *propertyName;
// === In your .m #implementation ===
#synthesize propertyName /* = otherVarName */;
The #property line defines a property called propertyName of type NSString *. This can be get/set using the following syntax:
myObject.propertyName = #"Hello World!";
NSLog("Value: %#", myObject.propertyName);
When you assign to or read from myObject.propertyName you are really calling setter/getter methods on the object.
The #synthesize line tells the compiler to generate these getter/setters for you, using the member variable with the same name of the property to store the value (or otherVarName if you use the syntax in comments).
Along with #synthesize you can still override one of the getter/setters by defining your own. The naming convention for these methods is setPropertyName: for the setter and propertyName (or getPropertyName, not standard) for the getter. The other will still be generated for you.
In your #property line you can define a number of attributes in parens for the property that can automate things like thread-safety and memory management. By default a property is atomic meaning the compiler will wrap #synthesized get/set calls with appropriate locks to prevent concurrency issues. You can specify the nonatomic attribute to disable this (for example on the iPhone you want to default most properties to nonatomic).
There are 3 attribute values that control memory management for any #synthesized setters. The first is retain which will automatically send release to old values of the property, and retain to the new values. This is very useful.
The second is copy which will make a copy of any values passed in rather than retaining them. It is good practice to use copy for NSString because a caller could pass in an NSMutableString and change it out from under you. copy will make a new copy of the input which only you have access to.
The third is assign which does a straight pointer assign without calling retain/release on the old or new object.
Lastly you can also use the readonly attribute to disable the setter for the property.
I use properties for the interface part - where the object interfaces with other objects
and instance variables are stuff that you need inside your class - nobody but you is supposed to see and manipulate those.
By default, a readwrite property will be backed by an instance variable, which will again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for the life of the object. The memory used for instance variables is allocated when the object is first created (through alloc), and freed when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName.
Previously people use properties publicly and ivars for private usage, but since several years ago, you can also define properties in #implementation to use them privately. But I'd still use ivars when possible, since there are less letters to type, and it runs faster according to this article. It makes sense since properties are mean to be "heavy": they are supposed to be accessed from either generated getters/setters or the ones manually written.
However, in recent codes from Apple, ivars are not used anymore. I guess because it's more like objc rather than C/C++, plus it's easier to use properties with assign, nullable, etc.
Objective-C Property vs Instance variable (iVar)
[Swift variable, property...]
Instance variable
#interface SomeClass: NSObject
NSString *someVariable;
#end
Property
#interface SomeClass: NSObject
#property (nonatomic, strong) NSString *someVariable;
#end
Property uses Instance variable inside. property = variable + bounded getter/setter. It is a method call with variable syntax and access
#property generates getter and setter methods(accessor methods) which uses backing ivar(aka backing field) which you can use via underscore _<var_name> (_someVariable).
Since it calls a method - method dispatch mechanism is used that is why KVO[About] can be applied
When you override accessor methods backing iVar is not generated that is why you can declare a new property explicitly or use #synthesize[About] to generate a new one or link with existing
#import "SomeClass.h"
#interface SomeClass()
#property (nonatomic, strong) NSString *someVariable;
#end
#implementation SomeClass
- (void) foo {
//property getter method
NSString *a1 = self.someVariable; //NSString *a1 = [self someVariable];
//property setter method
self.someVariable = #"set someVariable"; //[self setSomeVariable:#"set someVariable"];
//iVar read
NSString *a2 = _someVariable;
//iVar write
_someVariable = #"set iVar";
}
//if you overriding someVariable getter and setter the iVar(_someVariable) is not generated, that is why you can:
//1. create some variable explicitly
NSString *_someVariable;
//or
//2. use #synthesize
#synthesize someVariable = _someVariable;
//overriding
- (NSString*) someVariable {
return _someVariable;
}
- (void)setSomeVariable: (NSString*) updatedSomeVariable {
_someVariable = updatedSomeVariable;
}
#end
[property attributes]