Article 3: communication between objects through delegated and Data Source protocols
Objects often need to communicate with each other, but there are many communication methods. OC developers widely use a programming design pattern called "delegate pattern" to implement communication between objects. The purpose of this pattern is to define a set of interfaces, if an object wants to receive another object's delegate, it must follow this interface to be called a "delegate object" (delegate ). This "another object" can return some information to the delegate object, or notify the delegate object when the associated time occurs.
This mode decouples data from the business logic.
In objective-C, this mode is generally implemented through the "protocol" language feature. The entire Coco system framework does this. If your purchase agent is also written in this way, it can be well integrated with the system framework.
Example:
The process of calling back the delegate object. Please note that the "delegate object" may not have to be held by the eocdatamodel instance or be assumed by another object.
With the Protocol mechanism, it is easy to implement this mode with objective-C Code. The Code is as follows:
@ Protocol eocnetworkfetcherdelegate-(void) networkfetcher :( eocnetworkfetcher *) fetcher didreceivedata :( nsdata *) data; // This eocnetworkfetcher * parameter can delegate objects at high speed, who calls it-(void) networkfetcher :( eocnetworkfetcher *) fetcher didfailwithdata :( nserror *) error; @ end
With this protocol, the class can use an attribute to store the delegate object. In this example, this class is the eocnetworkfetcher class:
@interface EOCNetworkFetcher :NSObject@property (nonatomic,weak) id<EOCNetworkFetcherDelegate> delegate;@end
Be sure to define this attribute as weak instead of strong. Because the two must be non-having relationships ". As shown in:
Networkfetcher does not retain the delegate attribute to avoid loop reference.
Let's take a look at the implementation of eocdatamodel:
@interface EOCDataModel()<EOCNetworkFetcherDelegate>@end@implement EOCDataModel-(void)netWorkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data{if(fetcher == _myFetherA){/* handle data*/}else if(fetcher == _myFetherB){/* handle data*/}}-(void)netWorkFetcher:(EOCNetworkFetcher*)fetcher didFailWithData:(NSError*)error{/*handle error*/}@end
This eocnetworkfetcher * parameter can be used to delegate objects at high speed. Who calls this parameter.
The following are the eocnetworkfetcher calls.
NSData *data = /*data obtained from network*/if([_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]){[_delegate networkFetcher:self didReceiveData:data];}
Through this example, you can easily understand why this mode is called the "delegation mode": because the object delegates the responsibility for a certain behavior to another class.
Respondstoselector: @ selector (XXXX) is redundant for each running time. It is useful only for the first time.Reference Optimization Methods
[Highlights of this section]
● The delegation mode provides an interface for objects so that they can notify other objects of related events.
● Define the interfaces that the delegate object should support as protocols, and define the operations that may need to be processed as methods in the Protocol.
● When an object needs to obtain data from another object, the delegate mode can be used. In this situation, this mode is also called the data source protocol)
● If necessary, you can implement struct with bit segments and cache the information about whether the delegate object can use the relevant protocol methods.
Article 12: scatter the implementation code of classes into several categories that are easy to manage
Classes often fill up various methods, and the code of these methods is all heap in a huge implementation file. In this case, you can use the objective-c "classification" mechanism to partition the class code into Several partitions according to the logic.
In cocoa, the nsurlrequest class and the variable version nsmutableurlrequest class do this.
In addition, when writing a library to be shared with other developers, you can consider creating a "private" category. If you want to use these methods somewhere in the program, introduce the header file of this category. The classification header file will not be published along with the library, so the user of the Library does not know that there are these private methods in the library.
Article 12: Always prefix the category name of a third-party class
The classification mechanism is usually used to add new features to existing classes without source code. This feature is extremely powerful, but it is easy to ignore problems. The methods in classification are directly added to the class. If the methods in classification have the same names as the methods in the class, the inherent methods will be overwritten.
You may write a category like this.
@interface NSString (HTTP)//Encode a string with URL encoding-(NSString*)urlEncodeString;//Decode a URL encoded string-(NSString*)urlDecodedString;@end
If the nsstring class itself has the urlencodestring method, or another category is also called urlencodestring, your class will be overwritten if the classification loading time written by others is later than yours. To solve this problem, use a namespace to differentiate the names of each category
@interface NSString (ABC_HTTP)//Encode a string with URL encoding-(NSString*)abc_urlEncodeString;//Decode a URL encoded string-(NSString*)abc_urlDecodedString;@end
Article 3: Do not use lifecycle attributes in a category
Attribute is the way to encapsulate data. Although technically speaking, classification can have a life attribute, this approach should be avoided as much as possible.
Article 27th: Use "Class-continuation" to hide implementation details (to be supplemented) Article 28th: The Protocol provides anonymous object protocol to define a series of methods, and the objects complying with this Protocol should implement them. Therefore, we can use the Protocol to hide the implementation details in the API we write and hide the returned object involving bits of the pure Id type following this protocol. In this way, the class name to be hidden will not appear in the API. This concept is often called "anonymous object", which is different from "anonymous object" in other languages. @ Property (nonatomic, weak) ID <eocdelegate> delegate; because the property type is ID <eocdelegate>, in fact, any type of object can act as this property, even if the class does not inherit from nsobject, you only need to follow the eocdelegae protocol. Nsdictionary can also describe this concept. In the dictionary, the standard memory management Syntax of keys is "copy when setting", while the semantics of values is "retain when setting ". Therefore, in the dictionary of a variable version, the signature of the method used to set the key-value pair is:
-(void) setObject:(id)object forKey:(id<NSCopying>)key;
ID of the parameter type of the key <nscopying>. It can be of any type as long as it complies with the nscopying protocol, you can send a copy message to this object. This key parameter can be considered as an anonymous object. Similar to the data case of Delegate, database connection programs also use this idea to use anonymous objects to represent objects returned from another database. You may not want to know which class to process the connection. If there is no way for it to inherit the same word as a base class, then you have to follow this Agreement:
@protocol EOCDatabaseConnection-(void) connect;-(void)disconnect;-(void)isConnected;-(NSArray*)performQuery:(NSString*)query;@end;
Then, you can use the "database processor" Singleton to provide database connections. This Singleton interface can be written:
@protocol EOCDatabaseConnection@interface EOCDatabaseManger:NSObject+(id)sharedInstance;-(id<EOCDatabaseConnection>) connectionWithIdentifier:(NSString*)identifier;@end;
In this way, the class name UI used to process the database connection will not be disclosed. Sometimes the object type is not important. The important thing is whether the object has implemented some methods. In this case, you can also use the "anonymous type" to express this concept. This is also used in the coredata framework. The result obtained by querying the coredata database is processed by the nsfetchedresultscontrller class. If necessary, the data is partitioned. In the Controller responsible for processing query results, there is a section attribute used to represent data partitions. This attribute is an array, but the object does not specify the specific type. It means that these objects comply with the nsfetchedresultssectioninfo protocol. The following code uses the Controller to obtain data partition information:
NSFetchedResultsController * controller = /*some controller*/;NSUInteger section = /*section index to query*/NSArray *sections = controller.sections;id<NSFetchedResultsSectionInfo> sectionInfo = sections[section];NSUInteger numberOfObjects = sectionInfo.numberOfObjects;
Sectioninfo is an anonymous object. [Key points of this section] ● The Protocol provides an anonymous type to some extent. The specific object type can be reduced to the ID type following a protocol, which specifies the method to be implemented by the object. ● Use an anonymous object to hide the type name (or Class Name) ● if the room type is not important, it is important that the object can respond to a specific method, which can be represented by an anonymous object.