Alternative Cocoa framework, anyone?

LOL! I think “GTK” is the local name for one of the circles of Hell. I’ll leave that as an exercise for the reader. :slight_smile:

This project has been slowly building for a couple of years. Originally, I had just intended to organize my own collection of declares, which were scattered throughout dozens of projects I’ve written for my day-job since RealBasic 5.5. Somewhere along the line, I realized how useful it would be if the strengths of the IDE were leveraged to make declares simpler. Autocomplete alone made it worthwhile to me. Then I came up with my NSPtr class as a way of seeing critical info about Cocoa objects in the debugger, and the whole thing accelerated mightily. Now I use this thing in every project I start.

For anything too heavy, I’ll just use XCode, and maybe write a plugin, but I honestly prefer the Xojo IDE through long familiarity. Sticktuitiveness? Maybe. I prefer to think of it as active laziness. :wink:

That was an issue I wanted to address you with when I reviewed you vast collection, Daniel, but I am sorry I forgot: Are you sure you are handling the release/retain cycles correctly and your implementation isn’t causing leaks?
As a rule of thumb: Whenever you use an instance initializer, the instance is already retained and should be released on destruction time if you own it.
When you use a class initializer, the instance is not owned and should be retained first when you claim ownership.

The small print in Apple’s documentation is something I like to oversee. Usually everything’s working nicely, but then a function will not work until I realize that the result is not retained. Hours or days later usually :wink:

Is there a way to know what instances are still hanging around. Like in Xojo I can run through Runtime.IterateObjects, but is there something similar for declared instances?

[quote=269696:@Ulrich Bogun]That was an issue I wanted to address you with when I reviewed you vast collection, Daniel, but I am sorry I forgot: Are you sure you are handling the release/retain cycles correctly and your implementation isn’t causing leaks?
As a rule of thumb: Whenever you use an instance initializer, the instance is already retained and should be released on destruction time if you own it.
When you use a class initializer, the instance is not owned and should be retained first when you claim ownership.

The small print in Apple’s documentation is something I like to oversee. Usually everything’s working nicely, but then a function will not work until I realize that the result is not retained. Hours or days later usually ;)[/quote]

All I can say is that I have a decent understanding of when I am responsible for releasing, but it’s not perfect. I do test for leaks with Instruments, however, and things are looking pretty tight. I think I’m on the right track here, but I’m fallible. Any time I am wrong, please feel free say so.

I’ll look into the class vs. instance initializer thing. This may have been a gap in my knowledge.

I know of nothing, but that doesn’t mean there isn’t something. Again, I use Apple’s Instruments application to test for leaks.

@Ulrich Bogun Aha! I see. In the case of NSColor, I hadn’t considered factory methods and how the resulting objects are autoreleased. Thanks for leading me to that. I’ll keep it in mind going forward.

Ulrich’s rule (Hi, I’m Trump and I just invented that term right here and right now, I’ll patent it and… ). Can be simplified to “retain/release unless init”.

If you use alloc you should also use dealloc after release IIRC.

However… just letting auto release do it’s thing is very useful, just don’t expect the object to be around on the next cycle. In some of the convenience functions I write to get say system info, I just let autorelease do it’s thang.

The only way I know is retainCount. If an object has a positive retainCount it’s alive, negative and it should be 6 feet under.
In the past (haven’t tried for a while) retainCount still worked even after the object was released.

[quote=269704:@Sam Rowlands]Can be simplified to “retain/release unless init”.
If you use alloc you should also use dealloc after release IIRC.[/quote]

Yup. That was my guiding mantra (minus the dealloc part. AFAIK, release is sufficient.) When used correctly, my NSPtr class handles this automatically via a very simple mechanism. I’ve described it as ‘piggybacking’ on Xojo’s garbage collection, or ‘ghetto autorelease.’ So far, it seems to work well, though the necessary syntax can be cumbersome.

Never call dealloc manually.

[quote=269704:@Sam Rowlands]The only way I know is retainCount. If an object has a positive retainCount it’s alive, negative and it should be 6 feet under.
In the past (haven’t tried for a while) retainCount still worked even after the object was released.[/quote]

Never use retainCount either.

The command line ‘heap’ tool can do it.

In Obj-C you used to use dealloc when your custom class destructs, is this no longer the case or just a Xojo special?

Huh, I guess some the tricks I’ve learned over the years have died hard.

Thanks for correcting me. Mind you, I wonder how long before Obj-C API is deprecated and removed from the OS. Seems Apple’s throwing everything at Swift.

In Objective-C you were never supposed to call dealloc yourself. See the Apple docs:

[quote]Discussion
[…]
You never send a dealloc message directly. Instead, an object’s dealloc method is invoked by the runtime.[/quote]

From the beginnings of Objective-C (on OS X at least, I don’t know about NextSTEP and earlier) you were never supposed to use retainCount. retainCount is actually completely useless. See the Apple docs:

[quote]Special Considerations
This method is of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.[/quote]
See also When to use retainCount.

I always rely on this set of rules from CocoaDev:
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t.
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t. Yes: read this again!
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t. Twice is not enough for this rule, read it again!

Yup. This was the whole of my understanding until just yesterday when I learned the related corollary that objects which issue from class factory methods come to you autoreleased, and if you expect them to survive for long, they need to be retained, which means you need to release them. I’m debating how to incorporate this idea into my project.

Maybe you misunderstood the rule “If you alloc, retain, or copy it, …”.

It means

if the selector contains one of these words alloc, retain or copy,

“… it’s your job to release it. Otherwise it isn’t.”

No. I understood that quite well. I just didn’t count on how short lived an autoreleased object would actually be. Presumably the main loop is one big autorelease pool that drains each iteration?

A factory method (= a class method) needs to autorelease a created object, because on the class level you cannot create ivars, which would be necessary to hold a reference to it to be able to later release it. So you have to grab the newly created object immediately like that for example:

[code]Class ABC

Property mObjCPtr As Ptr

// method1
mObjCPtr = retain(SomeClass.sharedInstance())

// method2 (to be called later)
release(mObjCPtr)

End Class[/code]

Makes sense. Thanks. I had worked out the practical effect, and the needed solution the other day, but the reason wasn’t completely clear. As a concrete example, my conversion routine for NSColor used a class method, and the objects were vanishing on me when I tried to use them as properties. It now retains, and then flags the Xojo wrapper for release on destruct. Works just fine.

As an aside, I’m wondering what color space to use when converting Xojo colors to NSColor. NSCalibratedRGBColorSpace? NSDeviceRGBColorSpace? I’ve been ignoring this question so far.

This is what the framework uses. The device color spaces are deprecated and can provide surprising results.

[quote=269720:@Eli Ott]I always rely on this set of rules from CocoaDev :
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t.
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t. Yes: read this again!
If you alloc, retain, or copy it, it’s your job to release it. Otherwise it isn’t. Twice is not enough for this rule, read it again![/quote]

I think Apple’s docs on the basic memory management rules are rather straightforward.

Basically, but there can be nested autorelease pools. You also might want to wrap things like image conversions in your own autorelease pools so that the large objects don’t build up until the next iteration of the event loop