ios Objective C তে GCD এর dispatch_once ব্যবহার করে সিঙ্গলটন তৈরি করুন




objective-c singleton (8)

আপনি iOS 4.0 বা উপরে লক্ষ্য করতে পারেন

জিডিডি ব্যবহার করে, উদ্দেশ্য সি (সিঙ্গেল নিরাপদ) এ সিঙ্গল্ট তৈরি করার সেরা উপায়?

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

instancetype

instancetype Objective-C তে অনেক ভাষা এক্সটেনশনগুলির মধ্যে একটি মাত্র, প্রতিটি নতুন রিলিজের সাথে আরও যোগ করা হচ্ছে।

এটা জানি, এটা ভালোবাসি।

এবং নিম্ন-স্তরের বিশদগুলিতে মনোযোগ দেওয়ার পদ্ধতিটি কীভাবে আপনি উদ্দেশ্য-সি রূপান্তরিত করার জন্য শক্তিশালী নতুন উপায়ে অন্তর্দৃষ্টি দিতে পারেন তার একটি উদাহরণ হিসাবে গ্রহণ করুন।

এখানে পড়ুন: instancetype

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}
+ (Class*)sharedInstance
{
    static dispatch_once_t once;
    static Class *sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}

ডেভ সঠিক, যে পুরোপুরি সূক্ষ্ম। আপনি যদি ShareFoo পদ্ধতিটি ব্যবহার না করে তবে ক্লাসগুলি কেবলমাত্র তৈরি করা যেতে পারে তা নিশ্চিত করতে অন্য কয়েকটি পদ্ধতি বাস্তবায়নের জন্য টিপসগুলির জন্য একটি সিঙ্গলটন তৈরি করতে অ্যাপল এর ডক্সগুলি পরীক্ষা করতে চাইতে পারেন।


আপনি জিজ্ঞাসা করেন যে এটি "সিঙ্গলটন তৈরি করার সেরা উপায়" কিনা।

কয়েকটি চিন্তা:

  1. প্রথম, হ্যাঁ, এটি একটি থ্রেড-নিরাপদ সমাধান। এই dispatch_once প্যাটার্ন আধুনিক, থ্রেড নিরাপদ উপায় উদ্দেশ্য-সি মধ্যে singletons উৎপন্ন। সেখানে কোন উদ্বেগ নেই।

  2. আপনি জিজ্ঞাসা করেছেন, যদিও এটি এটি করার "সেরা" উপায় কিনা। এক, স্বীকার করা উচিত যে, instancetype এবং [[self alloc] init] যখন একক সাথে মিলিত হয় তখন সম্ভাব্য বিভ্রান্তিকর।

    Instancetype এর সুবিধাটি হল যে এটি এমন একটি ঘোষণা করার একটি অস্পষ্ট উপায় যা ক্লাসের উপাদানের সাথে কোনও উপায়ে উপবিষ্ট করা সম্ভব নয়, যেমনটি আমাদের আগে থেকেই করা হয়েছিল।

    কিন্তু এই পদ্ধতিতে static subclassing চ্যালেঞ্জ উপস্থাপন করে। ImageCache এবং BlobCache Cache একক ImageCache কীভাবে Cache সুপারক্লাস থেকে তাদের নিজস্ব sharedCache পদ্ধতি প্রয়োগ না করে উভয় sharedCache ?

    ImageCache *imageCache = [ImageCache sharedCache];  // fine
    BlobCache *blobCache = [BlobCache sharedCache];     // error; this will return the aforementioned ImageCache!!!

    এই কাজ করার জন্য, আপনাকে নিশ্চিত করতে হবে যে উপশ্রেণীগুলি তাদের নিজস্ব sharedInstance (অথবা আপনার নির্দিষ্ট ক্লাসের জন্য যেকোনো কল) পদ্ধতি প্রয়োগ করে।

    নিচের লাইন, আপনার মূল sharedInstance দেখে মনে হচ্ছে এটি উপশ্রেণীগুলি সমর্থন করবে, কিন্তু এটি হবে না। আপনি যদি সাব-ক্ল্যাসিং সমর্থন করতে চান তবে অন্ততপক্ষে ডকুমেন্টেশানগুলি ভবিষ্যতে ডেভেলপারদের সতর্ক করে দেয় যে তাদের এই পদ্ধতিটি অবশ্যই ওভাররাইড করতে হবে।

  3. সুইফ্টের সাথে সর্বোত্তম ইন্টারঅপারেবিলিটির জন্য, সম্ভবত আপনি এটি একটি সম্পত্তি হিসাবে নির্ধারণ করতে চান, ক্লাস শ্রেণী নয়, উদাহরণস্বরূপ:

    @interface Foo : NSObject
    @property (class, readonly, strong) Foo *sharedFoo;
    @end

    তারপরে আপনি এগিয়ে যেতে পারেন এবং এই সম্পত্তিটির জন্য একটি গেটর লিখতে পারেন (বাস্তবায়ন আপনি প্রস্তাবিত dispatch_once প্যাটার্ন ব্যবহার করবে):

    + (Foo *)sharedFoo { ... }

    এই সুবিধাটি যদি সুইফ্ট ব্যবহারকারী এটি ব্যবহার করতে যায় তবে তারা এমন কিছু করবে:

    let foo = Foo.shared

    নোট, কোন () , কারণ আমরা এটি একটি সম্পত্তি হিসাবে বাস্তবায়িত। সুইফ্ট 3 শুরু করা, এইভাবে এককভাবে সাধারণত অ্যাক্সেস করা হয়। সুতরাং সম্পত্তি হিসাবে এটি সংজ্ঞায়িত যে interoperability সহজতর সাহায্য করে।

    সরাইয়া হিসাবে, আপনি যদি অ্যাপলকে তাদের NSURLSession কীভাবে সংজ্ঞায়িত করেন তা NSURLSession তবে এটি তাদের প্যাটার্ন যা তারা গ্রহণ করেছে, উদাহরণস্বরূপ তাদের NSURLSession নিম্নরূপ সংজ্ঞায়িত করা হয়েছে:

    @property (class, readonly, strong) NSURLSession *sharedSession;
  4. আরেকটি, অতি ক্ষুদ্র সুইফ্ট ইন্টারঅপারেবিলিটি বিবেচনার একক নাম ছিল। sharedInstance পরিবর্তে আপনি যদি টাইপের নামটি অন্তর্ভুক্ত করতে পারেন তবে এটি sharedInstance । উদাহরণস্বরূপ, যদি ক্লাসটি Foo , তবে আপনি ভাগ করা Foo হিসাবে sharedFoo সম্পত্তি সংজ্ঞায়িত করতে পারেন। অথবা যদি sharedManager ডাটাবেস sharedManager , তবে আপনি sharedManager সম্পত্তিটি কল করতে পারেন। তারপর সুইফ্ট ব্যবহারকারীরা করতে পারে:

    let foo = Foo.shared
    let manager = DatabaseManager.shared

    স্পষ্টতই, যদি আপনি সত্যিই sharedInstance ব্যবহার করতে চান তবে আপনি সর্বদা সুইফ্ট নামটি প্রকাশ করতে চান:

    @property (class, readonly, strong) Foo* sharedInstance NS_SWIFT_NAME(shared);

    স্পষ্টতই, উদ্দেশ্য-সি কোড লেখার সময়, আমরা সুইফট ইন্টারঅপারোপলিবিলিটিটিকে অন্যান্য নকশা বিবেচনার বাইরে তুলতে দিই না, তবে আমরা যদি কোডটি লিখতে পারি যা উভয় ভাষাকে চিত্তাকর্ষকভাবে সমর্থন করে তবে এটি আরও ভাল।

  5. আমি অন্যদের সাথে একমত যে আপনি যদি এই সত্যিকারের সিঙ্গল্টন চান যেখানে ডেভেলপাররা তাদের নিজস্ব দৃষ্টান্তগুলি তাত্ক্ষণিকভাবে (/ আপাতত) তা করতে পারে না, তবে init এবং init unavailable যোগ্যতা জ্ঞানী।


MySingleton.h

@interface MySingleton : NSObject

+(instancetype)sharedInstance;

+(instancetype)alloc __attribute__((unavailable("alloc not available, call sharedInstance instead")));
-(instancetype)init __attribute__((unavailable("init not available, call sharedInstance instead")));
+(instancetype)new __attribute__((unavailable("new not available, call sharedInstance instead")));
-(instancetype)copy __attribute__((unavailable("copy not available, call sharedInstance instead")));

@end

MySingleton.m

@implementation MySingleton

+(instancetype)sharedInstance {
    static dispatch_once_t pred;
    static id shared = nil;
    dispatch_once(&pred, ^{
        shared = [[super alloc] initUniqueInstance];
    });
    return shared;
}

-(instancetype)initUniqueInstance {
    return [super init];
}

@end

এটি আপনার ক্লাসের একটি উদাহরণ তৈরি করার জন্য পুরোপুরি গ্রহণযোগ্য এবং থ্রেড-নিরাপদ উপায়। এটি টেকনিক্যালি একটি "সিঙ্গলটন" হতে পারে না (এতে কেবলমাত্র এই বস্তুর মধ্যে মাত্র 1 হতে পারে), কিন্তু যতক্ষণ আপনি কেবলমাত্র [Foo sharedFoo] পদ্ধতিটি অ্যাক্সেস করতে ব্যবহার করেন, এটি যথেষ্ট ভাল।


আপনি বরাদ্দ পদ্ধতি overwriting সঙ্গে বরাদ্দ বরাদ্দ যে এড়াতে পারেন।

@implementation MyClass

static BOOL useinside = NO;
static id _sharedObject = nil;


+(id) alloc {
    if (!useinside) {
        @throw [NSException exceptionWithName:@"Singleton Vialotaion" reason:@"You are violating the singleton class usage. Please call +sharedInstance method" userInfo:nil];
    }
    else {
        return [super alloc];
    }
}

+(id)sharedInstance
{
    static dispatch_once_t p = 0;
    dispatch_once(&p, ^{
        useinside = YES;
        _sharedObject = [[MyClass alloc] init];
        useinside = NO;
    });   
    // returns the same object each time
    return _sharedObject;
}

//Create Singleton  
  +( instancetype )defaultDBManager
    {

        static dispatch_once_t onceToken = 0;
        __strong static id _sharedObject = nil;

        dispatch_once(&onceToken, ^{
            _sharedObject = [[self alloc] init];
        });

        return _sharedObject;
    }


//In it method
-(instancetype)init
{
    self = [super init];
  if(self)
     {
   //Do your custom initialization
     }
     return self;
}

থ্রেড নিরাপদ এককন্টন তৈরি করতে আপনি এটি করতে পারেন:

@interface SomeManager : NSObject
+ (id)sharedManager;
@end

/* thread safe */
@implementation SomeManager

static id sharedManager = nil;

+ (void)initialize {
    if (self == [SomeManager class]) {
        sharedManager = [[self alloc] init];
    }
}

+ (id)sharedManager {
    return sharedManager;
}
@end

এবং এই ব্লগ একজোন / কোকো মধ্যে একক খুব ভাল singletons ব্যাখ্যা





grand-central-dispatch