How to Load a Resource from Your Application Bundle in Mac OS X

Introduction

Recently I launched myself into the world of Mac OS X programming. The entire experience has been of mixed results. On the one hand I appreciate that there are so many tools and guides out there to help programmers develop for the Mac OS X platform, but I feel that most of the Apple Developer Guides are sadly lacking in proper examples of how to do basic things.

One of the basic things that I wanted to do was find a way to get a C string path to a file located in the application bundle.

As some of you Mac OS X users may know one of the great things about professional Apple programs is that they are located inside bundles. All the data and files associated with the program are inside one tidy little bundle that can be dragged into your application directory to install it. Or you can drag the bundle to your home folder, or run it off of your desktop, or rename it. The application continues to run no matter how you change its name or location.

This is extremely nice for the end use, but finding out how to achieve this as a programmer was a frustrating process that required hours of research for me.

After searching through forum threads, Apple documentation, email list servers, and other sources I finally put together a flexible set of functions that allows you to easily get a string path reference to data inside your Mac OS X application bundle.

The C++ Source Code

#include "CoreFoundation/CFBundle.h"

CFBundleRef mainBundle;

bool initializeBundleLoading()
{
mainBundle = CFBundleGetMainBundle();

if(!mainBundle)
{
  return false;
}

return true;
}

char *absoluteBundleResourcePath(const char *name_of_file_in_bundle)

{
CFURLRef resourceURL;

// Look for the resource in the main bundle by name and type. resourceURL = CFBundleCopyResourceURL(
mainBundle,

CFStringCreateWithCString(
NULL,
name_of_file_in_bundle,
kCFStringEncodingASCII),

NULL,
NULL
);

if(!resourceURL)
{
  throw new message_list("Failed to locate a file in the loaded bundle!");
}

char *fileurl = new char [200];


if(!CFURLGetFileSystemRepresentation(
    resourceURL,
    true,
    (UInt8*)
    fileurl,
    200))

{
  throw new message_list("Failed to turn a bundle resource URL into a filesystem path representation!");
}

else
{
  return fileurl;
}
}
Function References

bool initializeBundleLoading();

This function must be called once at the start of your program before trying to access any files inside the application bundle. Basically it retrieves a reference to the main application bundle. Without calling this you have no access to the bundle, and trying to load files from it will crash the program.

If the code is unable to locate the main application bundle (a possibility if it was launched from some older nonstandard file system browsers), then it returns the Boolean value false as a way of indicating that it failed.

char *absoluteBundleResourcePath(const char *name_of_file_in_bundle);

This function is what translates the name and relative path of a file in your application's bundle, into a C string absolute path pointing to the file inside the bundle. You can pass the result of this function into any file opening function that needs an absolute path to open a file.

This is very important because ordinarily, when you go to open a file, the application starts to access the file from the root directory: "/"

So not only does this return an absolute path to the bundle, starting from the root directory, but it also gives you the path within the bundle to the file it contains.

Note: You are responsible for freeing up the memory allocated by absoluteBundleResourcePath(). The C string that it returns must be manually deleted to free up the memory. So watch out for memory leaks.....

Other Notes

You'll notice that the code in absoluteBundleResourePath() throws an exception if it fails. In doing this it references a "message_list" class that I programmed. Since this sample code obviously doesn't include that class, then before you use it you will have to replace that exception code with your own error handling routine.

For simplicity you could just make it return "false" on a crash, just like initializeBundleLoading().

If you get any strange compiler errors then it probably means that you haven't added the Core Foundation Framework to your code. This code is dependent on it.

Feel free to use this code in your projects if it helps you. If you have any questions ask them in the comments. If you are looking for a good book that can help you with Mac OS X programming, then check out the highly recommended "Mac OS X Internals: A Systems Approach".

7 comments:

  1. Gawd, I hate bundles. This is the #1 reason I hate programming on a mac. But thank you for posting this, this is exactly what I was looking for.

    ReplyDelete
  2. You are welcome Brandon. I'm glad it could help.

    ReplyDelete
  3. This works very well and you've saved me some time. Thank you.

    ReplyDelete
  4. Very useful, thanks a lot for your work!

    ReplyDelete
  5. Thank you so much! After hours of Googling, you solved my problem in 2 minutes!

    ReplyDelete
  6. Kota malang merupakan kota yang memiliki banyak destinasi wisata menarik untuk dikunjungi. Beragam wisata pilihan seperti wisata pantai, wisata edukasi dan wisata yang menguji adrenalin kita. Untuk berkunjung ke objek wisata yang ada di kota malang, anda bisa menggunakan jasa sewa mobil malang batu. Mereka siapa mengantarkan dan menemani perjalanan anda menuju objek wisata yang diinginkan. Para sopir dari rental mobil di kota malang batu ini sudah handal dan teruji keprofesionalitasannya. Info tentang sewa mobil malang, rental mobil di malang baca disini.

    Bandara juanda di surabaya merupakan bandar terbesar dan tersibuk kedua di Indonesia. Setiap harinya banyak yang datang dan pergi. Di bandara juanda juga terdapat jasa sewa mobil surabaya yang siap mengantarkan anda ke tempat tujuan di jawa timur. Rental mobil di juanda surabaya ini memberikan harga sewa mobil yang tidak terlalu mahal. Anda tinggal memilih paket sewa mobil yang terbaik. Informasi sewa mobil di surabaya, rental mobil murah surabaya klik sewa mobil kota surabaya.

    Kota Jogja juga merupakan kota ramai yang setiap harinya selalu dikunjungi pendatang dari luar daerah. Jika anda ada urusan kerja di jogja dan membutuhkan sewa mobil di jogja untuk durasi harian, anda bisa menghubungi kantor kami. Rental mobil jogja di tempat kami mengutamakan kepuasan pelanggan dan armada mobil yang disewakan juga yang terbaru. Sewa mobil jogja kami harus beserta sopir yang berpengalaman. Tempat sewa mobil jogja, rental mobil di jogja, rent car jogja murah baca link ini.

    Info paket wisata gunung bromo dan paket wisata malang batu bisa anda dapatkan dengan harga yang murah dan berbagai fasilitas menarik. Harga paket wisata gunung bromo midnight hanya 299.000 rupiah dan peserta minimal 6 orang (satu mobil). Paket wisata bromo ini akan mengunjungi 4 tempat di sekitar bromo, yaitu puncak penanjakan, pasir berbisik, kawah bromo dan bukit teletubbies. Meeting point paket wisata bromo ini bisa dari kota malang atau kota surabaya. Info paket wisata bromo, paket wisata gunung bromo, paket wisata bromo dari malang, paket wisata bromo dari surabaya baca paket wisata bromo murah.

    ReplyDelete