Objective C'de GCD dispatch_once istifadə edərək, bir single yaratmaq

İOS 4.0 və ya daha yüksək səviyyədə özelleştirebilirsiniz

GCD, Objective-C-də single-lər yaratmaq üçün ən yaxşı yol (iş parçacığı)?

 + (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once( ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } 
333
19 апр. Ryan tərəfindən 19 Martda təyin olundu 2011-04-19 20:07 '11 saat 20:07 'da 2011-04-19 20:07
@ 9 cavab

Bu, sinifin bir nümunəsi yaratmaq üçün mükəmməl məqbul və ipliklə təhlükəsiz bir yoldur. Texniki cəhətdən "tək" ola bilməz (yalnız bu obyektlərdən birinə malik ola bilər), ancaq bir obyektə çatmaq üçün [Foo sharedFoo] metodunu istifadə edərkən bu kifayətdir.

209
19 апр. Dave DeLong tərəfindən verilmiş cavab 19 aprel 2011-04-19 20:16 '11 at 20:16 2011-04-19 20:16

instancype

instancetype Objective-C üçün bir çox dil uzantısından biridir və daha çox hər bir yeni azad ilə əlavə edilir.

Onu sevirəm.

Bunu aşağı səviyyədə detallığa diqqətinizə Objektiv-C-yə çevirmək üçün güclü yeni yollar barədə fikir verə biləcəyinizə nümunə olaraq baxın.

Buraya baxın: instancetype

border=0
 + (instancetype)sharedInstance { static dispatch_once_t once; static id sharedInstance; dispatch_once( ^ { sharedInstance = [self new]; }); return sharedInstance; } 

 + (Class*)sharedInstance { static dispatch_once_t once; static Class *sharedInstance; dispatch_once( ^ { sharedInstance = [self new]; }); return sharedInstance; } 
35
13 нояб. Cavab Zelko Noyabr 13 verilir . 2013-11-13 09:49 '13 at 9:49 2013-11-13 09:49

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( ^{ shared = [[super alloc] initUniqueInstance]; }); return shared; } -(instancetype) initUniqueInstance { return [super init]; } @end 
30
18 марта '14 в 16:38 2014-03-18 16:38 Cavab Sergey Petruk'a 18 Mart, '14 'də 16:38' də veriləcək 2014-03-18 16:38

Dave doğru, yaxşıdır. Sifarişlərin paylaşılan Foo metodunu istifadə etmədikləri təqdirdə yalnız birinin yaradıla biləcəyini təmin etmək üçün digər üsulları necə tətbiq etmək barədə göstərişlər üçün Apple-ın Bir Parçalı Yaradılışını kontrol edə bilərsiniz.

6
19 апр. Cavab 19 Martda xristian tərəfindən verilir . 2011-04-19 20:48 '11 at 20:48 2011-04-19 20:48

Paylaşdırma metodunun üzərində yazılması ilə sinfi ayırmanın qarşısını ala bilərsiniz.

 @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( ^{ useinside = YES; _sharedObject = [[MyClass alloc] init]; useinside = NO; }); // returns the same object each time return _sharedObject; } 
5
22 авг. İ-geliştiricisinin cevaplaması 22 Av. 2013-08-22 16:40 '13 saat 16:40 'da 2013-08-22 16:40

[[MyClass alloc] init], paylaşılan bir maddə kimi sharedInstance (mənim fikrimcə, bu lazım deyil, lakin bəzi insanlar bunu istəyirəm), bu ikinci dispatch_once istifadə edərək, çox asanlıqla və təhlükəsiz edilə bilər əmin etmək istəyirsinizsə:

 - (instancetype)init { static dispatch_once_t once; static Class *sharedInstance; dispatch_once( ^ { // Your normal init code goes here. sharedInstance = self; }); return sharedInstance; } 

Bu, [[MyClass alloc] init] və [MyClass sharedInstance] hər hansı bir birləşməsini eyni obyektə qayıtmağa imkan verir; [MyClass sharedInstance] bir az daha təsirli olacaq. Necə işləyir? [MyClass sharedInstance] [[MyClass alloc] init] bir dəfə çağırır. Digər kod eyni sayda eyni ola bilər. Birinci init çağırıcısı bir "normal" başlanğıc yerinə yetirir və ilk üsulu init üsulunda saxlayır. Hər hansı bir sonradan çağırışlar tamamilə geri dəyərini görməməzlikdən və eyni paylaşılan dəyərini geri qaytarır; ayırmanın nəticəsi azad olacaq.

+ SharedInstance metodu həmişə olduğu kimi işləyəcəkdir. İlk arayan [[MyClass alloc] init] çağırmadıysa, init'in nəticəsi ayırma çağırışının nəticəsidir, lakin bu normaldır.

4
09 апр. Cavab verilir gnasher729 09 apr. 2014-04-09 14:43 '14 at 14:43 2014-04-09 14:43

Bir thread-safe singleton yaratmaq üçün aşağıdakıları edə bilərsiniz:

 @interface SomeManager : NSObject + (id)sharedManager; @end  @implementation SomeManager static id sharedManager = nil; + (void)initialize { if (self == [SomeManager class]) { sharedManager = [[self alloc] init]; } } + (id)sharedManager { return sharedManager; } @end 

və bu blog objc / kakao ilə çox yaxşı singlton singletons izah edir

0
15 дек. Hancock_Xu tərəfindən verilmiş cavab 15 dekabr. 2014-12-15 09:57 '14 da 9:57 2014-12-15 09:57

Bu, "bir single yaratmaq üçün ən yaxşı yol" olub-olmadığını soruşur.

Bir neçə fikir:

  • Birincisi, bəli, axın təhlükəsiz bir həlldir. Bu dispatch_once nüsxəsi Objective-C-də vahid ədəd yaratmaq üçün müasir, işlək vəziyyətdə olan təhlükəsiz yoludur. Xahiş etməyin.

  • Bunu həqiqətən "ən yaxşı" yoldan olub-olmadığını soruşdunuz. Buna baxmayaraq, bir nöqtə olanlar ilə birlikdə istifadə edildikdə, instancetype[[self alloc] init] potensial yanıltıcı olduğuna görə tanınmalıdır.

    İnançamın üstünlüyü ondan ibarətdir ki, keçmişdə etməmiş olduğumuz kimi, bir sinif id tipinə müraciət etmədən bir sinif alt sinifləşdirilə biləcəyini bəyan etmək üçün birmənalı bir yoldur.

    Lakin bu metodda static subclass problemləri təqdim edir. ImageCacheBlobCache , öz sharedCache Cache metodunu tətbiq etmədən Cache superclass'ından hər iki alt sinifdir?

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

    Bu iş üçün, alt siniflərin öz sharedInstance metodunu tətbiq etdiyinə əmin olmalısınız (və ya sizin xüsusi sinif üçün zəng etdiyiniz).

    Alt satırda, orijinal sharedInstance alt sinifləri dəstəkləyəcək kimi görünür, ancaq bu deyil. Alt sinifə dəstək vermək niyyətində olsanız, ən azı gələcək inkişaf etdiriciləri bu metodu ləğv etmələri barədə xəbərdar edən sənədləri daxil edin.

  • Swift ilə daha yaxşı uyğunluq üçün, ehtimal ki, bunu bir əmlak kimi müəyyən etmək istəyirik, məsələn, bir sinif metodu deyil:

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

    Sonra bu əmlak üçün getter yaza bilərsiniz (tətbiq siz təklif etdiyiniz dispatch_once şablonunu istifadə edəcək):

     + (Foo *)sharedFoo { ... } 

    Bunun üstünlüyü, əgər Swift istifadəçi onu istifadə etsə, onlar kimi bir şey edərdi:

     let foo = Foo.shared 

    Xahiş edirik unutmayın: no () , çünki biz onu bir əmlak kimi tətbiq etmişik. Swift 3-dən başlayaraq, bu singlon ilə necə paylaşılır. Buna görə, bir mülk olaraq təyin etmək, qarşılıqlı təsirini asanlaşdırır.

    Əlbəttə ki, əgər Apple öz singletonlarını necə müəyyənləşdirirsə, bu, məsələn, qəbul etdikləri bir şablondur. onların NSURLSession singleton aşağıdakı kimi müəyyən edilir:

     @property (class, readonly, strong) NSURLSession *sharedSession; 
  • Swift üçün bir çox kiçik uyğunluq baxımından tək adı idi. Hər sharedInstance , əgər siz sharedInstance dan daha çox növü adını daxil edə bilərsiniz. Məsələn, sinif Foo olarsa, singleton mülkünü sharedFoo olaraq təyin edə bilərsiniz. Sınıf DatabaseManager sharedManager , sharedManager . Sonra Swift istifadə edə bilər:

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

    Şübhəsiz ki, sharedInstance istifadə etmək istəyirsinizsə, hər halda Swift adını bəyan edə bilərsiniz:

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

    Şübhəsiz ki, Objective-C kodunu yazarkən, Swift uyğunluğuna digər dizayn məsələlərini daha ağır çəkməyə imkan verməməliyik, amma hər iki dildən zərif şəkildə dəstəkləyən kod yaza biləcəyiksə, bu da üstündür.

  • Başqaları ilə razılaşıram ki, əgər siz onu real nümunə olsanız, developers öz təsadüfi nümunələrini yaratmırlar (təsadüfən) unavailable , initnew ehtiyatlıdır.

0
22 марта '18 в 4:05 2018-03-22 04:05 Cavab Rob tərəfindən 22 Mart 18:05 ' da 4:05 2018-03-22 04:05' də verilir
 //Create Singleton +( instancetype )defaultDBManager { static dispatch_once_t onceToken = 0; __strong static id _sharedObject = nil; dispatch_once( ^{ _sharedObject = [[self alloc] init]; }); return _sharedObject; } //In it method -(instancetype)init { self = [super init]; if(self) { //Do your custom initialization } return self; } 
0
02 янв. Cavab Rohit Kashyap tərəfindən verilir. 02 yanvar. 2017-01-02 19:41 '17 saat 7:41 'da 2017-01-02 19:41

tags ilə bağlı digər suallar və ya bir sual verin