Blokir Daftar Sintaksis Deklarasi

277

Blok sintaksis di Objective C (dan memang C, saya kira) terkenal tidak sesuai. Melewati blok sebagai argumen terlihat berbeda dari mendeklarasikan blok sebagai ivar, yang terlihat berbeda dari typedefblok.

Apakah ada daftar lengkap sintaksis blok-deklarasi yang bisa saya pertahankan untuk referensi cepat?

Patrick Perini
sumber
9
Apa yang salah dengan "Mendeklarasikan dan Membuat Blok" di Panduan Topik Pemrograman Blok?
jscs
Penjelasan langsung tentang penggunaan properti blok: stackoverflow.com/a/20760583/294884
Fattie

Jawaban:

696

Daftar Sintaks Deklarasi Blok

Sepanjang, mari

  • return_typemenjadi jenis objek / primitif / dll. Anda ingin kembali (biasanya void)
  • blockName menjadi nama variabel dari blok yang Anda buat
  • var_typemenjadi tipe objek / primitif / dll. Anda ingin memberikan argumen (kosongkan tanpa parameter)
  • varName menjadi nama variabel dari parameter yang diberikan

Dan ingat bahwa Anda dapat membuat parameter sebanyak yang Anda inginkan.

Blok sebagai Variabel

Mungkin yang paling umum untuk deklarasi.

return_type (^blockName)(var_type) = ^return_type (var_type varName)
{
    // ...
};

Blok sebagai Properti

Sama seperti mendeklarasikan blok sebagai variabel, namun agak berbeda.

@property (copy) return_type (^blockName) (var_type);

Blok sebagai Parameter

Perhatikan bahwa ini berbeda dari "Blokir sebagai Argumen"; dalam contoh ini, Anda mendeklarasikan metode yang menginginkan argumen blok.

- (void)yourMethod:(return_type (^)(var_type))blockName;

Blok sebagai Argumen

Perhatikan bahwa ini berbeda dari "Blok sebagai Parameter"; dalam contoh ini, Anda memanggil metode yang ingin argumen blok dengan blok anonim. Jika Anda telah mendeklarasikan variabel blok, cukup untuk meneruskan nama variabel sebagai argumen.

[someObject doSomethingWithBlock: ^return_type (var_type varName)
{
    //...
}];

Blok Anonim

Ini secara fungsional blok anonim, namun sintaks untuk menetapkan blok ke variabel hanya untuk mengatur variabel sama dengan blok anonim.

^return_type (var_type varName)
{
    //...
};

typedef Blok

Ini memungkinkan Anda untuk mengatur nama pendek yang dapat direferensikan sama seperti nama kelas lainnya selama deklarasi blok.

typedef return_type (^blockName)(var_type);

Untuk kemudian menggunakan blockNamealih-alih sintaks deklarasi blok standar, cukup gantikan.

Blok sebaris

Ini bisa dibilang merupakan pemanfaatan blok yang kurang bermanfaat, tetapi tetap memiliki tempatnya. Blok inline adalah blok anonim yang dipanggil segera setelah instantiasi.

^return_type (var_type varName)
{
    //...
}(var);

Blok inline terutama berguna untuk offset ruang lingkup, dan kira-kira setara dengan potongan kode sederhana yang dibatasi oleh tanda kurung.

{
   //...
}

Blok Rekursif

Ini memungkinkan Anda untuk memanggil blok dari blok itu sendiri, membuat loop yang dapat digunakan selama panggilan balik dan panggilan GCD. Metode instantiasi ini bebas dari siklus penahan di ARC.

__block return_type (^blockName)(var_type) = [^return_type (var_type varName)
{
    if (returnCondition)
    {
        blockName = nil;
        return;
    }

    // ...
} copy];
blockName(varValue);

Blok Pengembalian

Metode dapat mengembalikan blok,

- (return_type(^)(var_type))methodName
{
    // ...
}

seperti yang bisa fungsi, jika agak aneh.

return_type (^FunctionName())(var_type)
{
    // ...
}

Adendum

Jika saya melewatkan sesuatu, beri tahu saya dalam komentar, dan saya akan meneliti / menambahkannya.

Oh, dan di Swift ...

blockName = (varName: var_type) -> (return_type)

Ini hampir seperti fitur bahasa.

Patrick Perini
sumber
1
@pcperini Daftar hebat! Dan bagaimana cara menggunakan definisi blok typedef'd dalam deklarasi variabel (item pertama dalam daftar Anda)? Logical BlockType ^blockVar = Anonymous Blockmenunjukkan kesalahan sintaks, tanpa ^ terlalu :(
esp
14
Entah bagaimana otak saya tidak mampu mengingat semua sintaks yang beragam ini untuk deklarasi blok. Saya mungkin melihat jawaban ini seminggu sekali. Seandainya saya bisa memberi Anda 10 upvotes untuk ini.
Ben Baron
36
Kami membutuhkan StackOverflow Hall of Fame untuk jawaban seperti ini.
bejonbee
1
Saya telah mengonversikan ini menjadi Markdown untuk digunakan dengan penampil untuk dicetak. Berguna! gist.github.com/swizzlr/6268955
Swizzlr
20
Saya pikir saya perlu ini sebagai tato.
Isaac Overacker
83

Saya pribadi suka menggunakan situs web ini ( http://fuckingblocksyntax.com ). Nama ini lebih mudah diingat daripada sintaks blok itu sendiri:

http://fuckingblocksyntax.com

dan jika Anda tidak dapat memuat URL dengan kata-kata buruk di dalamnya, Anda dapat menggunakan mirror ini: http://goshdarnblocksyntax.com

fuckingblocksyntax situs web

psy
sumber
1
nama yang sempurna untuk situs web ..: D
Vineeth
39

Typedef:

typedef void (^block)(NSString *arg);

Di barisan:

void (^block)(NSString *) = ^(NSString *param) {
  // do something....
};

Metode:

- (void)method:(void (^)(NSString *param))handler
Erik Aigner
sumber
Jawaban ini menunjukkan bahwa ternyata tidak sesulit itu ... hanya 3 sintaks yang berbeda untuk dipadupadankan.
Joseph Chen
4
Jawaban yang diterima hanyalah salinan dari jawaban ini dengan mengasapi yang tidak perlu.
Erik Aigner
16

Pustaka cuplikan Xcode 4 berisi templat untuk blok typedef dan inline blok sebagai variabel. Mereka juga tersedia melalui pelengkapan otomatis ( typedefblockdan inlineblock).

Untuk blok sebagai argumen untuk metode, saya akan merekomendasikan mendeklarasikan typedefdan kemudian hanya menggunakannya. Itu membuat kode lebih mudah dibaca.

omz
sumber
11

Saya menulis sebuahlockBlock untuk kelas yang akan mengembalikan nilai-nilai dadu setelah mereka diguncang:

  1. Tentukan typedef dengan returnType ( deklarasi di .hatas @interface)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
  2. Tentukan a @propertyuntuk blok ( .h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
  3. Tetapkan metode dengan finishBlock( .h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
  4. Masukkan metode yang didefinisikan sebelumnya dalam .mfile dan komit finishBlockuntuk @propertydidefinisikan sebelumnya

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
  5. Untuk memicu completionBlocklulus Variabel jenis yang telah ditentukan sebelumnya (Jangan lupa untuk memeriksa apakah completionBlockada)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }
Alex Cio
sumber
7
typedef void (^OkBtnBlock)(id data);
typedef void (^CancelBtnBlock)();

@property (nonatomic, strong) OkBtnBlock okBtnBlock;
@property (nonatomic, strong) CancelBtnBlock cancelBtnBlock;

+ (void)foo:(OkBtnBlock)okBtn andCancel:(CancelBtnBlock)btnCancel;
benhi
sumber
Akan bagus untuk menggambarkan keseluruhan proses langkah demi langkah, blok sulit untuk dipahami jika Anda baru mengenal ...
Alex Cio
3

Jika Anda perlu bekerja kembali di Xcode 4.2, Anda juga dapat @ mensintesiskan blok yang dinyatakan sebagai properti seperti yang Anda lakukan dengan properti non blok. Jangan biarkan sintaks blokir melempar Anda.

Jika properti blok Anda adalah ini:

@property (copy) return_type (^blockName) (var_type);

Maka, Anda mensintesis ini:

@property blockName;

Bersulang.

Alex Zavatone
sumber
Hai, bisa tolong periksa kembali .. Saya hanya mencoba mengikuti Anda .. @property blockNametidak bekerja. Saya pikir itu harus @synthesize blockName;? (untuk mensintesis satu blok)
jeet.chanchawat
oops ... tunggu Anda (secara tidak langsung) menyebutkan bahwa ia tidak akan berfungsi dengan xcode 7.
jeet.chanchawat