{"id":284180,"date":"2017-03-30T15:35:02","date_gmt":"2017-03-30T11:35:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=284180"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=284180","title":{"rendered":"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 code blocks \u0438\u0437 Objective-C \u0432 Delphi \u043d\u0430 macOS: \u043a\u0430\u043a \u043c\u044b \u043d\u0430\u0432\u0435\u043b\u0438 \u043c\u043e\u0441\u0442\u044b"},"content":{"rendered":"<p><img decoding=\"async\" src=\"http:\/\/www.tamos.com\/temp\/bridge.jpg\" alt=\"image\"\/><\/p>\n<p>  <\/p>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0441\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D1%82%D1%91%D0%BD%D0%BA%D0%B0\">\u043c\u0435\u0442\u043e\u0434 \u0443\u0442\u0435\u043d\u043a\u0430<\/a> (rubber duck debugging). \u0421\u0443\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u0441\u0435\u0441\u0442\u044c \u0432 \u0432\u0430\u043d\u043d\u0443\u044e, \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u0442\u044c\u0441\u044f, \u043f\u043e\u0441\u0430\u0434\u0438\u0442\u044c \u043d\u0430 \u0432\u043e\u0434\u0443 \u0438\u0433\u0440\u0443\u0448\u0435\u0447\u043d\u043e\u0433\u043e \u0443\u0442\u0435\u043d\u043a\u0430, \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0435\u043c\u0443 \u0441\u0443\u0442\u044c \u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438. \u0418, \u0447\u0443\u0434\u0435\u0441\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u0441\u043b\u0435 \u0442\u0430\u043a\u043e\u0439 \u0431\u0435\u0441\u0435\u0434\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f. <\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/habrahabr.ru\/post\/319922\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435<\/a>, \u0433\u0434\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 <a href=\"http:\/\/www.tamos.com\/products\/wifi-site-survey\/\">TamoGraph Site Survey<\/a> \u0434\u043b\u044f macOS, \u0432 \u0440\u043e\u043b\u0438 \u0443\u0442\u0435\u043d\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0441\u0430\u043c \u0425\u0430\u0431\u0440: \u044f \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 code blocks \u0438\u0437 Objective-C \u0432 Delphi. \u0418 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e! \u041f\u0440\u0438\u0448\u043b\u043e \u043f\u0440\u043e\u0441\u0432\u0435\u0442\u043b\u0435\u043d\u0438\u0435, \u0438 \u0432\u0441\u0451 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u041e \u0445\u043e\u0434\u0435 \u043c\u044b\u0441\u043b\u0435\u0439 \u0438 \u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u044f \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u043b\u044f \u0442\u0435\u0445 \u043a\u0442\u043e \u043d\u0435 \u0447\u0438\u0442\u0430\u043b \u043f\u0440\u043e\u0448\u043b\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u0435\u0449\u0435 \u0440\u0430\u0437 \u043a\u0440\u0430\u0442\u043a\u043e \u0438\u0437\u043b\u0430\u0433\u0430\u044e \u0441\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. <a href=\"https:\/\/developer.apple.com\/library\/content\/documentation\/Cocoa\/Conceptual\/ProgrammingWithObjectiveC\/WorkingwithBlocks\/WorkingwithBlocks.html\">Code blocks<\/a> \u2014 \u044d\u0442\u043e \u044f\u0437\u044b\u043a\u043e\u0432\u0430\u044f \u0444\u0438\u0447\u0430 \u0421++ \u0438 Objective-C, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 Delphi. \u0422\u043e\u0447\u043d\u0435\u0435, Delphi \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 code blocks, \u043d\u043e \u043e\u043d \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0442\u0435\u043c\u0438 code blocks, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0442 \u043d\u0430c macOS API. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438\u043c\u0435\u044e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f code blocks \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 handler&#8217;\u043e\u0432 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f. \u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2014 <a href=\"https:\/\/developer.apple.com\/reference\/appkit\/nssavepanel\/1527007-beginwithcompletionhandler?language=objc\">beginWithCompletionHandler<\/a> \u043a\u043b\u0430\u0441\u0441\u043e\u0432 <code>NSSavePanel<\/code> \u0438 <code>NSOpenPanel<\/code>. \u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 \u0441ode block \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"objectivec\">- (IBAction)openExistingDocument:(id)sender {    NSOpenPanel* panel = [NSOpenPanel openPanel];     \/\/ This method displays the panel and returns immediately.    \/\/ The completion handler is called when the user selects an    \/\/ item or cancels the panel.    [panel beginWithCompletionHandler:^(NSInteger result){       if (result == NSFileHandlingPanelOKButton) {          NSURL*  theDoc = [[panel URLs] objectAtIndex:0];           \/\/ Open  the document.       }     }]; }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u0432 \u0441 \u0443\u0442\u0435\u043d\u043a\u043e\u043c, \u044f \u043e\u0441\u043e\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u043d\u0435 \u0441 \u0442\u043e\u0433\u043e \u043a\u043e\u043d\u0446\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u044d\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Delphi. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u0430\u0434\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u044f\u0437\u044b\u043a\u0430\u0445. Google \u0432 \u0440\u0443\u043a\u0438 \u0438 \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u0438\u0439 \u043a \u043d\u0430\u0448\u0435\u0439 \u0442\u0435\u043c\u0435 \u043a\u043e\u0434 \u0434\u043b\u044f Python \u0438 JavaScript <a href=\"https:\/\/github.com\/jsbain\/objc_hacks\/blob\/master\/objcblock.py\">\u0442\u0443\u0442<\/a> \u0438 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/js-ctypes\/Examples\/Using_Objective-C_from_js-ctypes\">\u0442\u0443\u0442<\/a>. \u0425\u043e\u0440\u043e\u0448\u0438\u0439 \u0441\u0442\u0430\u0440\u0442: \u0435\u0441\u043b\u0438 \u0438\u043c \u044d\u0442\u043e \u0443\u0434\u0430\u043b\u043e\u0441\u044c, \u0442\u043e \u0443\u0434\u0430\u0441\u0442\u0441\u044f \u0438 \u043d\u0430\u043c. \u041f\u043e \u0441\u0443\u0442\u0438, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044f, \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0442\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0430\u0441\u0441\u043e\u0432 macOS, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u044e\u0442 \u043e\u0442 \u043d\u0430\u0441 \u0431\u043b\u043e\u043a\u043e\u0432. \u0415\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0433\u0443\u0433\u043b\u0435\u043d\u0438\u044f, \u0438 \u043c\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u043c <a href=\"https:\/\/opensource.apple.com\/source\/libclosure\/libclosure-38\/Block_private.h\">\u0445\u0435\u0434\u0435\u0440<\/a> \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 Apple:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">struct Block_descriptor {     unsigned long int reserved;     unsigned long int size;     void (*copy)(void *dst, void *src);     void (*dispose)(void *); };  struct Block_layout {     void *isa;     int flags;     int reserved;      void (*invoke)(void *, ...);     struct Block_descriptor *descriptor;     \/\/ imported variables };<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0437\u043b\u0430\u0433\u0430\u0435\u043c \u044d\u0442\u043e \u043d\u0430 \u041f\u0430\u0441\u043a\u0430\u043b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">  Block_Descriptor = packed record     Reserved: NativeUint;     Size: NativeUint;     copy_helper: pointer;     dispose_helper: pointer;   end;   PBlock_Descriptor = ^Block_Descriptor;    Block_Literal = packed record     Isa: pointer;     Flags: integer;     Reserved: integer;     Invoke: pointer;     Descriptor: PBlock_Descriptor;   end;   PBlock_Literal = ^Block_Literal;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u043e\u0447\u0438\u0442\u0430\u0432 \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0431\u043b\u043e\u043a\u0430\u0445 (<a href=\"https:\/\/www.cocoawithlove.com\/2009\/10\/how-blocks-are-implemented-and.html\">How blocks are implemented<\/a> \u0438 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, <a href=\"https:\/\/habrahabr.ru\/post\/271255\/\">Objective-C: \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0431\u043b\u043e\u043a\u0438<\/a>), \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0431\u043b\u043e\u043a\u0430, \u043f\u043e\u043a\u0430 \u0432 \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435, \u043d\u0430 \u043a\u043e\u043b\u0435\u043d\u043a\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">Var   OurBlock: Block_Literal; function CreateBlock: pointer; var   aDesc:  PBlock_Descriptor; begin   FillChar(OurBlock, SizeOf(Block_Literal), 0);   \/\/ Isa \u2013 \u043f\u0435\u0440\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043b\u043e\u043a\u0430-\u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0438 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0432 \u043d\u0435\u0433\u043e   \/\/ \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430, &quot;NSBlock&quot;.   OurBlock.Isa    := NSClassFromString ((StrToNSStr('NSBlock') as ILocalobject).GetObjectID);   \/\/ \u0423\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043d\u0430\u0448 \u043a\u043e\u043b\u043b\u0431\u0435\u043a. \u042d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f cdecl, \u043e\u0431\u044f\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435.   OurBlock.Invoke := @InvokeCallback;   \/\/ \u0410\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f Block_Descriptor   New(aDesc);   aDesc.Reserved       := 0;   \/\/ \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440   aDesc.Size           := SizeOf(Block_Literal);   OurBlock.Descriptor := aDesc;    result:= @OurBlock; end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0435 <code>flags<\/code> \u043c\u044b \u043f\u043e\u043a\u0430 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0443\u043b\u0435\u0432\u044b\u043c, \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b. \u041f\u043e\u0437\u0436\u0435 \u043e\u043d\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f. \u041d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0434\u0435\u043a\u043b\u0430\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0430. \u041f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>NSBlock<\/code>, \u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 Cocoa-\u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c code block. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435, \u0441 <code>NSSavePanel<\/code>, \u044d\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430 \u0441 \u043e\u0434\u043d\u0438\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0442\u0438\u043f\u0430 <code>NSInteger<\/code>. \u0422\u0430\u043a \u0438 \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">procedure InvokeCallback (aNSBlock: pointer; i1: NSInteger); cdecl; begin   Sleep(0); end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u0443\u0434\u0430\u0440 \u043f\u043e \u0432\u043e\u0440\u043e\u0442\u0430\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">    FSaveFile := TNSSavePanel.Wrap(TNSSavePanel.OCClass.savePanel);     NSWin := WindowHandleToPlatform(Screen.ActiveForm.Handle).Wnd;     objc_msgSendP2(                    (FSaveFile as ILocalObject).GetObjectID,                    sel_getUid(PAnsiChar('beginSheetModalForWindow:completionHandler:')),                    (NSWin as ILocalObject).GetObjectID,                    CreateBlock                    ); <\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430, \u043c\u044b \u0436\u043c\u0435\u043c \u041e\u041a \u0438\u043b\u0438 Cancel \u0438 \u2026 \u0434\u0430! \u041c\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u043c \u043d\u0430 break point, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043d\u0430 <code>Sleep(0)<\/code>, \u0438 \u0434\u0430, \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0435 <code>i1<\/code> \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0431\u043e 0, \u043b\u0438\u0431\u043e 1, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u0435 \u043c\u044b \u043d\u0430\u0436\u0430\u043b\u0438. \u041f\u043e\u0431\u0435\u0434\u0430! \u041c\u044b \u0441 \u0443\u0442\u0435\u043d\u043a\u043e\u043c \u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u044b, \u043d\u043e \u0432\u043f\u0435\u0440\u0435\u0434\u0438 \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438 \u0442\u0438\u043f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u043c\u0438. \u0415\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u043d\u0430\u0431\u043e\u0440\u044b, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c.<\/li>\n<li>\u0423 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434-\u0431\u043b\u043e\u043a\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u0432\u044b\u0437\u043e\u0432\u043e\u043c completion handler \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0438, \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0434\u0438\u0430\u043b\u043e\u0433 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0434-\u0431\u043b\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0432\u0442\u043e\u0440\u044b\u043c, \u0430 \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u043a\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u0444\u0430\u0439\u043b, \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u0434-\u0431\u043b\u043e\u043a. \u0425\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u0432\u0435\u0441\u0442\u0438 \u0443\u0447\u0435\u0442.<\/li>\n<li>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0442 \u0431\u043b\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u0432\u0430\u043b \u043a\u043e\u043b\u043b\u0431\u0435\u043a, \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u043e\u043c\u0443 \u0431\u043b\u043e\u043a\u0443 \u043a\u043e\u0434 Delphi.<\/li>\n<li>\u0411\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u043e\u0441\u0442\u0438\u043a \u043c\u0435\u0436\u0434\u0443 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0432 Delphi \u0438 \u043a\u043e\u0434-\u0431\u043b\u043e\u043a\u0430\u043c\u0438, \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u0451 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0438 \u043a\u0440\u0430\u0441\u043e\u0442\u0430. \u0425\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u043e\u0432 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"delphi\">SomeNSClassInstance.SomeMethodWithCallback (                 Arg1,                 Arg2,                     TObjCBlock.CreateBlockWithProcedure(                           procedure (p1: NSInteger)                           begin                             if p1 = 0                               then ShowMessage ('Cancel')                               else ShowMessage ('OK');                            end)                    );<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0432\u0438\u0434\u0430 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u043e\u0432. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u0441\u0430\u043c\u044b\u0439 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2013 \u0438\u043c\u0435\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0432\u043e\u0439 \u043a\u043e\u043b\u043b\u0431\u0435\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">procedure InvokeCallback1 (aNSBlock: pointer; p1: pointer); cdecl; procedure InvokeCallback2 (aNSBlock: pointer; p1, p2: pointer); cdecl; procedure InvokeCallback3 (aNSBlock: pointer; p1, p2, p3: pointer); cdecl;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e \u043a\u0430\u043a-\u0442\u043e \u044d\u0442\u043e \u043d\u0443\u0434\u043d\u043e \u0438 \u043d\u0435\u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b\u0441\u043b\u044c \u0432\u0435\u0434\u0435\u0442 \u043d\u0430\u0441 \u0434\u0430\u043b\u044c\u0448\u0435. \u0427\u0442\u043e, \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0432\u0438\u0434 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0430, \u043f\u0440\u043e\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u0432\u0430\u043b \u043a\u043e\u043b\u043b\u0431\u0435\u043a, \u0443\u0437\u043d\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u043e\u043f\u043e\u043b\u0437\u0442\u0438 \u043f\u043e \u0441\u0442\u0435\u043a\u0443, \u0447\u0438\u0442\u0430\u044f \u043d\u0443\u0436\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432?<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">procedure InvokeCallback (aNSBlock: pointer); cdecl; var   i, ArgNum: integer;   p: PByte;   Args: array of pointer; begin   i:= FindMatchingBlock(aNSBlock);   if i &gt;= 0 then   begin     p:= @aNSBlock;     Inc(p, Sizeof(pointer));   \/\/ \u041f\u0440\u044b\u0433\u0430\u0435\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432     ArgNum:= GetArgNum(...);     if ArgNum &gt; 0 then     begin       SetLength(Args, ArgNum);       Move(p^, Args[0], SizeOf(pointer) * ArgNum);     end;   ... end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043c\u044b\u0441\u043b\u044c? \u041d\u0435\u0442, \u043f\u043b\u043e\u0445\u0430\u044f. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 32-\u0431\u0438\u0442\u043d\u043e\u043c \u043a\u043e\u0434\u0435, \u043d\u043e \u0433\u0440\u043e\u0445\u043d\u0435\u0442\u0441\u044f \u043a \u0447\u0435\u0440\u0442\u043e\u0432\u043e\u0439 \u043c\u0430\u0442\u0435\u0440\u0438 \u0432 64-\u0431\u0438\u0442\u043d\u043e\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e cdecl \u0432 64-\u0431\u0438\u0442\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043d\u0435 \u0431\u044b\u0432\u0430\u0435\u0442, \u0430 \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u0430 \u043e\u0431\u0449\u0430\u044f calling convention, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 cdecl, \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u043d\u0435 \u0432 \u0441\u0442\u044d\u043a\u0435, \u0430 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. \u041d\u0443 \u0447\u0442\u043e \u0436\u0435, \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0435\u0449\u0435 \u043f\u0440\u043e\u0449\u0435, \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">function InvokeCallback(aNSBlock, p1, p2, p3, p4: pointer): pointer; cdecl;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e. \u0412 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u043c\u0443\u0441\u043e\u0440, \u043d\u043e \u043c\u044b \u043a \u043d\u0438\u043c \u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f. \u0418 \u0437\u0430\u043e\u0434\u043d\u043e \u043c\u044b \u0441\u043c\u0435\u043d\u0438\u043b\u0438 procedure \u043d\u0430 function, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 code block \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. Disclaimer: \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d\u044b \u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0438 \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041c\u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c, \u043d\u043e, \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, tastes differ.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u043b\u043e\u043a\u0430, \u0442\u043e \u0442\u0443\u0442 \u0432\u0441\u0451 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e: <code>aNSBlock<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043a \u043d\u0430\u043c, \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0432 \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0435, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0440\u043e\u0432\u043d\u043e \u043d\u0430 \u0442\u043e\u0442 \u0436\u0435 <code>Descriptor<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043c\u044b \u043f\u043e\u043a\u0440\u043e\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 90 \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0432 \u043a\u043b\u0430\u0441\u0441\u0430\u0445 macOS \u0438 \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">type    TProc1 = TProc;   TProc2 = TProc&lt;pointer&gt;;   TProc3 = TProc&lt;pointer, pointer&gt;;   TProc4 = TProc&lt;pointer, pointer, pointer&gt;;   TProc5 = TProc&lt;pointer, pointer, pointer, pointer&gt;;   TProc6 = TProc&lt;NSInteger&gt;;   TProc7 = TFunc&lt;NSRect, boolean&gt;;    TProcType = (ptNone, pt1, pt2, pt3, pt4, pt5, pt6, pt7);    TObjCBlock = record    private      class function CreateBlockWithCFunc(const aTProc: TProc; const aType: TProcType): pointer; static;    public      class function CreateBlockWithProcedure(const aProc: TProc1): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc2): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc3): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc4): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc5): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc6): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc7): pointer; overload; static;   end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0430 \u0441 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c <code>SizeOf(pointer)<\/code>, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc3): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt3); end;<\/code><\/pre>\n<p>  <\/p>\n<p>CreateBlockWithCFunc \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">class function TObjCBlock.CreateBlockWithCFunc(const aTProc: TProc; const aType: TProcType): pointer; begin   result:= BlockObj.AddNewBlock(aTProc, aType); end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c. \u043c\u044b \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a BlockObj, singleton-\u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TObjCBlockList<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u043c \u044d\u0442\u0438\u043c \u0445\u043e\u0437\u044f\u0439\u0441\u0442\u0432\u043e\u043c \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u044e\u043d\u0438\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">  TBlockInfo = packed record      BlockStructure: Block_Literal;      LocProc: TProc;      ProcType: TProcType;   end;   PBlockInfo = ^TBlockInfo;    TObjCBlockList = class (TObject)   private     FBlockList: TArray&lt;TBlockInfo&gt;;     procedure ClearAllBlocks;   public     constructor Create;     destructor Destroy; override;     function AddNewBlock(const aTProc: TProc; const aType: TProcType): pointer;     function FindMatchingBlock(const aCurrBlock: pointer): integer;     procedure ClearBlock(const idx: integer);     property BlockList: TArray&lt;TBlockInfo&gt; read FBlockList ;   end;  var   BlockObj: TObjCBlockList;<\/code><\/pre>\n<p>  <\/p>\n<p>&quot;\u0421\u0435\u0440\u0434\u0446\u0435&quot; \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0431\u044c\u0435\u0442\u0441\u044f \u0442\u0443\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">function TObjCBlockList.AddNewBlock(const aTProc: TProc; const aType: TProcType): pointer; var   aDesc:  PBlock_Descriptor; const   BLOCK_HAS_COPY_DISPOSE = 1 shl 25; begin   \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448 \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u043b\u043e\u043a\u043e\u0432 \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438 \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c \u0435\u0433\u043e   SetLength(FBlockList, Length(FBlockList) + 1);   FillChar(FBlockList[High(FBlockList)], SizeOf(TBlockInfo), 0);   \/\/ \u042d\u0442\u043e \u044f \u0443\u0436\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u043b \u0432\u044b\u0448\u0435   FBlockList[High(FBlockList)].BlockStructure.Isa    := NSClassFromString ((StrToNSStr('NSBlock')                                        as ILocalobject).GetObjectID);   FBlockList[High(FBlockList)].BlockStructure.Invoke := @InvokeCallback;   \/\/ \u0421\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0447\u0442\u043e \u043d\u0430\u0448 \u0431\u043b\u043e\u043a \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0434\u0432\u0430 \u0434\u043e\u043f. \u0445\u0435\u043b\u043f\u0435\u0440\u0430,   \/\/ \u0434\u043b\u044f copy \u0438 displose. \u0417\u0430\u0447\u0435\u043c? \u041e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u0436\u0435.   FBlockList[High(FBlockList)].BlockStructure.Flags  := BLOCK_HAS_COPY_DISPOSE;   \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0442\u0438\u043f \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0438 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043d\u0435\u0433\u043e:   FBlockList[High(FBlockList)].ProcType              := aType;   FBlockList[High(FBlockList)].LocProc               := aTProc;    New(aDesc);   aDesc.Reserved       := 0;   aDesc.Size           := SizeOf(Block_Literal);   \/\/ \u0423\u043a\u0430\u0436\u0435\u043c \u0430\u0434\u0440\u0435\u0441\u0430 \u0445\u0435\u043b\u043f\u0435\u0440-\u0444\u0443\u043d\u043a\u0446\u0438\u0439:   aDesc.copy_helper    := @CopyCallback;   aDesc.dispose_helper := @DisposeCallback;   FBlockList[High(FBlockList)].BlockStructure.Descriptor := aDesc;    result:= @FBlockList[High(FBlockList)].BlockStructure; end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0443 \u0432\u043e\u0442, \u0432\u0441\u0451 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438. \u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u043d\u043a\u0438\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432. <\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c thread safety, \u0447\u0442\u043e\u0431\u044b \u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u0438\u0442\u0435\u0439. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434. <\/p>\n<p>  <\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c, \u0430 \u043a\u043e\u0433\u0434\u0430 \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043a\u043e\u043d\u0435\u0446 &quot;\u043f\u0440\u0438\u0431\u0438\u0442\u044c&quot; \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u043d\u0430\u043c\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u0442.\u0435. \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 <code>FBlockList<\/code>. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0432\u044b\u0437\u0432\u0430\u043b\u0430 \u043a\u043e\u043b\u043b\u0431\u0435\u043a, \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u044f\u0442\u044c: \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f \u0444\u0430\u0439\u043b, \u0431\u044b\u043b \u0432\u044b\u0437\u0432\u0430\u043d completion handler \u2013 \u0432\u0441\u0451, \u0434\u0435\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u044d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0442\u0430\u043a. \u0415\u0441\u0442\u044c \u0431\u043b\u043e\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0440\u0430\u0437; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <a href=\"https:\/\/developer.apple.com\/reference\/appkit\/nsimage\/1519860-imagewithsize\">imageWithSize:flipped:drawingHandler:<\/a> \u043a\u043b\u0430\u0441\u0441\u0430 <code>NSImage<\/code> \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0431\u043b\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443, \u0447\u0442\u043e, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435, \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0445\u043e\u0442\u044c \u043c\u0438\u043b\u043b\u0438\u043e\u043d \u0440\u0430\u0437. \u0412\u043e\u0442 \u0442\u0443\u0442-\u0442\u043e \u043d\u0430\u043c \u0438 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f <code>aDesc.dispose_helper := @DisposeCallback<\/code>. \u0412\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b <code>DisposeCallback<\/code> \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0431\u043b\u043e\u043a \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u0443\u0434\u0430\u043b\u044f\u0442\u044c.<\/p>\n<p>  <\/p>\n<h3 id=\"vishenka-na-torte\">\u0412\u0438\u0448\u0435\u043d\u043a\u0430 \u043d\u0430 \u0442\u043e\u0440\u0442\u0435<\/h3>\n<p>  <\/p>\n<p>\u0410 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0435 self-test \u043d\u0430\u043f\u0438\u0448\u0435\u043c, \u043f\u0440\u044f\u043c\u043e \u0432 \u0442\u043e\u043c \u0436\u0435 \u044e\u043d\u0438\u0442\u0435? \u0412\u0434\u0440\u0443\u0433 \u0447\u0442\u043e-\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0438\u043b\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 64 \u0431\u0438\u0442\u0430. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438, \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u044f\u0441\u044c \u043a Cocoa-\u043a\u043b\u0430\u0441\u0441\u0430\u043c? \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u0434\u0435\u043a\u043b\u0430\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 Delphi \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">  function imp_implementationWithBlock(block: id): pointer; cdecl;                     external libobjc name _PU + 'imp_implementationWithBlock';   function imp_removeBlock(anImp: pointer): integer; cdecl;                     external libobjc name _PU + 'imp_removeBlock';<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 C-\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0431\u043b\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u043a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442. \u0412\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u043e &quot;\u043f\u043e\u0434\u0447\u0438\u0449\u0430\u0435\u0442&quot; \u043f\u043e\u0442\u043e\u043c \u043f\u0430\u043c\u044f\u0442\u044c. \u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u043b\u043e\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 <code>imp_implementationWithBlock<\/code>, \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 \u0438 \u0441 \u0437\u0430\u043c\u0438\u0440\u0430\u043d\u0438\u0435\u043c \u0441\u0435\u0440\u0434\u0446\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0431\u043b\u043e\u043a. \u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u0441\u0451 \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u044c. \u0412\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u0435\u0440\u0432\u044b\u0439, <strong>\u043d\u0430\u0438\u0432\u043d\u044b\u0439<\/strong>:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">class procedure TObjCBlock.SelfTest; var   p: pointer;   test: NativeUint;   func : procedure ( p1, p2, p3, p4: pointer); cdecl; begin   test:= 0;   p:= TObjCBlock.CreateBlockWithProcedure(                           procedure (p1, p2, p3, p4: pointer)                           begin                             test:= NativeUint(p1) + NativeUint(p2) +                                    NativeUint(p3) + NativeUint(p4);                           end);   @func := imp_implementationWithBlock(p);   func(pointer(1), pointer(2),  pointer(3),  pointer(4));   imp_removeBlock(@func);   if test &lt;&gt; (1 + 2 + 3 + 4)     then raise Exception.Create('Objective-C code block self-test failed!'); end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438\u2026 \u0443\u043f\u0441. \u041f\u043e\u043f\u0430\u0434\u0430\u0435\u043c \u0432 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434: p1=1, p2=3, p3=4, p4=\u043c\u0443\u0441\u043e\u0440. What the \u2026? \u041a\u0442\u043e \u0441\u044a\u0435\u043b \u0434\u0432\u043e\u0439\u043a\u0443? \u0418 \u043f\u043e\u0447\u0435\u043c\u0443 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u043c\u0443\u0441\u043e\u0440? \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0434\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <code>imp_implementationWithBlock<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 trampoline, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a \u043a\u0430\u043a <code>IMP<\/code>. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <code>IMP<\/code> \u0432 Objective-C \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0432\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430, <code>(id self, SEL _cmd)<\/code>, \u0442.\u0435. \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043d\u0430 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440, \u0430 \u043a\u043e\u0434-\u0431\u043b\u043e\u043a \u0438\u043c\u0435\u0435\u0442 \u043b\u0438\u0448\u044c \u043e\u0434\u0438\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 trampoline \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432: \u0432\u0442\u043e\u0440\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442, <code>_cmd<\/code>, \u0432\u044b\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0441\u0442\u044c\u044e, \u043d\u0430 \u0435\u0433\u043e \u043c\u0435\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442, \u0430 \u0432\u043e\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 <code>NSBlock<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430, \u0432\u043e\u0442 \u0442\u0430\u043a, trampoline \u043f\u043e\u0434\u043a\u0440\u0430\u043b\u0441\u044f \u043d\u0435\u0437\u0430\u043c\u0435\u0442\u043d\u043e. \u041b\u0430\u0434\u043d\u043e, \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432\u0442\u043e\u0440\u043e\u0439, <strong>\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439<\/strong>:<\/p>\n<p>  <\/p>\n<pre><code class=\"delphi\">class procedure TObjCBlock.SelfTest; var   p: pointer;   test: NativeUint;   func : procedure ( p1, _cmd, p2, p3, p4: pointer); cdecl; begin   test:= 0;   p:= TObjCBlock.CreateBlockWithProcedure(                           procedure (p1, p2, p3, p4: pointer)                           begin                             test:= NativeUint(p1) + NativeUint(p2) +                                    NativeUint(p3) + NativeUint(p4);                           end);   @func := imp_implementationWithBlock(p);   \/\/ \u0414\u0430, _cmd \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d!   func(pointer(1), nil, pointer(2),  pointer(3),  pointer(4));   imp_removeBlock(@func);   if test &lt;&gt; (1 + 2 + 3 + 4)     then raise Exception.Create('Objective-C code block self-test failed!'); end;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0433\u043b\u0430\u0434\u043a\u043e \u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u043e\u0439 \u0441 \u0431\u043b\u043e\u043a\u0430\u043c\u0438. \u0426\u0435\u043b\u0438\u043a\u043e\u043c \u044e\u043d\u0438\u0442 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c <a href=\"http:\/\/www.tamos.com\/code\/Mac.CodeBlocks.pas\">\u0442\u0443\u0442<\/a> \u0438\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0438\u0436\u0435. \u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 (&quot;\u043b\u0430\u043c\u0435\u0440\u044b, \u0443 \u0432\u0430\u0441 \u0442\u0443\u0442 \u0442\u0435\u0447\u0435\u0442 \u043f\u0430\u043c\u044f\u0442\u044c&quot;) \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442\u0441\u044f. <\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043e\u0440\u0441-\u043a\u043e\u0434<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"delphi\">{*******************************************************} {                                                       } {     Implementation of Objective-C Code Blocks         } {                                                       } {       Copyright(c) 2017 TamoSoft Limited              } {                                                       } {*******************************************************}  { LICENSE:  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and\/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  You may not use the Software in any projects published under viral licenses, including, but not limited to, GNU GPL.  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE } \/\/USAGE EXAMPLE \/\/ \/\/    FSaveFile :=TNSSavePanel.Wrap(TNSSavePanel.OCClass.savePanel); \/\/    NSWin := WindowHandleToPlatform(Screen.ActiveForm.Handle).Wnd; \/\/    objc_msgSendP2( \/\/                   (FSaveFile as ILocalObject).GetObjectID, \/\/                   sel_getUid(PAnsiChar('beginSheetModalForWindow:completionHandler:')), \/\/                   (NSWin as ILocalObject).GetObjectID, \/\/                   TObjCBlock.CreateBlockWithProcedure( \/\/                          procedure (p1: NSInteger) \/\/                          begin \/\/                            if p1 = 0 \/\/                              then ShowMessage ('Cancel') \/\/                              else ShowMessage ('OK'); \/\/                           end) \/\/                          );  unit Mac.CodeBlocks;  interface  uses System.SysUtils, Macapi.ObjectiveC, Macapi.Foundation, Macapi.Helpers,      Macapi.ObjCRuntime, Macapi.CocoaTypes;  type    TProc1 = TProc;   TProc2 = TProc&lt;pointer&gt;;   TProc3 = TProc&lt;pointer, pointer&gt;;   TProc4 = TProc&lt;pointer, pointer, pointer&gt;;   TProc5 = TProc&lt;pointer, pointer, pointer, pointer&gt;;   TProc6 = TProc&lt;NSInteger&gt;;   TProc7 = TFunc&lt;NSRect, boolean&gt;;    TProcType = (ptNone, pt1, pt2, pt3, pt4, pt5, pt6, pt7);    TObjCBlock = record    private      class procedure SelfTest; static;      class function CreateBlockWithCFunc(const aTProc: TProc; const aType: TProcType): pointer; static;    public      class function CreateBlockWithProcedure(const aProc: TProc1): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc2): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc3): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc4): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc5): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc6): pointer; overload; static;      class function CreateBlockWithProcedure(const aProc: TProc7): pointer; overload; static;   end;  implementation    function imp_implementationWithBlock(block: id): pointer; cdecl;                     external libobjc name _PU + 'imp_implementationWithBlock';   function imp_removeBlock(anImp: pointer): integer; cdecl;                     external libobjc name _PU + 'imp_removeBlock';  type    Block_Descriptor = packed record     Reserved: NativeUint;     Size: NativeUint;     copy_helper: pointer;     dispose_helper: pointer;   end;   PBlock_Descriptor = ^Block_Descriptor;    Block_Literal = packed record     Isa: pointer;     Flags: integer;     Reserved: integer;     Invoke: pointer;     Descriptor: PBlock_Descriptor;   end;   PBlock_Literal = ^Block_Literal;    TBlockInfo = packed record      BlockStructure: Block_Literal;      LocProc: TProc;      ProcType: TProcType;   end;   PBlockInfo = ^TBlockInfo;    TObjCBlockList = class (TObject)   private     FBlockList: TArray&lt;TBlockInfo&gt;;     procedure ClearAllBlocks;   public     constructor Create;     destructor Destroy; override;     function AddNewBlock(const aTProc: TProc; const aType: TProcType): pointer;     function FindMatchingBlock(const aCurrBlock: pointer): integer;     procedure ClearBlock(const idx: integer);     property BlockList: TArray&lt;TBlockInfo&gt; read FBlockList ;   end;  var   BlockObj: TObjCBlockList;  function InvokeCallback(aNSBlock, p1, p2, p3, p4: pointer): pointer; cdecl; var   i: integer;   aRect: NSRect; begin   result:= nil;   if Assigned(BlockObj) then   begin     TMonitor.Enter(BlockObj);     try       i:= BlockObj.FindMatchingBlock(aNSBlock);       if i &gt;= 0 then       begin         case  BlockObj.BlockList[i].ProcType of           TProcType.pt1: TProc1(BlockObj.BlockList[i].LocProc)();           TProcType.pt2: TProc2(BlockObj.BlockList[i].LocProc)(p1);           TProcType.pt3: TProc3(BlockObj.BlockList[i].LocProc)(p1, p2);           TProcType.pt4: TProc4(BlockObj.BlockList[i].LocProc)(p1, p2, p3);           TProcType.pt5: TProc5(BlockObj.BlockList[i].LocProc)(p1, p2, p3, p4);           TProcType.pt6: TProc6(BlockObj.BlockList[i].LocProc)(NSinteger(p1));           TProcType.pt7:           begin             aRect.origin.x   := CGFloat(p1);             aRect.origin.y   := CGFloat(p2);             aRect.size.width := CGFloat(p3);             aRect.size.height:= CGFloat(p4);             result:= pointer(TProc7(BlockObj.BlockList[i].LocProc)(aRect));           end;         end;       end;     finally       TMonitor.Exit(BlockObj);     end;   end; end;  procedure DisposeCallback(aNSBlock: pointer) cdecl; var   i: integer; begin   if Assigned(BlockObj) then   begin     TMonitor.Enter(BlockObj);     try       i:= BlockObj.FindMatchingBlock(aNSBlock);       if i &gt;= 0         then BlockObj.ClearBlock(i);     finally       TMonitor.Exit(BlockObj);     end;   end;   TNSObject.Wrap(aNSBlock).release; end;  procedure CopyCallback(scr, dst: pointer) cdecl; begin  \/\/ end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc1): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt1); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc2): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt2); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc3): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt3); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc4): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt4); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc5): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt5); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc6): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt6); end;  class function TObjCBlock.CreateBlockWithProcedure(const aProc: TProc7): pointer; begin   result:= CreateBlockWithCFunc(TProc(aProc), TProcType.pt7); end;  class function TObjCBlock.CreateBlockWithCFunc(const aTProc: TProc; const aType: TProcType): pointer; begin   result:= nil;   if Assigned(BlockObj) then   begin     TMonitor.Enter(BlockObj);     try       result:= BlockObj.AddNewBlock(aTProc, aType);     finally       TMonitor.Exit(BlockObj);     end;   end; end;  class procedure TObjCBlock.SelfTest; var   p: pointer;   test: NativeUint;   \/\/ Yes, _cmd is ignored!   func : procedure ( p1, _cmd, p2, p3, p4: pointer); cdecl; begin   test:= 0;   p:= TObjCBlock.CreateBlockWithProcedure(                           procedure (p1, p2, p3, p4: pointer)                           begin                             test:= NativeUint(p1) + NativeUint(p2) +                                    NativeUint(p3) + NativeUint(p4);                           end);   @func := imp_implementationWithBlock(p);   \/\/ Yes, _cmd is ignored!   func(pointer(1), nil, pointer(2),  pointer(3),  pointer(4));   imp_removeBlock(@func);   if test &lt;&gt; (1 + 2 + 3 + 4)     then raise Exception.Create('Objective-C code block self-test failed!'); end;  {TObjCBlockList}  constructor TObjCBlockList.Create; begin   inherited; end;  destructor TObjCBlockList.Destroy; begin   TMonitor.Enter(Self);   try     ClearAllBlocks;   finally     TMonitor.Exit(Self);   end;   inherited Destroy; end;  procedure TObjCBlockList.ClearBlock(const idx: integer); begin   Dispose(FBlockList[idx].BlockStructure.Descriptor);   FBlockList[idx].BlockStructure.isa:= nil;   FBlockList[idx].LocProc:= nil;   Delete(FBlockList, idx, 1); end;  function TObjCBlockList.AddNewBlock(const aTProc: TProc; const aType: TProcType): pointer; var   aDesc:  PBlock_Descriptor; const   BLOCK_HAS_COPY_DISPOSE = 1 shl 25; begin   SetLength(FBlockList, Length(FBlockList) + 1);   FillChar(FBlockList[High(FBlockList)], SizeOf(TBlockInfo), 0);    FBlockList[High(FBlockList)].BlockStructure.Isa    := NSClassFromString ((StrToNSStr('NSBlock') as ILocalobject).GetObjectID);   FBlockList[High(FBlockList)].BlockStructure.Invoke := @InvokeCallback;   FBlockList[High(FBlockList)].BlockStructure.Flags  := BLOCK_HAS_COPY_DISPOSE;   FBlockList[High(FBlockList)].ProcType              := aType;   FBlockList[High(FBlockList)].LocProc               := aTProc;    New(aDesc);   aDesc.Reserved       := 0;   aDesc.Size           := SizeOf(Block_Literal);   aDesc.copy_helper    := @CopyCallback;   aDesc.dispose_helper := @DisposeCallback;   FBlockList[High(FBlockList)].BlockStructure.Descriptor := aDesc;    result:= @FBlockList[High(FBlockList)].BlockStructure; end;  procedure TObjCBlockList.ClearAllBlocks(); var   i: integer; begin   for i := High(FBlockList) downto Low(FBlockList) do      ClearBlock(i); end;  function TObjCBlockList.FindMatchingBlock(const aCurrBlock: pointer): integer; var   i: integer; begin   result:= -1;   if aCurrBlock &lt;&gt; nil then   begin     for i:= Low(FBlockList) to High(FBlockList) do     begin       if FBlockList[i].BlockStructure.Descriptor = PBlock_Literal(aCurrBlock).Descriptor         then Exit(i);     end;   end; end;  initialization   BlockObj:=TObjCBlockList.Create;   TObjCBlock.SelfTest;  finalization   FreeAndNil(BlockObj);  end.<\/code><\/pre>\n<\/div>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/325204\/\"> https:\/\/habrahabr.ru\/post\/325204\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"http:\/\/www.tamos.com\/temp\/bridge.jpg\" alt=\"image\"\/><\/p>\n<p>  <\/p>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0441\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D1%82%D1%91%D0%BD%D0%BA%D0%B0\">\u043c\u0435\u0442\u043e\u0434 \u0443\u0442\u0435\u043d\u043a\u0430<\/a> (rubber duck debugging). \u0421\u0443\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u0441\u0435\u0441\u0442\u044c \u0432 \u0432\u0430\u043d\u043d\u0443\u044e, \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u0438\u0442\u044c\u0441\u044f, \u043f\u043e\u0441\u0430\u0434\u0438\u0442\u044c \u043d\u0430 \u0432\u043e\u0434\u0443 \u0438\u0433\u0440\u0443\u0448\u0435\u0447\u043d\u043e\u0433\u043e \u0443\u0442\u0435\u043d\u043a\u0430, \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0435\u043c\u0443 \u0441\u0443\u0442\u044c \u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438. \u0418, \u0447\u0443\u0434\u0435\u0441\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u0441\u043b\u0435 \u0442\u0430\u043a\u043e\u0439 \u0431\u0435\u0441\u0435\u0434\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f. <\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/habrahabr.ru\/post\/319922\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435<\/a>, \u0433\u0434\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 <a href=\"http:\/\/www.tamos.com\/products\/wifi-site-survey\/\">TamoGraph Site Survey<\/a> \u0434\u043b\u044f macOS, \u0432 \u0440\u043e\u043b\u0438 \u0443\u0442\u0435\u043d\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0441\u0430\u043c \u0425\u0430\u0431\u0440: \u044f \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 code blocks \u0438\u0437 Objective-C \u0432 Delphi. \u0418 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e! \u041f\u0440\u0438\u0448\u043b\u043e \u043f\u0440\u043e\u0441\u0432\u0435\u0442\u043b\u0435\u043d\u0438\u0435, \u0438 \u0432\u0441\u0451 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u041e \u0445\u043e\u0434\u0435 \u043c\u044b\u0441\u043b\u0435\u0439 \u0438 \u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u044f \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-284180","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=284180"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/284180\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=284180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=284180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=284180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}