Private properties and methods in Objective-C

When looking at one of Apple's examples in TableViewController.m they have the following:

// Private TableViewController properties and methods. @interface TableViewController () @property (nonatomic, retain) NSMutableArray* sectionInfoArray; @property (nonatomic, retain) NSIndexPath* pinchedIndexPath; @property (nonatomic, assign) NSInteger openSectionIndex; @property (nonatomic, assign) CGFloat initialPinchHeight; ... more properties and methods @end @implementation TableViewController ... usual stuff 

I am wondering why they put these properties in a .m file and how private it is. It seems that anyone who imports the TableViewController.m file can use these properties and methods correctly? Why not use @private in your .h file?

+6
source share
7 answers

What they do is declare a category in the class, but since it is done in the .m file, the effect is that these methods are "invisible."

This does not mean, however, that these methods cannot be called externally. This is due to the fact that there is no real confidentiality in object c, since we are dealing with messages, and not with method calls. This means that you can send a message about the object, even if you do not know whether this object really implements the method that you are trying to call. The receiving object will determine at run time if it can handle this call, it may even redirect it, and there will be no difference whether the method was known to the calling object or not.

This is one of the reasons why you can call private APIs and decline for it.

+4
source

AFAIK

a) You cannot mark properties as @private in .h - this only works for ivars.

b) You cannot refer to your class if you simply import the .m file (without defining the interface in the .h file). and if you do, you'll get duplicate characters during layout.

c) So yes, these properties are private in the sense that they are not available as normal properties from the outside - these properties are only available using explicit messages - however, in this case you will receive warnings from the compiler or you can use KVC

+2
source

They are not closed. These are anonymous properties because they are part of an anonymous category.

One of the things that are well suited for creating memory management semantics for an object belonging to it in one place. Consider this:

 @property (nonatomic, assigned) NSString *assigned; @property (nonatomic, copy) NSString *copied; @property (nonatomic, retain) NSString *retained; 

In all three cases, you can assign them this way without knowing what their semantics of memory are:

 self.assigned = stringParameter; // assigns to instance variable self.copied = stringParameter; // copies, assigns copy to instance variable self.retained = stringParameter; // retains, assigns to instance variable 

And in all three cases, you can clean up for free using the same code:

 self.assigned = nil; // this just nils the instance variable self.copied = nil; // releases copy in ivar, nils instance variable self.retained = nil; // releases ivar (same as original object), // nils instance variable 

That's why you often see local properties: it allows the encoder to skip writing all memory management logic every time they want to assign an instance variable. This main advantage is that you can change the memory management logic in the whole class by simply changing @property .

Another use of anonymous properties is to extend a property declared as readonly to external code as read / write for the class itself.

In .h:

 @property (nonatomic, readonly, retain) NSError *lastError; 

In .m, in the anonymous category:

 @property (nonatomic, readwrite, retain) NSError *lastError; 

Elsewhere .m code:

 self.lastError = error; 

Again, this is mainly due to memory management considerations.

An example related to using anonymous properties.

Here, every assignment to the _lastError instance variable looks without properties.

Suppose we have an NSError called _lastError defined in the .h file.

Saved:

 [_lastError release]; _lastError = [error retain]; 

With copy:

 [_lastError release]; _lastError = [error copy]; 

With purpose:

 _lastError = error; 

In the first two cases, you will need this in your dealloc:

 [_lastError release]; 

But in the latter case, you must put nothing in dealloc or you will get a failure.

So add what you need to use the property:

Add this to the anonymous category:

 @property (nonatomic, readwrite, retain) NSError *lastError; 

Add this to @implementation:

 @synthesize lastError = _lastError; 

Please also note that at this point on the “modern” Cocoa run-time (64-bit Mac or iOS) you can remove NSError * _lastError from your header. The compiler can understand what you want based on @synthesize.

Here's how it changes our code:

Each appointment:

 self.lastError = error; // works regardless of storage specifier 

In daelloc:

 self.lastError = nil; // works regardless of storage specifier 
+2
source

Firstly, as a rule, you cannot import a .m file - not without numerous compiler / linker errors. Secondly, the properties are private, so Apple is free to change them in subsequent releases.

Yes, you can reach them through reflection. But what a slippery slope, blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah ,

+1
source

Object c does not have private methods or variables, the @private flag basically only exists when other developers look at it, they know that it must be closed. That your vision in apple code is an example of a category, a way to fake private methods and variables in the lens c. Because external classes will only import the .h file, they will never see the added methods and variables in the .m file.

+1
source

Using internal properties and methods of an anonymous category that other classes should not know. Although the compiler does not know about them when this class refers to other classes, you can technically access any of these properties from this other class using key value encoding.

0
source

you cannot import the implementation file of TableViewController.m , you can import only the .h file of TableViewController ,

Although you can have a reference to this property outside the TableViewController class with a warning that shows a “do not respond” note.

0
source

Source: https://habr.com/ru/post/893289/


All Articles