Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

GNUstep - General mailing list
Ref : First Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton
Edition : First Edition: July 2000; Last Updated: January 2008
URL :
http://www.gnustep.it/nicola/Tutorials/WindowsAndButtons/index.html

Hi Nicola (Pero),
Hi All,

I wish first to thank You, Nicola, for the great tutorials You made.
They helped Me to understand and begin my learning pretty well.

Trying to play and understand the final code in the Tutorial 'First
Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton', I was
facing to some warnings and bugs. I think You should modify the final
code listing at page 9, in the '@implementation' section like this :

(1) In the method 'dealloc' :

- (void) dealloc
{
   RELEASE (myWindow);
   /* According to a warning while making the app */
   [super dealloc];
}

(2) In the method 'createWindow' :

- (void) createWindow
{
...
myWindow = [NSWindow alloc];

   /* Don't make a assignment of 'myWindow' again...
   myWindow = */
   /* So I kept only the message... */
   [myWindow initWithContentRect: rect
                        styleMask: styleMask
                        backing: NSBackingStoreBuffered
                        defer: NO];

  /* Here, the contentView was obviously missing : I added it... */
[myWindow setContentView: myButton];
...
}

I Hope this could be helpful for other Beginners like Me. ;-)

Regards,


--
Bien cordialement,
Patrick CARDONA


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

Richard Frith-Macdonald-8


> On 10 Jun 2020, at 10:42, Patrick Cardona via Discussion list for the GNUstep programming environment <[hidden email]> wrote:
>

> (2) In the method 'createWindow' :
>
> - (void) createWindow
> {
> ...
> myWindow = [NSWindow alloc];
>
>  /* Don't make a assignment of 'myWindow' again...
>  myWindow = */
>  /* So I kept only the message... */
>  [myWindow initWithContentRect: rect
>                       styleMask: styleMask
>                       backing: NSBackingStoreBuffered
>                       defer: NO];

The correct code here is

myWindow = [NSWindow alloc];
myWindow = [myWindow initWithContentRect: rect
                      styleMask: styleMask
                      backing: NSBackingStoreBuffered
                      defer: NO];

You *must* have the second assignment, because the initWithContentRect:... method may destroy the original window and return a new one.  maybe it would help for the tutorial to have a comment saying that.

If you find it aesthetically displeasing to have two assignments, you can write the code as

myWindow = [[NSWindow alloc] initWithContentRect: rect
                      styleMask: styleMask
                      backing: NSBackingStoreBuffered
                      defer: NO];


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

David Chisnall-7
In reply to this post by GNUstep - General mailing list
On 10/06/2020 10:42, Patrick Cardona via Discussion list for the GNUstep
programming environment wrote:

> Ref : First Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton
> Edition : First Edition: July 2000; Last Updated: January 2008
> URL : http://www.gnustep.it/nicola/Tutorials/WindowsAndButtons/index.html
>
> Hi Nicola (Pero),
> Hi All,
>
> I wish first to thank You, Nicola, for the great tutorials You made.
> They helped Me to understand and begin my learning pretty well.
>
> Trying to play and understand the final code in the Tutorial 'First
> Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton', I was
> facing to some warnings and bugs. I think You should modify the final
> code listing at page 9, in the '@implementation' section like this :
>
> (1) In the method 'dealloc' :
>
> - (void) dealloc
> {
>    RELEASE (myWindow);
>    /* According to a warning while making the app */
>    [super dealloc];
> }

Note that this -dealloc method is not required at all with ARC.

> (2) In the method 'createWindow' :
>
> - (void) createWindow
> {
> ...
> myWindow = [NSWindow alloc];
>
>    /* Don't make a assignment of 'myWindow' again...
>    myWindow = */
>    /* So I kept only the message... */
>    [myWindow initWithContentRect: rect
>                         styleMask: styleMask
>                         backing: NSBackingStoreBuffered
>                         defer: NO];
>
>   /* Here, the contentView was obviously missing : I added it... */
> [myWindow setContentView: myButton];
> ...
> }

As Richard says, the semantics of init-family methods mean that this
doesn't do what you think it does.

An init-family method consumes the receiver and returns a new owning
reference to the return value.  In the common case, the the receiver
will be the same as the return value and so this cancels out.  In the
case of things like NSWindow, it is quite likely that they are
different.  NSWindow +alloc is likely to return a singleton placeholder
and do the real allocation when you call one of the init-family methods
that

That is why it is considered good style to never assign the result of
alloc to a variable and always chain the call as [[SomeClass alloc]
initWithSomeInitFamilyMethod: ...].  For more information about method
families, see this:

https://www.informit.com/articles/article.aspx?p=1745875&seqNum=4

Note that without ARC, your version may generate memory management
errors.  With ARC, it will just have surprising behaviour: the newly
created window created by the init-family method will be deallocated
immediately and the value assigned to myWindow will point to the
placeholder.

> I Hope this could be helpful for other Beginners like Me. ;-)

I would *strongly* recommend any beginner use ARC from the outset.
Thinking in terms of ownership and consume operations is a far better
memory model than thinking in terms of reference count manipulation.

ARC also makes memory management work cleanly in Objective-C++, so
things like std::vector<NSMutableString*> work correctly (and will
typically be faster than NSMutableArray<NSMutableString*>).

David


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

GNUstep - General mailing list
In reply to this post by Richard Frith-Macdonald-8
Hi Richard,

Thank You for this aknowledgment. I will keep it in my Templates
Library.
I don't own the source of the Tutorial document, so only Nicola could
modify it.

When You say :
> the initWithContentRect:...
> method may destroy the original window...

Does it mean sometimes it does, sometimes it does not ? How this
behaviour is predictable ?
Well, I understand I must continue to read, try and learn...

Regards,

--
Bien cordialement,
Patrick CARDONA
On 2020-06-10 12:04:11 +0200 Richard Frith-Macdonald
<[hidden email]> wrote:

>
>
>> On 10 Jun 2020, at 10:42, Patrick Cardona via Discussion list for
>> the
>> GNUstep programming environment <[hidden email]> wrote:
>
>
>> (2) In the method 'createWindow' :
>
>> - (void) createWindow
>> {
>> ...
>> myWindow = [NSWindow alloc];
>
>>   /* Don't make a assignment of 'myWindow' again...
>>   myWindow = */
>>   /* So I kept only the message... */
>>   [myWindow initWithContentRect: rect
>>                        styleMask: styleMask
>>                        backing: NSBackingStoreBuffered
>>                        defer: NO];
>
> The correct code here is
>
> myWindow = [NSWindow alloc];
> myWindow = [myWindow initWithContentRect: rect
>                       styleMask: styleMask
>                       backing: NSBackingStoreBuffered
>                       defer: NO];
>
> You *must* have the second assignment, because the
> initWithContentRect:...
> method may destroy the original window and return a new one.  maybe
> it would
> help for the tutorial to have a comment saying that.
>
> If you find it aesthetically displeasing to have two assignments, you
> can
> write the code as
>
> myWindow = [[NSWindow alloc] initWithContentRect: rect
>                       styleMask: styleMask
>                       backing: NSBackingStoreBuffered
>                       defer: NO];
>


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

GNUstep - General mailing list
In reply to this post by David Chisnall-7
Hi David,

Thank You for the whole  aknowledgement, which completed Richard's answer.
I will now look for ARC.

Regards,

--
Bien cordialement,
Patrick CARDONA
On 2020-06-10 12:44:06 +0200 David Chisnall <[hidden email]> wrote:

> On 10/06/2020 10:42, Patrick Cardona via Discussion list for the GNUstep
> programming environment wrote:
>> Ref : First Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton
>> Edition : First Edition: July 2000; Last Updated: January 2008
>> URL : http://www.gnustep.it/nicola/Tutorials/WindowsAndButtons/index.html
>
>> Hi Nicola (Pero),
>> Hi All,
>
>> I wish first to thank You, Nicola, for the great tutorials You made.
>> They helped Me to understand and begin my learning pretty well.
>
>> Trying to play and understand the final code in the Tutorial 'First Steps
>> in GNUstep GUI Programming (2) : NSWindow,  NSButton', I was facing to
>> some warnings and bugs. I think You should modify the final code listing at
>> page 9, in the '@implementation' section like this :
>
>> (1) In the method 'dealloc' :
>
>> - (void) dealloc
>> {
>>     RELEASE (myWindow);
>>     /* According to a warning while making the app */
>>     [super dealloc];
>> }
>
> Note that this -dealloc method is not required at all with ARC.
>
>> (2) In the method 'createWindow' :
>
>> - (void) createWindow
>> {
>> ...
>> myWindow = [NSWindow alloc];
>
>>     /* Don't make a assignment of 'myWindow' again...
>>     myWindow = */
>>     /* So I kept only the message... */
>>     [myWindow initWithContentRect: rect
>>                          styleMask: styleMask
>>                          backing:
>> NSBackingStoreBuffered
>>                          defer: NO];
>
>>    /* Here, the contentView was obviously missing : I added it... */
>> [myWindow setContentView: myButton];
>> ...
>> }
>
> As Richard says, the semantics of init-family methods mean that this doesn't
> do what you think it does.
>
> An init-family method consumes the receiver and returns a new owning
> reference to the return value.  In the common case, the the receiver will be
> the same as the return value and so this cancels out.  In the case of things
> like NSWindow, it is quite likely that they are different.  NSWindow +alloc
> is likely to return a singleton placeholder and do the real allocation when
> you call one of the init-family methods that
>
> That is why it is considered good style to never assign the result of alloc
> to a variable and always chain the call as [[SomeClass alloc]
> initWithSomeInitFamilyMethod: ...].  For more information about method
> families, see this:
>
> https://www.informit.com/articles/article.aspx?p=1745875&seqNum=4
>
> Note that without ARC, your version may generate memory management errors.  
> With ARC, it will just have surprising behaviour: the newly created window
> created by the init-family method will be deallocated immediately and the
> value assigned to myWindow will point to the placeholder.
>
>> I Hope this could be helpful for other Beginners like Me. ;-)
>
> I would *strongly* recommend any beginner use ARC from the outset. Thinking
> in terms of ownership and consume operations is a far better memory model
> than thinking in terms of reference count manipulation.
>
> ARC also makes memory management work cleanly in Objective-C++, so things
> like std::vector<NSMutableString*> work correctly (and will typically be
> faster than NSMutableArray<NSMutableString*>).
>
> David
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

Patrick Cardona-2
In reply to this post by David Chisnall-7
Hi David,

I looked around to better understand how to use ARC and the new ABI as you suggested.
But according to your article on the wiki (1), I understood that only 64bits systems could be able to use the new ABI : is it right ?

And the RPI 3B+ I am using now is only 32 bits :
description: ARMv7 Processor rev 4 (v7l)
    product: Raspberry Pi 3 Model B Plus Rev 1.3
    ...
    bits: 32 bits


(1) The Wiki source :
 http://wiki.gnustep.org/index.php/ObjC2_FAQ,


--
Regards,
Bien cordialement,
Patrick CARDONA
On 2020-06-10 12:44:06 +0200 David Chisnall <[hidden email]> wrote:

> On 10/06/2020 10:42, Patrick Cardona via Discussion list for the GNUstep
> programming environment wrote:
>> Ref : First Steps in GNUstep GUI Programming (2) : NSWindow,  NSButton
>> Edition : First Edition: July 2000; Last Updated: January 2008
>> URL : http://www.gnustep.it/nicola/Tutorials/WindowsAndButtons/index.html
>
>> Hi Nicola (Pero),
>> Hi All,
>
>> I wish first to thank You, Nicola, for the great tutorials You made.
>> They helped Me to understand and begin my learning pretty well.
>
>> Trying to play and understand the final code in the Tutorial 'First Steps
>> in GNUstep GUI Programming (2) : NSWindow,  NSButton', I was facing to
>> some warnings and bugs. I think You should modify the final code listing at
>> page 9, in the '@implementation' section like this :
>
>> (1) In the method 'dealloc' :
>
>> - (void) dealloc
>> {
>>     RELEASE (myWindow);
>>     /* According to a warning while making the app */
>>     [super dealloc];
>> }
>
> Note that this -dealloc method is not required at all with ARC.
>
>> (2) In the method 'createWindow' :
>
>> - (void) createWindow
>> {
>> ...
>> myWindow = [NSWindow alloc];
>
>>     /* Don't make a assignment of 'myWindow' again...
>>     myWindow = */
>>     /* So I kept only the message... */
>>     [myWindow initWithContentRect: rect
>>                          styleMask: styleMask
>>                          backing:
>> NSBackingStoreBuffered
>>                          defer: NO];
>
>>    /* Here, the contentView was obviously missing : I added it... */
>> [myWindow setContentView: myButton];
>> ...
>> }
>
> As Richard says, the semantics of init-family methods mean that this doesn't
> do what you think it does.
>
> An init-family method consumes the receiver and returns a new owning
> reference to the return value.  In the common case, the the receiver will be
> the same as the return value and so this cancels out.  In the case of things
> like NSWindow, it is quite likely that they are different.  NSWindow +alloc
> is likely to return a singleton placeholder and do the real allocation when
> you call one of the init-family methods that
>
> That is why it is considered good style to never assign the result of alloc
> to a variable and always chain the call as [[SomeClass alloc]
> initWithSomeInitFamilyMethod: ...].  For more information about method
> families, see this:
>
> https://www.informit.com/articles/article.aspx?p=1745875&seqNum=4
>
> Note that without ARC, your version may generate memory management errors.  
> With ARC, it will just have surprising behaviour: the newly created window
> created by the init-family method will be deallocated immediately and the
> value assigned to myWindow will point to the placeholder.
>
>> I Hope this could be helpful for other Beginners like Me. ;-)
>
> I would *strongly* recommend any beginner use ARC from the outset. Thinking
> in terms of ownership and consume operations is a far better memory model
> than thinking in terms of reference count manipulation.
>
> ARC also makes memory management work cleanly in Objective-C++, so things
> like std::vector<NSMutableString*> work correctly (and will typically be
> faster than NSMutableArray<NSMutableString*>).
>
> David
>
>




--
Bien cordialement,
Patrick CARDONA


Reply | Threaded
Open this post in threaded view
|

Re: Tutorials enhancement proposal : First Steps in GNUstep GUI Programming (2) : NSWindow, NSButton

David Chisnall-7
Hi,

I'm not sure where you get that from.  The only comment about 64-bit on
that page is in reference to Apple's implementation, stating that the
new ABI is the only option on 64-bit Apple platforms (Apple supported
the old and new ABIs on 32-bit x86, only the new one on 64-bit Macs and
only the new one on any iOS devices).

That said, the page is quite out of date.  The new runtime supports
three ABIs:

  - The old GCC one.  Basically, don't use this, it doesn't support any
post-2005 Objective-C features.
  - The GNUstep v1 ABI, which tried to be backwards compatible with the
GCC runtime so you could mix code compiled with GCC.  This didn't work
particularly well and, in hindsight, was a bad idea.  This is the
minimum for using features like ARC.
  - The GNUstep v2 ABI, which is designed to use modern linker features.
  This supports all modern Objective-C features.  This depends on some
features specific to the binary format and so is supported on ELF and
COFF platforms (not currently Mach-O or Wasm, though I'd be interested
in adding them at some point).

ARC's memory model intrinsically requires an ABI with non-fragile
instance variables (i.e. the generated code does not hard-code the
offsets of instance variables, instead it looks the offsets up in a
variable initialised by the runtime).

You control the runtime with the -fobjc-runtime= flag to clang.  The
format is:

-fobjc-runtime={runtime name}-{version}

The options are:

gcc, any version, targets the old GCC ABI.

gnustep-1.{0-8} targets the GNUstep 1.x ABI, restricting itself to
features supported by the corresponding runtime release, for example not
using property accessor helpers that weren't added or only using
objc_msgSend on architectures that have the right implementation.

gnustep-2.0 (currently the only 2.x version, any point release value is
ignored).  This switches to the new ABI.  This should give smaller
binaries and faster code, but is incompatible with code compiled with GCC.

ARMv7 has all of the assembly fast paths, so should work well with the
new ABI, though I think there may still be a few corner cases in C++
exception interop that don't work with the ARM EH ABI.  Please try using
libobjc2 trunk and file bug reports on GitHub as you find them!

David

On 11/06/2020 20:01, Patrick Cardona wrote:

> Hi David,
>
> I looked around to better understand how to use ARC and the new ABI as you suggested.
> But according to your article on the wiki (1), I understood that only 64bits systems could be able to use the new ABI : is it right ?
>
> And the RPI 3B+ I am using now is only 32 bits :
> description: ARMv7 Processor rev 4 (v7l)
>      product: Raspberry Pi 3 Model B Plus Rev 1.3
>      ...
>      bits: 32 bits
>
>
> (1) The Wiki source :
>   http://wiki.gnustep.org/index.php/ObjC2_FAQ,
>
>