【iOS】ARC-MRC下的單例及其應用,iosmrcarc
單例的應用十分普遍,單例模式使一個類只有一個執行個體。
*易於供外界訪問.*方便控制執行個體個數,節約系統資源.
*OC中的常見單例:如:UIApplication, NSNotificationCenter, NSUserDefaults, NSFIleManager。
*應用程式中用到的單例:如:背景音樂,音效管理等。
一、ARC中實現單例
建立單例的步驟:*1.定義一個全域的靜態變數_instance,用來記錄“第一次”被執行個體化出來的對象.*2.重寫allocWithZone方法,此方法是為對象分配記憶體空間必須會被調用的一個方法!因此,在此方法中使用“dispatch_once”,能夠保證在多線程中,_instance也只能被“分配”一次空間.*3.定義一個sharedXXX“類”方法,方便其他使用單例的對象調用此單例.在此方法中,同樣使用“dispatch_once”,保證使用類方法調用的對象,只會被初始化一次!注釋:如果不考慮copy& MRC,以上三個步驟即可!*4.如果要支援copy,則需要:(1)遵守NSCopying協議(2)在copyWithZone方法中,直接返回_instance
tips:
*一般的寫法(懶漢式, 餓漢式, 加鎖):if(!_instance)_instance=[[XNShareToolalloc]init];return_instance;*懶漢式是
線程不安全的.因此實際中不這麼寫. 還有餓漢式,加鎖等.
*但是OC中有其自己的寫法.需要結合其對象生命週期的一些方法來寫單例.
*為什麼要使用dispatch_one? :防止多線程同時進來,就相當與Java單例中的加鎖機制,保證只被執行個體化一次.但這裡使用的不是synchronized, 是類似互斥鎖的東西, 但比他的效能高.
ARC中實現單例的代碼如下:
@implementation XNShareTool/** 步驟: 1.一個靜態變數_inastance 2.重寫allocWithZone, 在裡面用dispatch_once, 並調用super allocWithZone 3.自訂一個sharedXX, 用來擷取單例. 在裡面也調用dispatch_once, 執行個體化_instance -----------可選------------ 4.如果要支援copy. 則(先遵守NSCopying協議)重寫copyWithZone, 直接返回_instance即可. *//**第1步: 儲存唯一執行個體*/static XNShareTool *_instance;/**第2步: 分配記憶體孔家時都會調用這個方法. 保證分配記憶體alloc時都相同*/+(id)allocWithZone:(struct _NSZone *)zone{ //調用dispatch_once保證在多線程中也只被執行個體化一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance;}/**第3步: 保證init初始化時都相同*/+(instancetype)sharedTool{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[XNShareTool alloc] init]; }); return _instance;}/**第4步: 保證copy時都相同*/-(id)copyWithZone:(NSZone *)zone{ return _instance;}@end
測試代碼如下(列印單例對象的
地址都相同):
-(void)viewDidLoad{ //執行個體化一個類的幾種方法. 單例就是要保證執行個體化出來的類是同一個類 //1.alloc init方法. 一般不這麼來調用單例. XNShareTool *t1 = [[XNShareTool alloc] init]; XNShareTool *t2 = [[XNShareTool alloc] init]; //2.類方法 XNShareTool *t3 = [XNShareTool sharedTool]; //3.copy XNShareTool *t4 = [t3 copy]; NSLog(@"%@ %@ %@ %@", t1, t2, t3, t4);}
二、MRC中運用單例
因為單例對象是用static標記過的, 因此存放在靜態區. 所以在MRC中不需要由程式員去管理,因此要去覆蓋一些記憶體管理的方法.
實現部分與ARC一致,只需要覆蓋一些MRC中記憶體管理的方法:*- (id)retain. 單例中不需要增加引用計數器.returnself.*- (id)autorelease. 只有堆中的對象才需要.單例中不需要.returnself.*- (NSUInteger)retainCount.(可寫可不寫,防止引起誤解).單例中不需要修改引用計數,返回最大的不帶正負號的整數即可.return UINT_MAX;*- (oneway void)release.不需要release.直接覆蓋,生命也不做.
#import "XNShareTool.h"@implementation XNShareToolstatic XNShareTool *_instance;+ (id)allocWithZone:(struct _NSZone *)zone {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone];});return _instance;}+ (instancetype)sharedTool {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{ _instance = [[XNShareTool alloc] init];});return _instance;}- (id)copyWithZone:(NSZone *)zone {return _instance;}#pragma mark - MRC中需要覆蓋的方法//不需要計數器+1- (id)retain {return self;}//不需要. 堆區的對象才需要- (id)autorelease {return self;}//不需要- (oneway void)release {}//不需要計數器個數. 直接返回最大不帶正負號的整數- (NSUInteger)retainCount {return UINT_MAX; //參照常量區字串的retainCount}@end
三、ARC與MRC的整合
整合是為了方便單例既能在ARC中使用,又能在MRC中使用。而不必去修改單例中的方法。
具體做法是使用宏定義:(判斷是否是ARC環境,是的話就省略記憶體管理的方法)
#if !__has_feature(objc_arc)
MRC中記憶體管理的方法放在這個地方
#endif
代碼如下:
//=============================ARC/MRC整合=======================================#pragma mark - MRC中需要覆蓋的方法, ARC與MRC的整合#if !__has_feature(objc_arc)- (id)retain {return self;}- (id)autorelease {return self;}- (oneway void)release {}- (NSUInteger)retainCount {return UINT_MAX;}#endif//============================================================================
轉載請註明出處:http://blog.csdn.net/xn4545945
IOS 單例模式怎麼用??所有程式設計語言單例模式都大同小異Object-c, Java, C++等跟語言沒有太大關係只跟文法有點關係而己
IOS 假有類:AccountManager要定義單例則步法下:
. .h檔案應該有類似下定義:
+ (id) sharedInstance;
二. .m檔案內類應該有下定義:
//聲明全域唯靜態對象也AccountManager類型
static AccountManager * _sharedInstance;
//方法實現
+ (id) sharedInstance {
@synchronized ([AccountManagerclass]) {
if (_sharedInstance == nil) {
_sharedInstance = [[AccountManageralloc] init];
}
}
return_sharedInstance;
}
三. 別類對象要使用該單例並調用該單例某方法(todoSomething):
[[AccountManager sharedInstance] todoSomething ];
附加說明:
1 sharedInstance名字我習慣用用別名字任意總之保持AccountManager類整應用程式運行期間只能有執行個體
2 裡例子給實現懶漢式 單例 還有另外單例方式也完成任務餓漢式單例 清楚懶漢和餓漢再Google上查
開發中如何使用單例 ios解答
第、基本概念
單例模式種常用軟體設計模式核心結構只包含被稱單例類特殊類通過單例模式保證系統類別只有執行個體而且該執行個體易於外界訪問
第二、IOS使用單例模式情況
1.說建立對象會耗費多系統資源此時採用單例模式因只需要執行個體會節省alloc時間
2.IOS開發多模組都要使用同變數此時把該變數放入單例類則所有訪問該變數調用變得容易否則只能通過模組傳遞給另外模組樣增加了風險和複雜度
第三、建立單例模式基本步驟
1.聲明單例對象靜態執行個體並初始化nil
2.聲明類Factory 方法產生該類執行個體並且只會產生
3.覆蓋allcoWithZone方法確保使用者alloc 時會產生多餘對象
4.實現NSCopying協議覆蓋release,autorelease,retain,retainCount方法確保只有執行個體化對象
5.多線程環境注意使用@synchronized關鍵字
[cpp] view plaincopyprint?
//
// UserContext.h
// SingleDemo
//
// Created by andyyang on 9/30/13.
// Copyright (c) 2013 andyyang. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface UserContext : NSObject
@property (nonatomic,retain) NSString *username;
@property(nonatomic,retain)NSString *email;
+(id)sharedUserDefault;
@end
[cpp] view plaincopyprint?
//
// UserContext.m
// SingleDemo
//
// Created by andyyang on 9/30/13.
// Copyright (c) 2013 andyyang. All rights reserved.
//
#import "UserContext.h"
static UserContext *singleInstance=nil;
@implementation UserContext
+(id)sharedUserDefault
{
if(singleInstance==nil)
{
@synchronized(self)
{
if(singleInstance==nil)
{
singleInstance=[[[self class] alloc] init];
}
}
}
return singleInstance;
}
+ (id)allocWithZone:(NSZone *)zone;
{
NSLog(@"HELLO");
if(singleInstance==nil)
{
singleInstance=[super allocWithZone:zone];
}
return singleInstance;
}
-(id)copyWithZone:(NSZone *)zone
{
NSLog(@"hello");
return singleInstance;
}
-(id)retain
{
return singleInstance;
}
- (oneway void)release
{
}
- (id)autorelease
{
return singleInstance;
}
- (NSUInteger)retainCount
{
return UINT_MAX;
}@end
[cpp] view plaincopyprint?
#import <Foundation/Foundation.h>
#import "UserContext.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
UserContext *userContext1=[UserContext sharedUserDefault];
UserContext *userContext2=[UserContext sharedUserDefault];
UserContext *userContext3=[[UserContext alloc] init];
UserContext *userContext4=[userContext1 copy];
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
開發我們利用ios提供方法來實現單例模式:
SYNTHESIZE_SINGLETON_FOR_CLASS(MyClassName);
該語句置於@implementation MyClassName聲明樣類自動會變成單例
內容來自於richard_風部落格