Single-case mode under ARC and NON-ARC

Source: Internet
Author: User

Original: http://www.cocoachina.com/industry/20130510/6168.html

http://www.justinyan.me/post/1306

single-case mode
There are also many classes in the IOS SDK that use singleton mode, for example, uiapplication: When the program starts, it calls the Uiapplicationmain method, in which a UIApplication object is instantiated, Subsequent calls to the Sharedapplication method anywhere in the program will return a uiapplication instance associated with the current application (UIApplication Singleton created in the Uiapplicationmain method).

When do I use singleton mode?

In a program, a singleton pattern is often used to expect only one instance of a class, without running a class with more than two instances. Of course, in the iOS SDK, depending on the specific requirements, some classes not only provide a single-access interface, but also provide the developer with the instantiation of a new object interface, for example, Nsfilemanager can return the same Nsfilemanager object through the Defaultmanager method. If you need a new Nsfilemanager instance object, you can pass the Init method.

Implementation of the Singleton mode in iOS

There are two ways to implement the singleton pattern in iOS: Non-arc (non-ARC) and ARC+GCD.


1.non-arc (non-ARC)
The implementation of non-arc is as follows:

BVNonARCSingleton.h

@interface Bvnonarcsingleton:nsobject @property  (Nonatomic, retain) NSString  *tempproperty; + (Bvnonarcsingleton *@end

Bvnonarcsingleton.m

@implementationBvnonarcsingletonStaticBvnonarcsingleton *sharedinstance =Nil;//gets an instance of sharedinstance that, if necessary, instantiates a+ (Bvnonarcsingleton *) sharedinstance {if(Sharedinstance = =Nil) {sharedinstance=[[Super Allocwithzone:null] init]; }    returnsharedinstance;}//This init method is called when the Singleton is used for the first time. - (ID) init{ Self=[Super Init]; if(self) {//usually do some related initialization tasks here    }    returnSelf ;}//This dealloc method will never be called-because the Singleton is always present in the program's life-cycle content. (So the method does not have to be implemented)-(void) dealloc{[Super Dealloc];}//by returning the current Sharedinstance instance, you can prevent the instantiation of a new object. + (ID) Allocwithzone: (nszone*) Zone {return[self sharedinstance] retain];}//Similarly, you do not want to generate multiple copies of a single case. - (ID) Copywithzone: (Nszone *) Zone {returnSelf ;}//do nothing-the singleton does not require a reference count (retain counter)- (ID) Retain {returnSelf ;}//Replace the reference count-this will never release this singleton. -(Nsuinteger) retaincount {returnNsuintegermax;}//the method is empty-do not want the user to release the object. -(OneWayvoid) Release {}//Nothing is done except the return single exception. - (ID) Autorelease {returnSelf ;} @end

In fact, the above code Apple official website also provides:Creating a Singleton Instance, but did not give the definition of the document. The method above using non-arc to implement the singleton is thread insecure, if there are multiple threads calling the Sharedinstance method simultaneously to get an instance, and the Sharedinstance method takes 1-2 seconds, Then the Bvnonarcsingleton init method may be called multiple times, that is, the Bvnonarcsingleton obtained by different threads may not be the same instance. How to solve thread insecurity? The answer is to use @synchronized to create the mutex.

// guaranteed to be thread-safe at instantiation (of course, this method does not guarantee that all methods in the singleton are thread-safe) @synchronized (self) {   if(sharedinstance = = Nil    )       {= [[Super Allocwithzone:null] init];}    }

Thread safety can be saved through the code above.
Reminder: In iOS, it is not recommended to use non-arc for singleton mode. A better approach is to use ARC+GCD to implement.

2.arc+gcd
It is very simple to implement the singleton mode by ARC+GCD method. Let's take a look at the specific implementation:

BVARCSingleton.h

@interface Bvarcsingleton:nsobject@property  (Nonatomic, weak) NSString  *tempproperty; + (Bvarcsingleton *) sharedinstance; @end

Bvarcsingleton.m

@implementationBvarcsingleton+ (Bvarcsingleton *) sharedinstance{StaticBvarcsingleton *sharedinstance =Nil; Staticdispatch_once_t Oncetoken;//LockDispatch_once (& Oncetoken, ^ {//call at most onceSharedinstance =[[Self alloc] init];    }); returnsharedinstance;}//This init method is called when the Singleton is used for the first time. - (ID) init{ Self=[Super Init]; if(self) {//usually do some related initialization tasks here    }     returnSelf ;}@end

In the preceding code, calling the Dispatch_once method in the Grand Central Dispatch (GCD) ensures that the Bvarcsingleton is instantiated only once. And the method is thread-safe, and we don't have to worry about getting different instances in different threads. (Of course, the method also does not guarantee that all methods in the singleton are thread-safe.)

Of course, in arc, it is also possible to thread-safe without gcd, as in the previous non-arc code using @synchronized, the following code:

// do not use GCD, through @synchronized @synchronized (self) {   if(sharedinstance = = Nil    )        {= [[Self alloc] INIT];}    }



To simplify the use of ARC+GCD to create a singleton, you can define a macro such as the following:

#define Static 0  staticid sharedinstance = nil; dispatch_once (&oncetoken, ^=   return


The implementation of the instantiation is as follows:

+ (Bvarcsingleton *) sharedinstance{    define_shared_instance_using_block (^{        return  [[Self alloc] init];}    );


Use of a single case

The use of a single example is simple, anywhere in the code, as follows:

To add a header file in BVAPPDELEGATE.M:
#import "BVNonARCSingleton.h"
#import "BVARCSingleton.h"


Use this method as follows:

-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (Nsdictionary *) launchoptions{[Bvnonarcsingleton sharedinstance].tempproperty=@"implementation of non-arc single case"; NSLog (@"%@", [Bvnonarcsingleton sharedinstance].tempproperty); [Bvarcsingleton Sharedinstance].tempproperty=@"the implementation of Arc single example"; NSLog (@"%@", [Bvarcsingleton sharedinstance].tempproperty); returnYES;}

Running the program will output the following in the console window:
1.2013-05-09 16:44:07.649 singletonpattern[5159:c07] Non-ARC single-instance implementation
2.2013-05-09 16:44:33.204 SINGLETONPATTERN[5159:C07] Arc single-case implementation

Alloc and Allocwithzone

First, the origin of the problem

All originated in Apple's official documentation for the sample code for Singleton (Singleton): Creating a Singleton Instance.

The main controversy is focused on the following paragraph:

1234567891011121314 static MyGizmoClass *sharedGizmoManager = nil;+ (MyGizmoClass*)sharedManager{    if (sharedGizmoManager == nil) {        sharedGizmoManager = [[super allocWithZone:NULL] init];    }    return sharedGizmoManager;}+ (id)allocWithZone:(NSZone *)zone{    return [[self sharedManager] retain];}

which

1 sharedGizmoManager = [[superallocWithZone:NULL] init];

There is another version of this paragraph that does not use allocwithzone but directly alloc, as follows:

1 sharedGizmoManager = [[superalloc] init];

This leads to a discussion, why to cover the Allocwithzone method, exactly what is the difference between alloc and allocwithzone?

PS: About the implementation of OBJC single case, @Venj this blog post has a more detailed discussion, including thread safety considerations, interested children shoes can be onlookers.

Second, Allocwithzone

First we know that we need to make sure that there is only one instance of the Singleton class, and when we initialize an object, [[Class alloc] init] actually does two things. Alloc allocates memory space to an object, Init is the initialization of the object, including setting the initial value of the member variable. In addition to the Alloc method, there is another way to allocate space to the object: Allocwithzone.

In the official document of the NSObject class, the Allocwithzone method describes that the parameters of the method are ignored, and the correct procedure is to pass nil or null parameters to it. The reason why this method exists is a legacy of history.

Do not override allocwithzone:to include any initialization code. Instead, class-specific versions of Init ... methods.

This method is exists for historical reasons; Memory zones is no longer used by objective-c.

It is mentioned in the document that the memory zone has been deprecated, only for historical reasons to retain this interface. I didn't find out what the historical reason was, but the content of the introduction would be a little more involved.

The practice proves that when initializing an instance of a class using the Alloc method, the default is to call the Allocwithzone method. The reason for overwriting the Allocwithzone method is obvious: to keep the singleton instance unique, you need to overwrite all methods that generate a new instance, and if someone initializes the singleton class without walking [[Class alloc] init], it is directly Allocwithzone, then this single case is no longer a singleton, so it is necessary to plug the method. Allocwithzone's answer to this is solved, but the problem is endless.

Here's another question: What's the hell is Memory Zone?

Third, Nszone

Apple's Official document contains a few simple words, stingy:

12345678910111213 NSZoneUsed to identify and manage memory zones. typedef struct _NSZone NSZone; Availability Available in OS X v10.0 and later. Declared InNSZone.h

Cocadev Wiki is written in more detail, the original address here: Http://cocoadev.com/wiki/NSZone

The main idea is that Nszone is a way that Apple allocates and frees memory, not an object, but rather uses a C structure to store information about the memory management of the object. Basically, developers don't have to bother with this stuff, cocoa. Application uses a system default Nszone to manage the application's objects. So when do you want to have a nszone of your own control? When a large number of objects are managed in the default Nszone. At such times, the release of a large number of objects can lead to serious memory fragmentation, cocoa itself has been optimized, each time the alloc will try to fill the memory gap, but it is expensive to do so. Thus, you can create a nszone yourself, so that when you have a large number of Alloc requests, it is all transferred to the specified Nszone, reducing the amount of time overhead. In addition, using Nszone can also be in one breath to remove the contents of the zone you created, eliminating a lot of time to dealloc objects.

In general, when you need to create a large number of objects, you can save some time by using Nszone, but only if you know how to use it. The wiki also contains nszone usage, and interested children's shoes can be seen, but another 2002-year article says that developers can't create a real nszone (which might be a historical reason), and can only create a child zone in the main zone. Article here: http://www.cocoabuilder.com/archive/cocoa/65056-what-an-nszone.html#65056 Timothy J.wood's answer.

Timothy also said that if you can use Nszone, multiple objects at the same time alloc can reduce paging use, and at the same time Dealloc can reduce memory fragmentation. Presumably later Apple has done this, transparent to developers, without the need for developers to do it themselves.

Iv. Conclusion

Allocwithzone is not encouraged by Apple, and most of the time programmers do not need to manage their own zone. Of course it's always nice to know more about something.

Single-case mode under ARC and NON-ARC

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.