discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Cocoa/GNUStep compatible build


From: Ivan Vučica
Subject: Re: Cocoa/GNUStep compatible build
Date: Mon, 3 Sep 2012 23:15:17 +0200

So based on your surprise with regards to NSArrays, it sounds like you are completely new to Objective-C? You'll want to read some tutorials or books first, but this time I'll step in and give a non-GNUstep-specific piece of help (since it applies to Cocoa/Cocoa Touch as well).

First, Foundation framework is a reference counted environment to develop for. This means that according to a "contract" (that is, rules that Objective-C developers that use Foundation -- that's almost all of them -- decided to comply with) objects have a reference counter which is incremented and decremented based on some message sends ("method calls" in other languages).

These messages are -retain and -release. A utility method exists, -autorelease, which in concert with a utility class NSAutoreleasePool allows for adding an object to an autorelease pool, which is drained at regular intervals. Draining an autorelease pool is the same as sending all objects in the pool a -release message. In a GUI app, the intervals are not quite regular -- they are not created by some sort of a timer triggered by a hardware interrupt that would abort execution of your code and flush the autorelease pool. Rather, the place where the pool is drained is rather safe: it's done approximately in the place where the event loop resumes after your, app developer's, event-handling code has run.

-retain and -release are called when you want to claim "ownership" over an object ("hey, I might use it, don't let it disappear") or when you want to release your ownership ("that's fine, I'm done with it"). An internal counter is incremented or decremented. Objects that have their count decremented to zero are deallocated. Object's -dealloc method is called. Objects commonly call [super dealloc] to allow superclass to clean up the memory as well (typically by releasing all objects stored in instance variables). NSObject's dealloc actually frees the memory -- think of NSObject calling standard C function free().

Methods that, in their name, have "create", "alloc" and "new" (did I miss any?) will return an object with reference counter set to 1. This is not a language feature, but a "contract", a "convention" -- but one so far widespread you can almost treat it as a language feature. Class methods (the + ones) that have name of the class in its name typically return an object with 1 (-1) reference counter. By -1, I mean that the object has been added to the autorelease pool, and to ensure the object doesn't get deallocated, you'll want to increase the reference count to 2 (-1) using -retain, and consider that very soon, the reference counter will be just 1. If you don't do this, you'll get the hyper-cool feature that the object will be guaranteed to exist long enough to be returned from the function, but it'll get released very soon.


So what does this have to do with array?

See, the array actually wants to take ownership of an object. As stated above, that means an array is (by a contract!) bound to send -retain message  to each and every object added into it, no matter in what way. In your example below, you add the objects via the autoreleasing allocator+initializer class method, "+[NSArray arrayWithObjects:]".

If you pass numbers -- NSArray will happily treat each of them as pointers, and try to send -release method to an object stored at memory location, for example, 0x00000002.

As you might guess, there is no valid object stored at memory location 0x00000002.

So what can be done about the evil NSArray? Well, there's NSPointerArray. And under Apple's Cocoa environment, you could perhaps construct the NSArray using Core Foundation by specifying that no retain and release C function should be called for pointers added into CFArrayRef (which is toll-free-bridged into NSArray).

While first solution would be neat, it'd mean you can't mix other Objective-C objects (those based on NSObject) int the same array and ensure that they won't get deallocated prematurely. Second one, as far as I know, is available only for Apple platforms; I'm not sure how far GNUstep's CoreBase progressed.

So we reach the third solution: the one you posted below. You box non-Objective-C data types into NSNumber (for integers, floats, doubles, etc), NSDecimalNumber (for high-precision currency types), NSString (for strings), NSData (for unstructured byte streams) and NSValue (for all other C types; for example, structures). -valueForKey{Path}: and -setValue:forKey{Path}: make use of NSValue and NSNumber for non-Objective-C data types, and the original Objective-C data types for i-vars and KVO getters and setters that use, well, Objective-C data types.

So since NSValue and NSNumber are nice, clean and, dare I say it, sexy ways to pack various data types into something that can be retained and released just like Objective-C objects.

What you read about literals of NSArrays et al is a very new compiler thingy that I believe was introduced with Mountain Lion and Xcode 4.4's Clang. I have no idea how well and if it is supported in GNUstep, and don't even know the syntax; with something that new and limited to only one very new release of an OS, I couldn't really make use of it anyway. (See, I may be even wrong and it may be only a compiler trick, meaning this could be used on previous versions of the OS. I don't know though.)

In GNUstep community you'll find primarily "old-school Objective-C developers". Even dot-syntax for property access is looked down upon around here. My personal sentiment about, for example, ARC is negative, but that's primarily due to tastes and nothing else. I have no particular opinions about the dot syntax. I have no idea how well accepted the array and dictionary literals are or will be. What I'd suggest is that you first play with the basics.

Regarding the use of a compiler: Clang is where most new language features are first added. Why? Apple is the one adding the new features, and they currently favor Clang, due to their dislike of GCC's license. So if those features are to work, you almost certainly need to use Clang. To see which compiler you use (and all commands that gnustep-make orders GNU Make to run), type:
  make messages=yes


Let's wrap this up with a repeated call for you to first read up some more on Objective-C memory management and other basics. We'll be more than happy to answer your questions, but only if they don't require an extremely lengthy answer to a beginner's confusion like this one did. I made an exception, but you'll really want to get acquainted with the language first.

And do so with an older subset of the language, first; it'll be far easier to understand the inner workings of the language that way, and you'll be less confused by how properties work, how setters work, and what the dot syntax means.


Good luck!

On 3. 9. 2012., at 22:27, pepijn de vos <pepijndevos@yahoo.com> wrote:

Tanks for the help.

I created a brew formula for gnustep-make, and can compile a basic NSLog a... tool. https://github.com/mxcl/homebrew/pull/14645

However, I tried to do something "simple" like make a list of number and print those, or see if an NSArray has a hash.

It seems that you need to do something like [NSArray arrayWithObjects: [NSNumber numberWithInteger:1], [NSNumber numberWithInteger:1][NSNumber numberWithInteger:1], nil] or use classic C arrays.

I read that in recent versions of Objective C it is possible to create literals of NSArray, NSNumber and NSDictionary.

This does not work for me, except for NSStrings. Am I using the wrong compiler? I seem to be using gcc, can I tell it to use llvm?

Are these literals supported on Linux as well?

Pepijn


From: Ivan Vučica <ivucica@gmail.com>
To: Steve Van Voorst <svanvoorst@hughes.net>
Cc: pepijndevos@yahoo.com; Discuss-gnustep@gnu.org
Sent: Monday, September 3, 2012 12:07 AM
Subject: Re: Cocoa/GNUStep compatible build


On 2. 9. 2012., at 15:58, Steve Van Voorst <svanvoorst@hughes.net> wrote:

<<I want to write a command line app in Objective C that needs to run on Linux and Mac. I read I can use Foundation on Linux using GNUStep.  Do I need the whole of GNUStep, or can I just depend on Foundation?>>

In my experience, you need both <Foundation/Foundation.h> and <AppKit/AppKit.h>.  

Just to clear this up: if you are writing a command line tool, you definitely only need to include Foundation headers and link with Foundation. In fact, you don't even need to do that if you won't be using any classes from Foundation/gnustep-base. For example, you might write your own root class and use standard C input/output functions.

Regarding "app", we commonly call the command line stuff tools, not apps, in GNUstep; if it's a GUI program, then it's an app.

AppKit includes graphical components, such as windows, textfields, tabviews, et cetera. Unless you're writing a graphical app, you almost certainly don't need to include AppKit nor link with it. 






reply via email to

[Prev in Thread] Current Thread [Next in Thread]