Date   

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@...> 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@...> 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


Re: ***UNCHECKED*** Re: [cocoa-dev] How to present a web view while supporting 10.9?

Owen Hartnett
 

Yes.  Prior to 10.12, WKWebView was not available in Interface Builder and could only be instantiated in code.

-Owen

On Feb 7, 2020, at 10:13 AM, 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


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

John Brownie
 

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


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

John Brownie
 

Thanks for the reply.

Sandor Szatmari wrote on 6/2/20 20:51:
What SDK are you building against?
I assuming deployment target of 10.9 and not earlier…
I'm still on 10.14.6, Xcode 11.0, current SDK, which I assume is 10.14 (I can't see an option to choose anything but a platform in the SDK pop-up).
What is the exact problem your having? Is it just warnings, or are there compile/link/runtime errors…
I create a window in IB, and add a WKWebView to fill the content view. I then create an outlet to that, and Xcode wants me to mark the whole class (in Swift) as being available in 10.10 or later, and that's an error, not a warning. So there is a problem with what I do if I'm running on 10.9. Maybe I should just do it in Objective-C instead?

I have done this before with API available only on some platforms, but it's the first time I've run across it in a view built with IB. It's probably something quite simple, but I haven't been able to find an answer.
I just set the deployment target of an app with a WKWebView to 10.9 and build SDK 10.14. I got warnings of WKWebview et. all… not being available on 10.9 but it compiled and ran fine on Mojave. I’m assuming the availability conditionals would allow selection of WebView code if I ran it on some earlier release.
Not having the luxury of more than my own computer to test on, I can't tell what would happen if I did that and ran on 10.9. I'm still in the design/coding phase of this particular item.
I added a reference to a plain WebView and it did not complain about that with the deployment target set to 10.9.
With all the dire warnings about not using WebView, I'd much rather aim for WKWebView if possible. And this is only for a maintenance release, so I don't want to change the deployment target to 10.10 just for this.

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?

Sandor Szatmari
 

What SDK are you building against?
I assuming deployment target of 10.9 and not earlier…

What is the exact problem your having? Is it just warnings, or are there compile/link/runtime errors…

I just set the deployment target of an app with a WKWebView to 10.9 and build SDK 10.14. I got warnings of WKWebview et. all… not being available on 10.9 but it compiled and ran fine on Mojave. I’m assuming the availability conditionals would allow selection of WebView code if I ran it on some earlier release.

I added a reference to a plain WebView and it did not complain about that with the deployment target set to 10.9.

Sandor


On Feb 6, 2020, at 08:07, John Brownie <john_brownie@...> wrote:

My app currently supports 10.9, and I want to add a feature that displays an HTML document stored locally (in the bundle). The obvious way is to have a window which contains a web view. However, WKWebView is only available in 10.10, and WebView is deprecated.

If it were a matter of calling a method, I could wrap it with availability calls, but it's a definition of the class of an element in a window controller class. Presumably there is a way to handle this, but I haven't discovered it.

What I'm looking for is something like

if #available(macOS 10.10, *) {
var webView: WKWebView
}
else {
var webView: WebView
}

...but that is for running code, not declarations.

Is there a way to do this through IB? Or is my alternative to build the window in code, using whatever is available based on the runtime platform?

John
--
John Brownie
Mussau-Emira language, New Ireland Province, Papua New Guinea
Kouvola, Finland


281 - 300 of 1478