Sign in Join
Wiki copytemporary

FPC PasCocoa: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: FPC PasCocoa

OldNewLine
1+*(macOS only)*
2+
3+*(iOS only)*
4+
5+## Introduction
6+
7+A large and growing fraction of the macOS system frameworks are written in Objective-C and only offer an Objective-C interface. This makes it unwieldy to use them directly from other programming languages. The Objective-C run time library, which is used for everything from defining classes to sending messages (calling methods), has a public procedural C interface however, which makes it possible to integrate other languages directly with Objective-C code. Two general approaches exist.
8+
9+The first approach is to create a *bridge*. In this case calls to the Objective-C run time helpers are wrapped in host language constructs and helpers. The host language itself is generally not modified. A number of examples of Cocoa bridges can be found at <http://www.cocoadev.com/index.pl?CocoaBridges>.
10+
11+A second approach is to extend the host language so that it can directly interface with Objective-C code using new language constructs. A list of such language extensions can be found at <http://www.cocoadev.com/index.pl?CocoaLanguages>. As far as Pascal is concerned, a first proposal for Objective-Pascal was made by [MetroWerks in 1997](http://www.pascal-central.com/cwpascal.html#Extensions%20providing%20compatibili). Based on this preliminary proposal (it was never finalised nor implemented by MetroWerks) and on evolutions of the Object Pascal language since that time, we have designed our own Objective-Pascal dialect.
12+
13+## PasCocoa wrappers
14+
15+Before the compiler supported Objective-Pascal (as described below), the primary way for Objective-C interfacing was through ObjFPC wrapper classes. This process is described on the [[PasCocoa]] page, and falls in the *bridge* approach mentioned above. This approach is no longer recommended nor maintained.
16+
17+## Objective-Pascal FPC Compiler
18+
19+All Objective-Pascal support is available in FPC 2.6.0 and later.
20+
21+For an overview of some conceptual differences between Objective-Pascal and Object Pascal on the one hand, and between Objective-Pascal and Objective-C on the other hand, see [[FPC PasCocoa/Differences|FPC PasCocoa differences]].
22+
23+## Syntax (implemented)
24+
25+### Enabling Objective-C/Objective-Pascal
26+
27+The compiler has mode switches to enable the use of Objective-C-related constructs. To enabled Objective-C 1.0 language features, either add *{\$modeswitch objectivec1}* to a source file, or using the *-Mobjectivec1* command line switch. Similarly, for Objective-C 2.0 language features use *{\$modeswitch objectivec2}* resp. *-Mobjectivec2* (this automatically also enables Objective-C 1.0 features). Note that in the latter case, the resulting program may only work on Leopard 10.5 and later. Due to these being mode switches rather than actual syntax modes, they can be used in combination with every general syntax mode (fpc, objfpc, tp, delphi, macpas).
28+
29+Note that mode switches are reset when the general syntax mode is changed using, e.g., *{\$mode objfpc}*. So if you have such a statement in a unit, compiling it with *-Mobjectivec1* will not change anything. You will have to add *{\$modeswitch objectivec1}* in the source code after the *{\$mode objfpc}* in that case.
30+
31+Whether or not the compiler has support for Objective-C-related constructs can be checked using *{\$ifdef FPC_HAS_FEATURE_OBJECTIVEC1}*. There will be no separate switches when new Objective-C-related features are implemented. Since all this works happens in FPC trunk, simply expect that people are using the latest version available.
32+
33+### Selectors
34+
35+To declare a selector for a method, use the *objcselector()* statement. It returns a value of the type *objc.SEL*. It accepts one parameter, which can either be a constant string representing an Objective-C method name, or a method of an Objective-C class.
36+
37+``` pascal
38+{$modeswitch objectivec1}
39+var
40+ a: SEL;
41+begin
42+ a:=objcselector('initiWithWidth:andHeight:');
43+ a:=objcselector('myMethod');
44+end.
45+```
46+
47+### Method declaration
48+
49+In general methods are declared in the same way as in Object Pascal, with the exception that each objcclass method must also have a messaging name specified:
50+
51+``` pascal
52+NSSomeObject = objcclass(NSObject)
53+ procedure method(params: Integer); message 'method:';
54+ class procedure classmethod(para: char); override; // "message 'classmethod:'" not required, compiler will get this from the parent class
55+end;
56+```
57+
58+Every objcclass/objcprotocol/objccategory method must be associated with an Objective-C message name, a.k.a. *selector*. This can happen in two different ways:
59+
60+- an inherited method, an implemented protocol method or a method reintroduced by a category will automatically use the message name of the inherited/implemented/reintroduced method. If an explicit message name is specified, it must match the message name specified for the corresponding method.
61+- in other cases, the *message* keyword must be used, followed by a constant string that contains the selector name.
62+
63+Instance and class methods correspond respectively to methods preceded with "-" and "+" in Objective-C. Furthermore, every method is by definition *virtual* in Objective-C/Pascal.
64+
65+**Note:** it's common for Objective-C to start method names with a lower case character.
66+
67+### Class declaration
68+
69+#### Regular declaration/definition
70+
71+To declare an Objective-C class, use the keyword *objcclass*. Objective-C classes must be declared like regular Object Pascal types in a *type* block:
72+
73+``` pascal
74+type
75+ ObjCClassName = objcclass [external [name 'ExternalClassName']] [(ObjCSuperClassName|ProtocolName [, ProtocolName, ProtocolName])]
76+ [private, protected, public]
77+ [variables declarations]
78+ [method declarations]
79+end;
80+```
81+
82+- *objcclass*: defines an Objective-C class type declaration
83+- *external*: many Objective-C classes are implemented in external frameworks, such as Cocoa. The *external* modifiers enables you to declare such external classes for use in Pascal code. It is possible to specify a different external name for the class than the identifier used in Pascal code, because the duplicate identifier rules in Objective-C are laxer than those of Pascal (e.g., there are both a class and a protocol called *NSObject* in Cocoa, so one of the two has to be renamed in Pascal)
84+- ObjCSuperClassName: defines parent (or super) class for the class. If name is not specified, the class defines a new root class. See [[FPC PasCocoa/Differences|no unique root class]] for more information.
85+
86+For example:
87+
88+``` pascal
89+// NSView is an external class, declared in some external framework
90+// External classes from Apple's framework
91+// have all fields in private sections
92+NSView = objcclass external (NSResponder)
93+private
94+ _subview : id; // private field
95+public
96+ function initWithFrame(rect : NSRect): id; message 'initWithFrame:';
97+ procedure addSubview(aview: NSView); message 'addSubview:';
98+ procedure setAutoresizingMask(mask: NSUInteger); message 'setAutoresizingMask:';
99+ procedure setAutoresizesSubviews(flag: LongBool); message 'setAutoresizesSubviews:';
100+ procedure drawRect(dirtyRect: NSRect); message 'drawRect:';
101+end;
102+
103+// MyView is a locally implemented class
104+// that should be declared in the local unit
105+// * drawRect_ method is overriden (the 'message' of the inherited method will be reused)
106+// * customMessage_ is a newly added method
107+// * data is a newly added field
108+MyView = objcclass(MSView)
109+public
110+ data : Integer;
111+ procedure customMessage(dirtyRect: NSRect); message 'customMessage';
112+ procedure drawRect(dirtyRect: NSRect); override;
113+end;
114+
115+...
116+procedure MyView.customMessage(dirtyRect: NSRect);
117+begin
118+end;
119+
120+procedure MyView.drawRect(dirtyRect: NSRect);
121+begin
122+end;
123+```
124+
125+#### Formal declaration
126+
127+In Objective-C, a class can also be declared formally using the *[@class SomeClass](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html%23//apple_ref/doc/uid/TP30001163-CH12-SW1)* syntax. This is called a *forward declaration* in Objective-C, but because this term has a different meaning in Pascal, we have termed this a *formal declaration* in Objective-Pascal.
128+
129+A formal declaration of an *objcclass* instructs the compiler to assume that somewhere, there is a complete definition of this *objcclass* (including fields, methods, etc), but that it is not in this unit. The practical upshot is that it is possible to use such a formal *objcclass* type for parameter types, field types, function result types and variable types, but that it is not possible to inherit from them, to send any messages to such instances, nor to access any fields (since the compiler does not know the full definition).
130+
131+The compiler will automatically resolve any uses of formal *objcclass*es to the real declaration when this real declaration is also in scope. Hence, as soon as the unit containing the real declaration is added to the uses clause, the aforementioned restrictions no longer apply and the compiler will treat the occurrences of the formal *objcclass* type the same as the actual type.
132+
133+To declare a *formal objcclass*, use the following syntax:
134+
135+``` pascal
136+type
137+ // note:
138+ // * no inheritance is specified
139+ // * the external name (if any) must match the external name of any real definition
140+ // to which this formal definition resolves later on
141+ MyExternalClass = objcclass external;
142+```
143+
144+Example:
145+
146+``` pascal
147+unit ContainerClass;
148+
149+{$mode objfpc}
150+{$modeswitch objectivec1}
151+
152+interface
153+
154+type
155+ // Formal declaration of MyItemClass, which is defined in another unit
156+ MyItemClass = objcclass external;
157+
158+ MyContainerClass = objcclass
159+ private
160+ item: MyItemClass;
161+ public
162+ function getItem: MyItemClass; message 'getItem';
163+ end;
164+
165+implementation
166+
167+ function MyContainerClass.getItem: MyItemClass;
168+ begin
169+ // we cannot send any message to item, but
170+ // we can use it in assignments
171+ result:=item;
172+ end;
173+
174+end.
175+
176+// ======================
177+// ======================
178+
179+unit ItemClass;
180+
181+{$mode objfpc}
182+{$modeswitch objectivec1}
183+
184+interface
185+
186+type
187+ // the actual definition of MyItemClass
188+ MyItemClass = objcclass(NSObject)
189+ private
190+ content : longint;
191+ public
192+ function initWithContent(c: longint): MyItemClass; message 'initWithContent:';
193+ function getContent: longint; message 'getContent';
194+ end;
195+
196+implementation
197+
198+ function MyItemClass.initWithContent(c: longint): MyItemClass;
199+ begin
200+ content:=c;
201+ result:=self;
202+ end;
203+
204+ function MyItemClass.getContent: longint;
205+ begin
206+ result:=content;
207+ end;
208+
209+end.
210+
211+// ======================
212+// ======================
213+
214+Program test;
215+
216+{$mode objfpc}
217+{$modeswitch objectivec1}
218+
219+// regardless of the order of the units in the uses-clause, as soon as
220+// ItemClass is used then the full declaration of MyItemClass is in
221+// scope and all uses of the formal declaration are replaced by the
222+// actual declaration
223+uses
224+ ItemClass, ContainerClass;
225+
226+var
227+ c: MyContainerClass;
228+ l: longint;
229+begin
230+ c:=MyContainerClass.alloc.init;
231+ ...
232+ // even though MyContainerClass.getItem returns a "formal" MyItemClass,
233+ // the fact that the real declaration is in scope means that it can be
234+ // used as a regular MyItemClass instance
235+ l:=c.getItem.getContent;
236+end.
237+```
238+
239+#### Objective-Pascal class references
240+
241+Just like in Object Pascal, it is possible to declare a class reference type for an Objective-Pascal class. In Objective-C, these are called meta-classes and are represented by the *pobjc_class* type. If you wish to mix code using the *pobjc_class* type and the Pascal syntax for class references, you have to use typecasts, as shown below.
242+
243+``` pascal
244+{$mode objfpc}
245+{$modeswitch objectivec1}
246+
247+program Test;
248+
249+type
250+ TMyClass = objcclass (NSObject)
251+ end;
252+ TMyClassMeta = class of TMyClass; // declare the meta-class type for dynamic allocation
253+
254+var
255+ theClass: pobjc_class;
256+begin
257+ theClass := TMyClass.classClass; // get the meta-class reference for TMyClass; could
258+ TMyClassMeta(theClass).alloc.init; // cast theClass as TMyClassMeta and send messages as normal
259+end.
260+```
261+
262+### Protocol declaration
263+
264+An Objective-C Protocol is pretty much the same as an *interface* in Object Pascal: it lists a number of methods to be implemented by classes that conform to the protocol. The only difference is that protocol methods can be *optional*. Moreover, unlike in Object Pascal, a protocol can inherit from multiple other protocols:
265+
266+``` pascal
267+type
268+ ObjCProtocolName = objcprotocol [external [name 'ExternalClassName']] [(ObjCParentProtocol1[, ObjCParentProtocol2, ...])]
269+ [required, optional]
270+ [method declarations]
271+end;
272+```
273+
274+- *objcprotocol*: defines an Objective-C protocol type declaration
275+- *external*: same as with objcclass
276+- *ObjCParentProtocols*: the protocols this protocol inherits from (so a class conforming to this protocol, will also have to implement all methods from those other protocols)
277+- *required, optional*: If nothing is specified, the default is *required*. *optional* methods do not have to be implemented by classes conforming to this protocol.
278+
279+Example:
280+
281+``` pascal
282+type
283+ MyProtocol = objccprotocol
284+ // default is required
285+ procedure aRequiredMethod; message 'aRequiredMethod';
286+ optional
287+ procedure anOptionalMethodWithPara(para: longint); message 'anOptionalMethodWithPara:';
288+ procedure anotherOptionalMethod; message 'anotherOptionalMethod';
289+ required
290+ function aSecondRequiredMethod: longint; message 'aSecondRequiredMethod';
291+ end;
292+
293+ MyClassImplementingProtocol = objcclass(NSObject,MyProtocol)
294+ // the "message 'xxx'" modifiers can be repeated, but this is not required
295+ procedure aRequiredMethod;
296+ procedure anOptionalMethodWithPara(para: longint);
297+ function aSecondRequiredMethod: longint;
298+ end;
299+```
300+
301+Similar to *objcclass*es, *objcprotocol*s can be external in case they are implemented in e.g. the Cocoa framework.
302+
303+### Category declaration
304+
305+An Objective-C category is similar to a *class helper* in Object Pascal: it allows adding methods to an existing class, without inheriting from that class. In Objective-C, this functionality goes even further: multiple categories can be in scope at the same time for a particular class, and a category can also replace existing methods in another class rather than only add new ones. Since all methods are virtual in Objective-C, this also means that this method changes for all classes that inherit from the class in which the method was replaced (unless they override it). An Objective-C category can also implement protocols.
306+
307+Note that a category cannot extend another category. Furthermore, if two categories add/replace a method with the same selector in the same class, it is undefined which method will actually be called at run time. This would depend on the order in which the categories are registered with the Objective-C run time.
308+
309+``` pascal
310+type
311+ ObjCCategoryName = objccategory [external [name 'ExternalCategoryName']] (ExtendedObjCClass[,ObjCProtocol1, ObjCProtocol2, ...])
312+ [method declarations]
313+end;
314+```
315+
316+- *objccategory*: defines an Objective-C category type declaration
317+- *external*: same as with objcclass. As of Objective-C 2.0, the name of a category is optional. *Not yet implemented*: to declare an external category without a name, use an empty string.
318+- *method declarations*: the methods that this category adds or replaces in the extended class. These can be both class and instance methods. Note that when replacing a method in the extended class, you must mark this new method as *reintroduce*. The reason that we do not use *override* here, is that the method is really replaced in the original class. This means, e.g., that if you call *inherited* from the new method, that you will call this method in the parent class of the extended class, and not the replaced method. The replaced method is "lost".
319+- *ObjCParentProtocols*: the protocols this category implements. The category will have to implement all required methods from these protocols.
320+
321+Example:
322+
323+``` pascal
324+type
325+ MyProtocol = objcprotocol
326+ procedure protocolmethod; message 'protocolmethod';
327+ end;
328+
329+ MyCategory = objccategory(NSObject,MyProtocol)
330+ // method replaced in NSObject. This means that every objcclass that does not
331+ // override the hash function will now use this method instead.
332+ function hash: cuint; reintroduce;
333+
334+ // we have to implement this method, since we declare that we implement the
335+ // MyProtocol protocol. This method is added to NSObject afterwards.
336+ procedure protocolmethod;
337+
338+ // a random class methods added to NSObject
339+ class procedure newmethod; message 'newmethod';
340+ end;
341+```
342+
343+Similar to *objcclass*es, *objccategory*s can be external in case they are implemented in e.g. the Cocoa framework.
344+
345+### The *id* type
346+
347+The *id* type is special in Objective-C/Pascal. It is assignment-compatible with instances of every objcclass and objcprotocol type, in two directions. This means that you can assign variables of any objcclass/objcprotocol type to a variable of the type *id*, but also that you can assign these *id* variables to variables of any particular objcclass/objcprotocol type. In neither case an explicit typecast is required.
348+
349+Furthermore, it is possible [[FPC PasCocoa/Differences|to call any Objective-C method declared]] in an objcclass or objccategory that's in scope using an *id*-typed variable. If, at run time, the objcclass instance stored in the *id*-typed variable does not respond to the sent message, the program will terminate with a run time error.
350+
351+When there are multiple methods with the same Pascal identifier, the compiler will use the standard overload resolution logic to pick the most appropriate method. In this process, it will behave as if all objcclass/objccategory methods in scope have been declared as global procedures/functions with the *overload* specifier. If the compiler cannot determine which overloaded method to call, it will print an error. If you compile with -vh, it will print a list of all methods that could be used to implement the call when it cannot determine the appropriate overloaded method. In this case, you will have to use an explicit type cast to clarify the class type from which you wish to call a method.
352+
353+### Fast enumeration
354+
355+*Fast enumeration* is a convention that enables enumerating the elements in a Cocoa container class in a generic yet fast way. The syntax used for this feature is the *for-in* construct, both in Objective-C and in Objective-Pascal. This feature behaves identically in both languages. It requires the Objective-C 2.0 mode switch to be activated.
356+
357+Example:
358+
359+``` pascal
360+{$mode delphi}
361+{$modeswitch objectivec2}
362+
363+uses
364+ CocoaAll;
365+
366+var
367+ arr: NSMutableArray;
368+ element: NSString;
369+ pool: NSAutoreleasePool;
370+ i: longint;
371+begin
372+ pool:=NSAutoreleasePool.alloc.init;
373+ arr:=NSMutableArray.arrayWithObjects(
374+ NSSTR('One'),
375+ NSSTR('Two'),
376+ NSSTR('Three'),
377+ NSSTR('Four'),
378+ NSSTR('Five'),
379+ NSSTR('Six'),
380+ NSSTR('Seven'),
381+ nil);
382+
383+ i:=0;
384+ for element in arr do
385+ begin
386+ inc(i);
387+ if i=2 then
388+ continue;
389+ if i=5 then
390+ break;
391+ if i in [2,5..10] then
392+ halt(1);
393+ NSLog(NSSTR('element: %@'),element);
394+ end;
395+ pool.release;
396+end.
397+```
398+
399+## Syntax (proposed)
400+
401+## todo:
402+
403+a\) how to declare a constant NSString/CFString in Pascal (the @"somestring" from Objective-C)
404+
405+-- the dollar sign could work... ex. \$theString
406+
407+## Objective Pascal Examples
408+
409+### Application with one menu item
410+
411+Please note, that for the creation of the menu, the application must be located in the application bundle. Lazarus may create the bundle for you.
412+
413+``` pascal
414+ program project1;
415+
416+ {$mode objfpc}{$H+}
417+ {$modeswitch objectivec1}
418+
419+ uses
420+ CocoaAll;
421+
422+ type
423+ { MyCallback }
424+ MyCallback = objcclass(NSObject)
425+ public
426+ procedure haltMenuEvent(sender: id); message 'haltMenuEvent:';
427+ end;
428+
429+ var
430+ pool : NSAutoreleasePool;
431+ filemenu : NSMenu;
432+ subitem : NSMenuItem;
433+ app : NSApplication;
434+ callback : MyCallback;
435+
436+ function NSStr(const s: AnsiString): NSString;
437+ begin
438+ if s='' then Result:=NSString.alloc.init
439+ else Result:=NSString.alloc.initWithCString(@s[1]);
440+ end;
441+
442+ { MyCallback }
443+
444+ procedure MyCallback.haltMenuEvent(sender:id);
445+ begin
446+ WriteLn('HALT!');
447+ app.stop(self);
448+ end;
449+
450+ procedure initMenus;
451+ var
452+ root : NSMenu;
453+ rootitem : NSMenuItem;
454+ begin
455+ root:=NSMenu.alloc.init;
456+ rootitem:=root.addItemWithTitle_action_keyEquivalent(NSStr(''), nil, NSStr(''));
457+ filemenu:=NSMenu.alloc.initWithTitle(NSStr('File'));
458+ rootitem.setSubmenu(filemenu);
459+ rootitem.setEnabled(true);
460+ subitem:=filemenu.addItemWithTitle_action_keyEquivalent(NSStr('Halt'), nil, NSStr(''));
461+ subitem.setEnabled(true);
462+ app.setMainMenu(root);
463+ end;
464+
465+ procedure InitCallback;
466+ begin
467+ callback:=MyCallback.alloc;
468+ subitem.setAction(ObjCSelector(callback.haltMenuEvent));
469+ subitem.setTarget(callback);
470+ end;
471+
472+ begin
473+ pool:=NSAutoreleasePool.alloc.init;
474+ app:=NSApplication.sharedApplication;
475+ initMenus;
476+ initCallback;
477+ app.run;
478+ pool.release;
479+ end.
480+```
481+
482+### Application with a single window and no menus
483+
484+``` pascal
485+program simplewindow;
486+
487+{$mode objfpc}{$H+}
488+{$modeswitch objectivec2}
489+
490+uses
491+ CocoaAll;
492+
493+var
494+ appName: NSString;
495+ window: NSWindow;
496+ pool: NSAutoreleasePool;
497+begin
498+ pool := NSAutoreleasePool.new;
499+ NSApp := NSApplication.sharedApplication;
500+ NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
501+ appName := NSProcessInfo.processInfo.processName;
502+ window := NSWindow.alloc.initWithContentRect_styleMask_backing_defer(NSMakeRect(0, 0, 200, 200),
503+ NSTitledWindowMask, NSBackingStoreBuffered, False).autorelease;
504+ window.center;
505+ window.setTitle(appName);
506+ window.makeKeyAndOrderFront(nil);
507+ NSApp.activateIgnoringOtherApps(true);
508+ NSApp.run;
509+end.
510+```
511+
512+### Application with a simple window and menus
513+
514+``` pascal
515+program simplewindow;
516+
517+{$mode objfpc}{$H+}
518+{$modeswitch objectivec2}
519+
520+uses
521+ CocoaAll;
522+
523+var
524+ menubar: NSMenu;
525+ appMenu: NSMenu;
526+ appName: NSString;
527+ quitMenuItem: NSMenuItem;
528+ appMenuItem: NSMenuItem;
529+ quitTitle: NSString;
530+ window: NSWindow;
531+ pool: NSAutoreleasePool;
532+begin
533+ pool := NSAutoreleasePool.new;
534+ NSApp := NSApplication.sharedApplication;
535+ NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
536+ menubar := NSMenu.alloc.autorelease;
537+ appMenuItem := NSMenuItem.alloc.autorelease;
538+ menubar.addItem(appMenuItem);
539+ NSApp.setMainMenu(Menubar);
540+ appMenu := NSMenu.new.autorelease;
541+ appName := NSProcessInfo.processInfo.processName;
542+ quitTitle := NSSTR('Quit ').stringByAppendingString(appName);
543+ quitMenuItem := NSMenuItem.alloc.initWithTitle_action_keyEquivalent(quitTitle,
544+ sel_registerName(PChar('terminate:')),
545+ NSSTR('q'));
546+ appMenu.addItem(quitMenuItem);
547+ appMenuitem.setSubmenu(appMenu);
548+ window := NSWindow.alloc.initWithContentRect_styleMask_backing_defer(NSMakeRect(0, 0, 200, 200),
549+ NSTitledWindowMask, NSBackingStoreBuffered, False).autorelease;
550+ window.center;
551+ window.setTitle(appName);
552+ window.makeKeyAndOrderFront(nil);
553+ NSApp.activateIgnoringOtherApps(true);
554+ NSApp.run;
555+end.
556+```
557+
558+### Simple window and a non-editable text field inside it
559+
560+This shows how to create and position a sub-control in a window:
561+
562+``` pascal
563+program simplewindow;
564+
565+{$mode objfpc}{$H+}
566+{$modeswitch objectivec2}
567+
568+uses
569+ CocoaAll;
570+
571+var
572+ appName: NSString;
573+ window: NSWindow;
574+ pool: NSAutoreleasePool;
575+ lText: NSTextField;
576+begin
577+ // Autorelease pool, app and window creation
578+ pool := NSAutoreleasePool.new;
579+ NSApp := NSApplication.sharedApplication;
580+ NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
581+ appName := NSProcessInfo.processInfo.processName;
582+ window := NSWindow.alloc.initWithContentRect_styleMask_backing_defer(NSMakeRect(0, 0, 200, 200),
583+ NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask,
584+ NSBackingStoreBuffered, False).autorelease;
585+
586+ // text label
587+ lText := NSTextField.alloc.initWithFrame(NSMakeRect(50, 50, 200, 50)).autorelease;
588+ lText.setBezeled(False);
589+ lText.setDrawsBackground(False);
590+ lText.setEditable(False);
591+ lText.setSelectable(False);
592+ lText.setStringValue(NSSTR('NSTextField'));
593+ window.contentView.addSubview(lText);
594+
595+ // Window showing and app running
596+ window.center;
597+ window.setTitle(appName);
598+ window.makeKeyAndOrderFront(nil);
599+ NSApp.activateIgnoringOtherApps(true);
600+ NSApp.run;
601+end.
602+```
603+
604+### Button which handles an event
605+
606+This event shows how to make a button that responds to clicking on it.
607+
608+``` pascal
609+program simplewindow;
610+
611+{$mode objfpc}{$H+}
612+{$modeswitch objectivec1}
613+
614+uses
615+ CocoaAll;
616+
617+type
618+ { TMyDelegate }
619+ TMyDelegate = objcclass(NSObject)
620+ public
621+ procedure HandleButtonClick(sender: id); message 'HandleButtonClick:';
622+ end;
623+
624+var
625+ appName: NSString;
626+ window: NSWindow;
627+ pool: NSAutoreleasePool;
628+ lText: NSTextField;
629+ lButton: NSButton;
630+ lDelegate: TMyDelegate;
631+
632+procedure TMyDelegate.HandleButtonClick(sender: id);
633+begin
634+ lText.setStringValue(NSSTR('New text!'));
635+end;
636+
637+begin
638+ // Autorelease pool, app and window creation
639+ pool := NSAutoreleasePool.new;
640+ NSApp := NSApplication.sharedApplication;
641+ NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
642+ appName := NSProcessInfo.processInfo.processName;
643+ window := NSWindow.alloc.initWithContentRect_styleMask_backing_defer(NSMakeRect(0, 0, 200, 200),
644+ NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask,
645+ NSBackingStoreBuffered, False).autorelease;
646+
647+ // text label
648+ lText := NSTextField.alloc.initWithFrame(NSMakeRect(50, 50, 120, 50)).autorelease;
649+ lText.setBezeled(False);
650+ lText.setDrawsBackground(False);
651+ lText.setEditable(False);
652+ lText.setSelectable(False);
653+ lText.setStringValue(NSSTR('NSTextField'));
654+ window.contentView.addSubview(lText);
655+
656+ // button
657+ lButton := NSButton.alloc.initWithFrame(NSMakeRect(50, 100, 120, 50)).autorelease;
658+ window.contentView.addSubview(lButton);
659+ lButton.setTitle(NSSTR('Button title!'));
660+ lButton.setButtonType(NSMomentaryLightButton);
661+ lButton.setBezelStyle(NSRoundedBezelStyle);
662+
663+ // button event handler setting
664+ lDelegate := TMyDelegate.alloc.init;
665+ lButton.setTarget(lDelegate);
666+ lButton.setAction(ObjCSelector(lDelegate.HandleButtonClick));
667+
668+ // Window showing and app running
669+ window.center;
670+ window.setTitle(appName);
671+ window.makeKeyAndOrderFront(nil);
672+ NSApp.activateIgnoringOtherApps(true);
673+ NSApp.run;
674+end.
675+```
676+
677+---
678+*From the Free Pascal wiki, page "FPC PasCocoa", as it stood on 2021-05-01 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
679+Category: Cocoa
680+Category: Headers and Bindings
681+Category: Objective Pascal
682+Category: Objective-C
683+Category: iOS
684+Category: macOS

Back to history