Objective-C, property interface declarations

In the following general pattern

//// @interface MyObject : NSObject { @public NSString * myString_; } @property (assign) NSString * myString; @end @implementation MyObject @synthesize myString = myString_; @end //// 

why even declare myString_ in the interface?

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 should, if you save it instead.

+4
source share
4 answers

In modern Obj-C runtime, the ivar declaration is more a formality than anything else. However, there are some memory management things to keep in mind.

First, declaring a property for an object type is usually retain , or for strings it can be copy . In any case, the new object is saved.

Given the following code:

 NSString *string = [[NSString alloc] init]; myString_ = string; self.myString = string; // If the property was retain or copy 

The second destination will be a leak; the first will not. This is because the property will save what already has a save account of 1, now it is 2. When you release the property in dealloc , the counter will be 1, not 0, so it will not be released. However, with the first option, the save counter remains at 1, so dealloc reduces it to 0.

In your example, leaving the property as assign will make the ivar declaration formal.

+1
source

This is a matter of preference / convention for some. Default:

 @property (assign) NSString * myString; 

... then follow:

 @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 called myString , which can be accessed directly inside your class (that is, without going through getter and setter) and is used to set and get the value of the property and which is used internally to return the property.

If you like, you can do @synthesize myString = someOtherVarName , and then you still get the setters and getters as before, but instead of the myString instance variable, the someOtherVarName instance someOtherVarName used to return the property, and no myString variable is created.

So why use a more detailed syntax? There is never a case when you do this, but some people prefer to do this when dealing with properties declared with retain or copy . The reason for this is that setting the declared retain or copy property through its generated installation method affects the account of saving the object that is set / not set. The same thing happens when directly accessing an instance variable.

Thus, by smoothing the instance variable to something else, you can make the difference in the code line by line “everything that xxx.myString = Y does, changing the save counter, while everything that someOtherVarName = Y does not” . Again, this does not need to be done, but some people prefer to do it.

+5
source

You can skip it. Modern compilers allow this.

When you define a property, you are actually declaring how the getter and setter methods are created for a particular instance variable. Previously, he needed to specify an instance variable for you to declare it. It also allowed the property name to differ from the instance variable name with @synthesize myProperty = myIVar; . Now you don’t have to do this, as modern compilers generate an instance variable for you.

The dot syntax is actually convenient, as you would have noticed. It does not directly refer to the instance variable, but the myProperty and setMyProperty: methods. You can even call myArray.count , where count not a property (I would not recommend it, even if many people like it).

Despite the difference between the two, the gap seems to close slowly.

+2
source

This is just a problem in terms. If you access ivar directly, you get access to it internally. If you use a property, you do not get access to ivar (semantically). You are using the object access method. Thus, you treat self as a similar external object, the internal is unknown.

This is the problem of encapsulating an object-oriented paradigm.

And I recommend some tricks when using properties.

  • An ivar declaration is optional, not required. The compiler will automatically generate it.
  • You must set ivar as @protected or @protected in order to encapsulate it correctly. (at least there are no reasonable reasons).
  • I recommend using nonatomic if you do not need thread locking when accessing the property. Blocking threads will significantly reduce performance and may cause strange behavior while executing code.

You can use this code to do the same.

 @interface MyObject : NSObject @property (assign,nonatomic) NSString * myString; @end @implementation MyObject @synthesize myString; @end 

And it will be 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 

Actually, I'm not sure if synchronization is synchronized with the assign behavior directive, but it is always better to configure it nonatomic explicitly. The compiler can optimize it with an atomic instruction rather than blocking.

Here is the properties reference document: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html%23//apple_ref/doc/uid/TP30001163-CH17

+2
source

All Articles