Singleton trong lập trình IOS

I. Thông tin chung:
– Singleton là một design pattern quen thuộc với tất cả mọi người
– Nó cho phép chỉ một instant của class được tạo ra và bạn có khả năng truy cập vào class này bất cứ đâu.
– Đây là một công cụ cực mạnh để chia sẽ dữ liệu giữa những class khác nhau trong cùng một chương trình mà không cần phải đưa dữ liệu qua từng class khác nhau chỉ để đi đến một class nữa..
– Nó còn giúp cho chương trình dễ dàng để bảo trì và thay đổi những thông tin cần thiết. Ví dụ như trong chương trình có giám đốc công ty, giám đốc có thể thay đổi nhưng rất lâu và tỉ lệ rất thấp. Vì vậy nên việc lưu vào trong chương trình là việc nên làm nhưng phải gom lại một chỗ để có thể làm việc dễ dàng hơn. Đây chính là mục đích của design pattern

* Đây là một pattern cực kì hữu ích cho mọi lập trình viên. Dĩ nhiên, pattern này cũng xuất hiện trong iPhone SDK.
* UIApplication có một method gọi là sharedApplication. Nó có thể được gọi ở bất cứ nơi đâu mà vẫn trả về đúng một UIApplication instant trong cùng ứng dụng đang chạy.

II. Nội dung chính:

File LKManager.h:

#import <foundation/Foundation.h>

@interface LKManager : NSObject {
NSString *someProperty;
}

@property (nonatomic, retain) NSString *author;

@property (nonatomic, retain) NSString *authorCompany;

+ (id)sharedManager;

@end

File LKManager.m:

#import “LKManager.h”

@implementation LKManager

#pragma mark Singleton Methods

+ (id)sharedManager {
static LKManager *sharedLKManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedLKManager = [[self alloc] init];
});
return sharedLKManager;
}

– (id)init {
if (self = [super init]) {
author = [[NSString alloc] initWithString:@”Huygamer”];

     authorCompany = [[NSString alloc] initWithString:@”LapKan Company”];
}
return self;
}

– (void)dealloc {
}

@end

Điều này biến nó thành một biến tĩnh (nhưng chỉ với trường hợp này) đã tạo ra một sharedLKManager chỉ được khởi tạo một lần duy nhất trong sharedManager. Cách chúng ta sử dụng để chắc chắn được điều này là dùng dispatch_once method trong Grand Central Dispatch (GCD). Nó là một quá trình an toàn và được xử lý toàn bộ trên tổng thể chương trình được vận hành bởi hệ điều hành để bạn không cần phải lo lắng về việc đó.  Nếu bạn có nhiều hứng thú về GCD và muốn tìm hiểu thêm về GCD thì link này có thể giúp bạn có những hiểu biết về việc quản lý bộ nhớ:

http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1

Trong một số trường hợp nếu bạn không muốn sử dụng GCD thì bạn có thể thay thế bằng đoạn code sau:

+ (id)sharedManager {
@synchronized(self) {
if (sharedLKManager == nil)
sharedLKManager = [[self alloc] init];
}
return sharedLKManager;
}

=> Nó sẽ đồng bộ hóa và xem xét nếu instance của class đã được tạo ra rồi thì sẽ trả về đúng đối tượng đã tạo nếu không thì nó mới tạo mới.

* Những đoạn code viết ở trên là đã sử dụng đến ARC, nếu bạn vẫn còn cổ lỗ xỉ hay chính xác hơn là những ông già lạc hậu trong làng công nghệ (già mà không biết cũng hơi bị lạ nhỉ) thì bạn có thể sử dụng đoạn code sau cho chương trình không sử dụng ARC (non-ARC):

#import “LKManager.h”

static LKManager *sharedLKManager = nil;

@implementation LKManager

@synthesize someProperty;

#pragma mark Singleton Methods
+ (id)sharedManager {
@synchronized(self) {
if(sharedLKManager == nil)
sharedLKManager = [[super allocWithZone:NULL] init];
}
return sharedLKManager;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
– (id)copyWithZone:(NSZone *)zone {
return self;
}
– (id)retain {
return self;
}
– (unsigned)retainCount {
return UINT_MAX; //denotes an object that cannot be released
}
– (oneway void)release {
// never release
}
– (id)autorelease {
return self;
}
– (id)init {
if (self = [super init]) {
someProperty = [[NSString alloc] initWithString:@”Default Property Value”];
}
return self;
}
– (void)dealloc {
// Should never be called, but just here for clarity really.
[someProperty release];
[super dealloc];
}

@end

Bạn có thể sử dụng class Singleton vừa tạo bằng cách gọi nó ra như sau:

MyManager *sharedManager = [MyManager sharedManager];

Tôi thường sử dụng nó trong việc lưu trữ các biến toàn cục để không cần phải set lại trong cả chương trình. Ngoài ra, CoreLocation cũng là một trong số những bạn bè quen thuộc của Singleton, bạn chỉ lấy vị trí của người dùng 1 lần duy nhất và sử dụng trên cả chương trình tránh trường hợp mất mạng và giảm lưu lượng sử dụng rất nhiều. Đối với Core Data cũng vậy, bạn chỉ viết câu lệnh kết nối 1 lần duy nhất và sử dụng cho toàn bộ chương trình.

III. Kết luận:
– Singleton pattern là một pattern cực kì quen thuộc xuất hiện trên hầu hết các chương trình. Tôi cũng rất thường sử dụng Singleton trong các chương trình của tôi để lưu các dữ liệu sử dụng thường xuyên. Ngoài ra, nó cũng có tính tái sử dụng lại rất cao, có thể dùng để lưu những setting căn bản và khi cần chỉ paste lại không cần phải code lại mệt mỏi.

Tagged: , , , , , , , , , , , , , , , , , , , ,

3 thoughts on “Singleton trong lập trình IOS

  1. cuongproit February 1, 2013 at 1:51 am Reply

    mình mới chỉ biết là singleton là để bảo đảm lúc nào trong chương trình của mình, chỉ duy nhất 1 instance của class được tạo ra, nhưng mình thấy bạn nhấn mạnh về tính chia sẻ dữ liệu của nó.
    Trên đoạn code của bạn cũng ko thấy miêu tả về vấn đề này, bạn có thể nói rõ hơn về tính chia sẻ mạnh mẽ của nó thế nào, và có đoạn demo ko ^^.

  2. huygamer February 1, 2013 at 2:02 am Reply

    Do cái này mình đang sử dụng trong game của mình luôn nên chưa viết tiếp. Thấy nó thật sự rất hay.
    Nếu bạn thật sự có đam mê và muốn học hỏi thì mình sẽ viết tiếp và tách phần singleton từ trong game của mình ra để bạn hiều ứng dụng trong thực tế của SIngleton.

  3. cuongproit February 1, 2013 at 2:10 am Reply

    Tất nhiên là mình thực sự quan tâm chứ ^^.mình cũng code iOS 1 thời gian rồi, nhưng ban đầu ko để ý mấy cái này lắm, mới dùng singleton nhưng thực sự chưa hiểu hết giá trị của nó.
    Bạn chia sẻ được thì tốt quá😀

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: