Date   

Re: NSAlert boxes ...

Jon Gotow
 

Oh interesting - it looks like when you call [NSAlert beginSheetModalForWindow:completionHandler:], the alert gets retained by the parent window's attachedSheet property. So you're right, no issues there either. Now that you've brought it up, I have to say I've never worried about the alert being released too early in my code when I use beginSheetModalForWindow - I never gave it much thought because it just worked.

- Jon

On Feb 17, 2020, at 12:54 AM, Graham Cox <graham@mapdiva.com> wrote:

That is the case I’m talking about and no, it works fine even if you don’t “worry” about the lifecycle.

Just alloc + init + autorelease, then beginSheet…. it works, it has always worked since completion blocks were introduced.

It also works for the -runModal case also, you can autorelease prior to that call and that also doesn’t cause a lifecycle issue.

You can certainly “worry” about extending the lifecycle into the completion block if you want, except the unbalanced release will throw a compiler warning. That in itself shows how unnecessary it is to bother with.

TL;DR: Normal rules apply, stop overthinking this! Just because an NSAlert has some unusual asynchronous lifespan doesn’t mean it needs to be treated any differently from any other object you instantiate.


Re: NSAlert boxes ...

Graham Cox
 



On 17 Feb 2020, at 4:27 pm, Jon Gotow <gotow@...> wrote:

If you were to use [NSAlert beginSheetModalForWindow:completionHandler:], then you'd have to worry about lifecycle of the alert extending beyond the current function context.


That is the case I’m talking about and no, it works fine even if you don’t “worry” about the lifecycle.

Just alloc + init + autorelease, then beginSheet…. it works, it has always worked since completion blocks were introduced.

It also works for the -runModal case also, you can autorelease prior to that call and that also doesn’t cause a lifecycle issue.

You can certainly “worry” about extending the lifecycle into the completion block if you want, except the unbalanced release will throw a compiler warning. That in itself shows how unnecessary it is to bother with.

TL;DR: Normal rules apply, stop overthinking this! Just because an NSAlert has some unusual asynchronous lifespan doesn’t mean it needs to be treated any differently from any other object you instantiate.

—Graham





Re: NSAlert boxes ...

Jon Gotow
 

You're making this far more complicated than it is (talking about running the alert asynchronously, etc).

NSModalResponse choice = [alert runModal];

will run the alert synchronously. Note that it returns a result from this method call, meaning that the call blocks by running its own modal event loop in runModal and only returns after the user has clicked on a button. That means that your autorelease is fine - the scope of this alert is just within the current function, so it'll get cleaned up at the end of the current runloop invocation. That said, you can also just release it manually after you call runModal, like this:

NSAlert *alert = [[NSAlert alloc] init];

alert.messageText = @"Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

NSModalResponse choice = [alert runModal];

[alert release];

If you were to use [NSAlert beginSheetModalForWindow:completionHandler:], then you'd have to worry about lifecycle of the alert extending beyond the current function context.

- Jon

On Feb 16, 2020, at 6:17 AM, Peter Hudson via Groups.Io <Peter.hudson=me.com@groups.io> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter


Re: NSAlert boxes ...

Graham Cox
 



On 17 Feb 2020, at 12:22 pm, Sandor Szatmari <admin.szatmari.net@...> wrote:

The MRR rules are straight forward and deviating from them because the runloop may retain the alert is asking for trouble in my opinion.  There is no harm in taking ownership of the alert and releasing/autoreleasing it.  I would argue that doing so ensures that any changes in SDK/runtime behavior don’t adversely affect your product.  

Sandor


That’s exactly what I’m saying - you are taking ownership of it with alloc+init.

Then you release it or autorelease it within the scope of setting it up. Normal rules.

But the point is the alert is run asynchronously, so it has to survive long after the scope of where you instantiated and set it up. Long after the next autorelease drain in fact. But that is someone else's problem - the run-loop’s, I’m supposing.

The alternative is to try to take ownership of it until it is finally and completely dismissed, which requires an unbalanced release in the completion block. This not only flags a warning when you compile, but it’s simply unnecessary. Trying to overthink the ownership rules in this case leads to code that is not only complicated, but redundant. The designers of NSAlert have already taken its lifetime into consideraton, so YOUR ownership of it only lasts as long as it takes to instantiate it, set it up, and ask it to run modally.

Peter’s original code, where he autoreleases as part of alloc + init, works absolutely fine.

—Graham



Re: NSAlert boxes ...

Sandor Szatmari
 

The MRR rules are straight forward and deviating from them because the runloop may retain the alert is asking for trouble in my opinion.  There is no harm in taking ownership of the alert and releasing/autoreleasing it.  I would argue that doing so ensures that any changes in SDK/runtime behavior don’t adversely affect your product.  

Sandor

On Feb 16, 2020, at 19:26, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:


Thanks Graham and Alex. 
I had reached the same sort of conclusions - but could not find any corroborative info anywhere ....
Peter 

On 16 Feb 2020, at 23:59, Graham Cox <graham@...> wrote:

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.



Re: NSAlert boxes ...

Peter Hudson
 

Thanks Graham and Alex. 
I had reached the same sort of conclusions - but could not find any corroborative info anywhere ....
Peter 

On 16 Feb 2020, at 23:59, Graham Cox <graham@...> wrote:

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.



Re: NSAlert boxes ...

Graham Cox
 

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.



Re: NSAlert boxes ...

Alex Zavatone
 

On Feb 16, 2020, at 5:04 PM, Graham Cox <graham@mapdiva.com> wrote:

Hi Peter,

FWIW, I’ve always done exactly the same as this too, and have never had an issue.

My understanding (which may be wrong) is that the modal loop that runs the alert temporarily retains it, so you are safe no matter whether the alert is released by you afterwards, or autoreleased.

The point is, your code follows the normal rules. There’s no special case for NSAlert or other modal dialogs, because internal code behind the scenes makes sure the normal rules apply.

—Graham
Sorry, A bit groggy here. If my previous assumption that autorelease isn’t needed is incorrect, then it might be that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.

In any case, it’s an easy check.


Re: NSAlert boxes ...

Graham Cox
 

Hi Peter,

FWIW, I’ve always done exactly the same as this too, and have never had an issue.

My understanding (which may be wrong) is that the modal loop that runs the alert temporarily retains it, so you are safe no matter whether the alert is released by you afterwards, or autoreleased.

The point is, your code follows the normal rules. There’s no special case for NSAlert or other modal dialogs, because internal code behind the scenes makes sure the normal rules apply.

—Graham



On 17 Feb 2020, at 12:17 am, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];
       
NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter



Re: NSAlert boxes ...

Alex Zavatone
 

On Feb 16, 2020, at 9:37 AM, Peter Hudson via Groups.Io <Peter.hudson=me.com@groups.io> wrote:

Thanks Sandor.

My use of alert is very tightly scoped - and only used once - and not passed on.
Many thanks for the link.

Peter
My expectation is that autorelease is not needed. In any case, if you do use the memory graph debugger to see if it stays allocated or not, and if autorelease is needed, please let us know.


Re: NSAlert boxes ...

Alex Zavatone
 

Why are you making it autorelease?

Run your method, display and dispose of the alert and then while your app is still running click on the Memory Graph Debugger icon in the debug bar.  Look at your allocations and leaks to see if any object of an NSAlert class is still there.

This will tell you if it’s needed or not.

On Feb 16, 2020, at 7:17 AM, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];
       
NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter



Re: NSAlert boxes ...

Peter Hudson
 

Thanks Sandor.

My use of  alert is very tightly scoped - and only used once - and not passed on.
Many thanks for the link.

Peter



On 16 Feb 2020, at 15:28, Sandor Szatmari <admin.szatmari.net@...> wrote:

Peter,

On Feb 16, 2020, at 08:18, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.

You may have to dispose of it yourself or maybe ARC will take care of it for you.  If you’re writing MRR (not ARC) code you always have to -release/-autorelease objects you own (create).  

You take ownership of an object when you call -retain or -copy on an existing object, or use -new, -alloc/-init when creating an object.  As far as I’m aware there are no exceptions to these ownership rules.  In MRR you are responsible for calling -release/-autorelease on any object you used these methods to create/copy/take ownership.

These rules are essentially true in ARC too, except the compiler figures out when to call -release so you don’t explicitly call it.

Here is some additional reading on the topic.



My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];
       
NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It appears to be but I cannot tell what else you do with ‘alert’.  -autorelease says that the object should live for the current scoped autorelease-pool.

So, if this alert panel is not supposed to live beyond the current autorelease-pool, then the code is fine.  If it does live beyond it, then you need to transfer ownership to that scope.

Sandor


It certainly seems to work …..



Peter



Re: NSAlert boxes ...

Sandor Szatmari
 

Peter,

On Feb 16, 2020, at 08:18, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.

You may have to dispose of it yourself or maybe ARC will take care of it for you.  If you’re writing MRR (not ARC) code you always have to -release/-autorelease objects you own (create).  

You take ownership of an object when you call -retain or -copy on an existing object, or use -new, -alloc/-init when creating an object.  As far as I’m aware there are no exceptions to these ownership rules.  In MRR you are responsible for calling -release/-autorelease on any object you used these methods to create/copy/take ownership.

These rules are essentially true in ARC too, except the compiler figures out when to call -release so you don’t explicitly call it.

Here is some additional reading on the topic.



My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

       

NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It appears to be but I cannot tell what else you do with ‘alert’.  -autorelease says that the object should live for the current scoped autorelease-pool.

So, if this alert panel is not supposed to live beyond the current autorelease-pool, then the code is fine.  If it does live beyond it, then you need to transfer ownership to that scope.

Sandor


It certainly seems to work …..



Peter


NSAlert boxes ...

Peter Hudson
 

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

       

NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter


Re: Auto layout help

John Brownie
 

And I found the missing piece. I was failing to set translatesAutoresizingMaskIntoConstraints to false for one of the views. Doing that makes it all work.

John


Re: Auto layout help

John Brownie
 

Further digging leaves me more confused. Because I'm supporting 10.9, there are various features I can't use, so I'm stuck with the auto layout basics, and it's hard to find a good explanation of how to set that up.

So, the window has a plain NSView in it, call it Container A. In the windowDidLoad of the window controller, I create an instance of the appropriate concrete subclass of MyWebView, which is the abstract class that captures the common behaviour I want, call it Container B, and make it a subview of Container A. The subclass creates its appropriate web view (WKWebView or WebView) and adds it as a subview of itself. So we have Container A containing Container B, which contains a web view.

What I want is to have zero margins around the web view and Container B, and have them resize as Container A is resized by resizing the window. My approach has been to set constraints in IB on Container A. When creating the web view, I add it as a subview of Container B and add constraints. When Container B has been created, I add it to Container A and add constraints. But somehow the constraints seem to be in the wrong places.

For debug purposes, I made the margins different at each level, and that gives me an unsatisfiable layout, as I have the different constraints conflicting.

The conclusion is that I don't know what I'm doing, and I haven't been able to find anything to explain how to set these up in code. Can anyone point me to a resource that tells me how to do this?

John


Auto layout help

John Brownie
 

I have my web view displaying correctly, but I've run into a problem in getting the auto layout constraints working correctly. Basically, I build the appropriate web view as a subview of a custom view, which is in turn embedded in a view within a window. The problem is that, if I set constraints on the custom view, the window stops being resizable, and I can't work out why.

Here's the code for the constraints:

let variableBindings = ["webView": webView]
let constraints1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[webView]-0-|", options: [], metrics: nil, views: variableBindings)
let constraints2 = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[webView]-0-|", options: [], metrics: nil, views: variableBindings)
webContentView.addConstraints(constraints1)
webContentView.addConstraints(constraints2)

I have very similar code for the actual web view within its containing view. If I have only those and not the outer constraints, the window is resizable, but the container for the web view doesn't resize.

I must be doing something wrong, obviously, but I have run out of ideas on how to find my problem. Needless to say, this is the first time I've had to do auto layout in code.

Thanks for any insights,
John
--
John Brownie
Mussau-Emira language, New Ireland Province, Papua New Guinea
Kouvola, Finland


Re: How to present a web view while supporting 10.9?

John Brownie
 

Thanks for all the tips. I have it all worked out now.

John

Jens Alfke wrote on 7/2/20 21:39:

You'll need two code paths, one that instantiates and runs a WebView, the other that instantiates and runs a WKWebView. Their APIs and functionality are not identical, so it's not just a question of "how do I get IB to instantiate the right class". Your controller code needs to be different.

I would create my own abstract view and controller class for this (MyWebView and MyWebViewController?), then have concrete subclasses of each for the old and new WebViews. Each view class instantiates the appropriate system view and makes it a subview of itself.
--
John Brownie
Mussau-Emira language, New Ireland Province, Papua New Guinea
Kouvola, Finland


Re: How to present a web view while supporting 10.9?

 

You'll need two code paths, one that instantiates and runs a WebView, the other that instantiates and runs a WKWebView. Their APIs and functionality are not identical, so it's not just a question of "how do I get IB to instantiate the right class". Your controller code needs to be different.

I would create my own abstract view and controller class for this (MyWebView and MyWebViewController?), then have concrete subclasses of each for the old and new WebViews. Each view class instantiates the appropriate system view and makes it a subview of itself.

—Jens


Re: How to present a web view while supporting 10.9?

Sandor Szatmari
 

Yes I could have been more specific, everything worked, all be it with warnings, with both classes of web views being instantiated in code.  

Sandor

On Feb 7, 2020, at 10:13, John Brownie <john_brownie@...> wrote:

I should note that, once I put the WKWebView into the window, there is an error that I hadn't noticed before:
error: Class Unavailable: WKWebView before macOS 10.12 (NSCoding support was broken in previous versions)
So I would have to drop support for 10.9-10.11 to use WKWebView, so I really need to work out how to do this.

Is building the window in code the solution?

John

221 - 240 of 1422