예전에 Objective-C에서 Singleton 객체를 만드는 방법에 대해 써놓은 글(http://b4you.net/blog/210)이 있었는데 사용하다보니 몇 가지 제약이 있어 새로 만들어 보았습니다.

문제는 singleton 클래스를 하나 만들어 두고 그 클래스를 상속받으면 하위 클래스도 singleton 객체가 되게끔 하려고 하는데 여기서 여러 클래스가 상속을 받게 되면 static 객체를 공유한다는 것이었습니다.
각 객체마다 static 영역이 있어서 공유되는게 당연한데 상속 구조를 고려하지 않고 구현을 해놓은 바람에 귀찮은 문제가 발생하더군요. 이러한 것들은 C++이야 template를 사용하여 처리하면 되는데 Objective-C는 그렇게 되질 않아 다음과 같이 수정하였습니다.

+ (SingletonClass *)sharedSingletonClass
{
	static NSMutableDictionary *dictionary = nil;
	id sharedObject = nil;
	NSString *className;
	
	// for DCL
	if(dictionary == nil)
	{
		@synchronized(self)
		{
			if(dictionary == nil)
			{
				dictionary = [[NSMutableDictionary alloc] init];
			}
		}
	}
	
	className = NSStringFromClass([self class]);
	
	sharedObject = [dictionary objectForKey:className];

	// for DCL
	if(sharedObject == nil)
	{
		@synchronized(self)
		{
			sharedObject = [dictionary objectForKey:className];
			
			if(sharedObject == nil)
			{
				sharedObject = [[[self class] alloc] init];
				[dictionary setObject:sharedObject forKey:className];
			}
		}
	}
	
	return sharedObject;
}

달라진 부분은 NSDictionary를 사용한 점 입니다. 이렇게 처리하면 dictionary 내에서 search 할 때의 속도 때문에 overhead가 발생하긴 하겠지만, 상속 구조에서도 깔끔하게 잘 사용할 수 있습니다.

아직까진 다른 문제점은 없었으나 문제가 발생하면 3탄을 만들어야겠군요 ㅎㅎ
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2010/09/24 00:05 2010/09/24 00:05
Response
8 Trackbacks , No Comment
RSS :
http://b4you.net/blog/rss/response/257

iPhone 개발 중 Network Indicator(이하 NI)를 사용하다 보면 다음과 같은 경우가 있습니다.

1. thread1에서 network 사용 (NI 켬)
2. thread2에서 network 사용 (NI 켬)
3. thread1이 통신을 마침 (NI 끔)
4. thread2가 통신을 마침 (NI 끔)

이러한 시나리오를 거쳤을 때 UIApplication의 setNetworkActivitryIndicatorVisible값을 변경하는 것 만으로는 문제가 있습니다. 위의 예에서는 3번에서 NI를 껐을 때 thread1은 network를 사용중임에도 불구하고 NI는 꺼져 있는 것으로 나타납니다.

이러한 현상을 해결하기 위해 작성한 singleton class입니다. (singleton class 제작 방법: http://b4you.net/blog/210)

// NetworkActivityManager.h
#import <Foundation/Foundation.h>

@interface NetworkActivityManager : NSObject
{
    volatile NSUInteger _visibleCount;
}

+ (NetworkActivityManager *)sharedNetworkActivityManager;
- (void)setNetworkActivityIndicatorVisible:(BOOL)visible;

@property(readwrite) volatile NSUInteger _visibleCount;

@end


//  NetworkActivityManager.m
#import "NetworkActivityManager.h"

@implementation NetworkActivityManager

@synthesize _visibleCount;

+ (NetworkActivityManager *)sharedNetworkActivityManager
{
    static NetworkActivityManager *networkActivityClass = nil;
    
    if(networkActivityClass == nil)
    {
        @synchronized(self)
        {
            if(networkActivityClass == nil)
            {
                networkActivityClass = [[self alloc] init];
                networkActivityClass._visibleCount = 0;
                [self autorelease];
            }
        }
    }
    
    return networkActivityClass;
}

- (void)setNetworkActivityIndicatorVisible:(BOOL)visible
{
    @synchronized(self)
    {
        if(visible == YES)
        {
            _visibleCount++;
            
            [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        }
        else if(visible == NO)
        {
            if(_visibleCount <= 1)
            {
                // 모든 곳에서 NO로 했다면
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                _visibleCount = 0;
            }
            else
            {
                // YES로 한 곳이 남아있다면
                _visibleCount--;
            }
        }
    }
}

@end


사용 방법은 다음과 같이~

[[NetworkActivityManager sharedNetworkActivityManager] setNetworkActivityIndicatorVisible:NO];

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/05/21 18:25 2009/05/21 18:25
, ,
Response
No Trackback , a comment
RSS :
http://b4you.net/blog/rss/response/225

Objective-C에서 Singleton객체 만들기

Objective-C에서 Singleton 객체를 만드는방법은 다음과 같습니다.

//  SingletonClass.h

#import <Foundation/Foundation.h>

@interface SingletonClass : NSObject
{
}

+ (SingletonClass *)sharedSingletonClass;

@end


//  SingletonClass.m

#import "SingletonClass.h"

@implementation SingletonClass

+ (SingletonClass *)sharedSingletonClass
{
    static SingletonClass *singletonClass = nil;
    
    if(singletonClass == nil)
    {
        @synchronized(self)
        {
            if(singletonClass == nil)
            {
                singletonClass = [[self alloc] init];
            }
        }
    }
        
    return singletonClass;
}

@end


여기선 DCL(double-checked locking)을 사용하였는데, Objective-C에서도 최적화 과정에서 비교 구문의 instruction의 위치가 바뀐다면.. 엄밀히 말하면 100% 안전한 코드는 아니되겠습니다.


사용 방법은

SingletonClass *s = [SingletonClass sharedSingletonClass];


와 같이 하시면 됩니다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/03/31 13:04 2009/03/31 13:04
,
Response
No Trackback , 8 Comments
RSS :
http://b4you.net/blog/rss/response/210


블로그 이미지

빗소리를 먹는 사람.

- 장현준

Notices

Archives

Authors

  1. 장현준

Recent Trackbacks

Calendar

«   2017/12   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            

Site Stats

Total hits:
2084475
Today:
4319
Yesterday:
5115