รายการบล็อกการประกาศบล็อก


277

ไวยากรณ์ที่ถูกบล็อกใน Objective C (และแน่นอน C, ฉันเข้าใจ) ไม่เข้ากันอย่างฉาวโฉ่ การส่งบล็อกเป็นอาร์กิวเมนต์จะต่างไปจากการประกาศบล็อกเป็นไอวอรี่ซึ่งมีลักษณะแตกต่างจากtypedefบล็อกไอเอ็นจี

มีรายการที่ครอบคลุมของไวยากรณ์ประกาศบล็อกที่ฉันสามารถเก็บไว้เพื่อการอ้างอิงอย่างรวดเร็ว?


9
มีอะไรผิดปกติกับ"การประกาศและการสร้างบล็อก"ในคู่มือหัวข้อการเขียนโปรแกรมบล็อก
jscs

คำอธิบายที่ตรงไปตรงมาของการใช้คุณสมบัติบล็อก: stackoverflow.com/a/20760583/294884
Fattie

คำตอบ:


696

รายการบล็อกการประกาศที่ถูกบล็อก

ให้ทั่ว

  • return_typeเป็นประเภทของวัตถุ / ดั้งเดิม / ฯลฯ คุณต้องการที่จะกลับมา (ปกติvoid)
  • blockName เป็นชื่อตัวแปรของบล็อกที่คุณกำลังสร้าง
  • var_typeเป็นวัตถุชนิด / ดั้งเดิม / ฯลฯ คุณต้องการผ่านเป็นอาร์กิวเมนต์ (ปล่อยว่างไว้โดยไม่มีพารามิเตอร์)
  • varName เป็นชื่อตัวแปรของพารามิเตอร์ที่กำหนด

และจำไว้ว่าคุณสามารถสร้างพารามิเตอร์ได้มากเท่าที่คุณต้องการ

บล็อกเป็นตัวแปร

อาจเป็นเรื่องธรรมดาที่สุดสำหรับการประกาศ

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

บล็อกเป็นคุณสมบัติ

คล้ายกับการประกาศบล็อกเป็นตัวแปร แต่แตกต่างกันเล็กน้อย

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

บล็อกเป็นพารามิเตอร์

โปรดทราบว่าสิ่งนี้แตกต่างจาก "บล็อกเป็นอาร์กิวเมนต์"; ในตัวอย่างนี้คุณกำลังประกาศวิธีที่ต้องการโต้แย้งอาร์กิวเมนต์

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

บล็อกเป็นอาร์กิวเมนต์

โปรดทราบว่าสิ่งนี้แตกต่างจาก "บล็อกเป็นพารามิเตอร์"; ในตัวอย่างนี้คุณกำลังเรียกวิธีการที่ต้องการโต้แย้งอาร์กิวเมนต์ด้วยบล็อกที่ไม่ระบุชื่อ หากคุณได้ประกาศตัวแปรบล็อกแล้วมันก็เพียงพอที่จะผ่านชื่อตัวแปรเป็นอาร์กิวเมนต์

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

บล็อกนิรนาม

นี่คือบล็อกที่ไม่ระบุชื่อที่ใช้งานได้อย่างไรก็ตามไวยากรณ์สำหรับการกำหนดบล็อกให้กับตัวแปรนั้นเป็นเพียงการตั้งค่าตัวแปรให้เท่ากับบล็อกที่ไม่ระบุชื่อ

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

typedef บล็อก

สิ่งนี้อนุญาตให้คุณตั้งค่าชื่อแบบสั้นที่สามารถอ้างอิงได้เช่นเดียวกับชื่อคลาสอื่น ๆ ในระหว่างการประกาศบล็อก

typedef return_type (^blockName)(var_type);

หากต้องการใช้ในภายหลังblockNameแทนไวยากรณ์ประกาศบล็อกมาตรฐานเพียงแทนที่

บล็อกแบบอินไลน์

นี่เป็นการใช้ประโยชน์จากบล็อกที่มีประโยชน์น้อยกว่า แต่อาจมีตำแหน่งได้ บล็อกแบบอินไลน์คือบล็อกนิรนามที่ถูกเรียกใช้ทันทีหลังจากการสร้างอินสแตน

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

บล็อกแบบอินไลน์มีประโยชน์อย่างยิ่งสำหรับการชดเชยขอบเขตและโดยคร่าว ๆ จะเทียบเท่ากับชิ้นส่วนของรหัสที่ใช้วงเล็บปีกกาแบบง่ายๆ

{
   //...
}

บล็อกแบบเรียกซ้ำ

สิ่งนี้ช่วยให้คุณสามารถเรียกบล็อกจากตัวเองสร้างวงที่สามารถใช้ในระหว่างการโทรกลับและโทร GCD วิธีการสร้างอินสแตนซ์นี้ไม่มีการวนรอบใน ARC

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

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

การกลับมาบล็อก

วิธีสามารถส่งคืนบล็อก

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

เช่นเดียวกับฟังก์ชั่นถ้าบิตแปลก

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

แนบท้าย

หากฉันไม่ได้รับอะไรเลยโปรดแจ้งให้เราทราบในความคิดเห็นและฉันจะทำการวิจัย / เพิ่มพวกเขา

โอ้และในสวิฟท์ ...

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

มันเกือบจะเหมือนเป็นคุณสมบัติทางภาษา


1
@pcperini เป็นรายการที่ยอดเยี่ยม! และวิธีใช้ typedef'd บล็อกคำจำกัดความในการประกาศตัวแปร (รายการที่ 1 ในรายการของคุณ) Logical BlockType ^blockVar = Anonymous Blockแสดงข้อผิดพลาดทางไวยากรณ์โดยไม่มี ^ เกินไป :(
esp

14
อย่างไรก็ตามสมองของฉันไม่สามารถจดจำไวยากรณ์ต่าง ๆ เหล่านี้ทั้งหมดสำหรับการประกาศบล็อก ฉันอาจดูคำตอบนี้สัปดาห์ละครั้ง หวังว่าฉันจะให้ 10 upvotes สำหรับสิ่งนี้
Ben Baron

36
เราต้องการหอเกียรติยศ StackOverflow สำหรับคำตอบเช่นนี้
bejonbee

1
ฉันได้แปลงสิ่งนี้เป็น Markdown สำหรับใช้กับวิวเวอร์สำหรับการพิมพ์ ที่มีประโยชน์! gist.github.com/swizzlr/6268955
Swizzlr

20
ฉันคิดว่าฉันต้องการสิ่งนี้เป็นรอยสัก
Isaac Overacker

83

ฉันชอบใช้เว็บไซต์นี้เป็นส่วนตัว ( http://fuckingblocksyntax.com ) ชื่อนั้นง่ายต่อการจดจำได้ง่ายกว่าไวยากรณ์ของบล็อก:

http://fuckingblocksyntax.com

และหากคุณไม่สามารถโหลด URL ด้วยคำที่ไม่เหมาะสมคุณสามารถใช้มิรเรอร์นี้: http://goshdarnblocksyntax.com

เว็บไซต์ fuckingblocksyntax


1
ชื่อที่สมบูรณ์แบบสำหรับเว็บไซต์ .. : D
Vineeth

39

typedef:

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

แบบอินไลน์:

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

วิธี:

- (void)method:(void (^)(NSString *param))handler

คำตอบนี้แสดงให้เห็นว่ามันไม่ซับซ้อนเลย ... เพียงแค่ 3 รูปแบบที่แตกต่างกันในการมิกซ์และจับคู่
Joseph Chen

4
คำตอบที่ได้รับการยอมรับเป็นเพียงสำเนาของคำตอบนี้โดยไม่จำเป็น
Erik Aigner

16

ตัวอย่างโค้ด Xcode 4 มีเทมเพลตสำหรับบล็อก typedefs และ inline blocks เป็นตัวแปร นอกจากนี้ยังมีให้ผ่านการเติมข้อความอัตโนมัติ ( typedefblockและinlineblock)

สำหรับบล็อกเป็นอาร์กิวเมนต์ของวิธีการฉันขอแนะนำให้ประกาศ a typedefแล้วใช้วิธีนั้น ทำให้อ่านรหัสง่ายขึ้นมาก


11

ฉันเขียนส่วนที่สมบูรณ์แล้วสำหรับคลาสที่จะคืนค่าของลูกเต๋าหลังจากพวกเขาถูกเขย่าแล้ว:

  1. กำหนด typedef ด้วย returnType ( ประกาศ.hด้านบน@interface)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
  2. กำหนด a @propertyสำหรับบล็อก ( .h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
  3. กำหนดวิธีการด้วยfinishBlock( .h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
  4. แทรกวิธีที่กำหนดไว้ก่อนหน้าใน.mไฟล์และกระทำfinishBlockเพื่อ@propertyกำหนดไว้ก่อนหน้า

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
  5. หากต้องการเรียกใช้งานcompletionBlockVariType ที่กำหนดไว้ล่วงหน้าให้กับมัน (อย่าลืมตรวจสอบว่าcompletionBlockมีอยู่จริงหรือไม่)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }

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;

จะเป็นการดีที่จะอธิบายกระบวนการทั้งหมดทีละขั้นตอนบล็อกยากที่จะเข้าใจถ้าคุณยังใหม่กับ ios ...
Alex Cio

3

หากคุณต้องการกลับมาทำงานใน Xcode 4.2 คุณสามารถ @synthesize บล็อกที่ประกาศเป็นคุณสมบัติเช่นเดียวกับที่คุณทำกับคุณสมบัติบล็อกที่ไม่ใช่ อย่าให้ไวยากรณ์ของบล็อกคุณโยนทิ้งไป

หากคุณสมบัติบล็อกของคุณคือ:

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

จากนั้น @synthesize ของคุณคือ:

@property blockName;

ไชโย


สวัสดีโปรดตรวจสอบอีกครั้ง .. ฉันแค่พยายามติดตามคุณ .. @property blockNameไม่ทำงาน ฉันคิดว่ามันควรจะเป็น@synthesize blockName;อย่างไร (สำหรับการสังเคราะห์บล็อก)
jeet.chanchawat

โอ๊ะ ... รอคุณอยู่แล้ว (อ้อม) กล่าวว่าเคยทำงานกับ Xcode 7
jeet.chanchawat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.