Re: Cocoa trouble



Keith Wiley <kwiley@xxxxxxxxxx> writes:

> I also added an image to the project by drag-dropping a jpeg file into
> the Interface Builder window. I have verified that the image is part
> of the bundle by inspecting the Bundle contents. The jpg file is
> available under Contents/Resources/imageName.jpg.
>
> Then I put this code in my action handler:
>
> - (IBAction)myAction:(id)sender
> {
> NSString* str = [[NSString alloc] init];

You're leaking memory here. Whenever you create an object using +alloc or
-copy, or you send it a -retain, you're responsible for releasing it when
you're done.

You're not doing that with str. Here, you're creating a new, empty string
and storing a reference to it in str. But then:

> str = [NSString stringWithCString:"imageName.jpg"];

Here you're overwriting the reference to your newly-created string, and
replacing it with a reference to the string returned by +stringWithCString:.

Because you have no more references to the first string, you have no way to
release it, so it leaks.

> NSImage* image = [[NSImage alloc] initWithContentsOfFile:str];
>
> [myOutlet setImage:image];

Similar leak here: You're creating an NSImage object with +alloc, but you
haven't released it.

Have a look at Don Yacktman's classic article "Hold Me, Use Me, Free Me"
for more:

<http://www.stepwise.com/Articles/Technical/HoldMe.html>

> }
>
> It doesn't work. Running the debugger, str seems to get properly
> initialized to the relevant file name.

The file name, yes - but not the path. You need to include the full path,
not just the file name alone. You can get the path to the .app bundle with
NSBundle's methods:

str = [[NSBundle mainBundle] bundlePath];

You could get the path to the Resources/ subdirectory within the bundle:

str = [[NSBundle mainBundle] resourcePath];

You could use either of the above methods to get a "base" path, and then use
-stringByAppendingPathComponent: to construct the rest. But there's a much
better way - Get the full path directly to a specific resource:

str = [[NSBundle mainBundle] pathForResource:@"imageName" ofType:@"jpg"];

This is the preferred method of getting the path to a resource, because it
respects the user's language preferences, and returns the path to the correct
localized resource.

Last, and *certainly* not least, NSImage provides a convenience method you
can use to load an image resource that's been given a name in IB:

image = [NSImage imageNamed:@"imageName"];

> image gets initialized to nil however. The docs say it is supposed to
> return nil if there is a problem initing the file from the file
> name. Fine, but I can't figure out what the problem is. I tried
> putting a path to the file by calling it
> "Contents/Resources/imageName.jpg" instead of just the file name.

That's not the full path. A relative path such as the one you provided here is
resolved by appending it to the Current Working Directory. The CWD is what you
navigate in a shell with the "cd" command. If you use "open" from a shell to
start your app, the CWD is inherited from the shell environment unchanged. If
you start your app from Finder, the CWD is "/". If you start it from Xcode, it
is the build directory.

So as you can see, you can't depend on the CWD having any particular value -
so you have to use fully-qualified path names for pretty much everything you
do. (This is not a Cocoa issue, btw - the same is true of any app in Mac OS
X, regardless of what GUI toolkit the app uses.)

> Still no dice. I even tried putting the file in my home directly and
> calling it with a full path "~/imageName.jpg".

If you have a tilde in a path, it's not expanded automatically. But there's
a convenient method for expanding a string:

str = [@"~/imageName.jpg" stringByExpandingTildeInPath];

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
.



Relevant Pages

  • [API] Win32 Resources - List Icon Resource Names
    ... private static extern IntPtr LoadLibraryEx(string FileName, ... /// Gets the string resource names for the current file. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: UpdateResource being weird
    ... > That's funny, I was working on updateresource just yesterday, only i was ... > for String Types. ... >> inspection using a resource viewer shows that the MSI file is being ... but the INI file is messing me arround. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How to add button on Mail editor which is not outlook.??
    ... 'The bmp files are added to a resource file. ... Private Declare Function GdiplusShutdown Lib "GDIPlus" (_ ... ByVal filename As String) As StdPicture ... Dim tSI As GdiplusStartupInput ...
    (microsoft.public.office.developer.outlook.vba)
  • Re: Other version information
    ... header to locate the resource table. ... Windows PE files ... marked by a literal string. ... files in a folder, ...
    (microsoft.public.scripting.vbscript)
  • Re: June 2005 EAL Question
    ... parameter to a string. ... > public class MyEventLogInstaller: Installer ... You have a web app, ... >>> at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean ...
    (microsoft.public.dotnet.general)

Loading