0

I have a series of images that I want to make use of in an app. What I wanted to do is store them in an NSArray for easy identification within the drawRect: function.

I have created a .plist file, which details an NSDictionary with the keys simply ascending integer values, and the values corresponding to the image file names. This allows me to iterate through the dictionary and add a series of NSImage objects into the array. I am using a for loop here because the order is important and fast enumeration does not guarantee order of execution when reading from a dictionary!

Currently I am doing the following: (This is in a Subclass of NSView)

@property (strong) NSDictionary *imageNamesDict;
@property (strong) NSMutableArray *imageArray;
...

// in init method:

    _imageNamesDict = [[NSDictionary alloc] initWithContentsOfFile:@"imageNames.plist"];

    _imageArray = [[NSMutableArray alloc] initWithCapacity:[_imageNamesDict count]];

    for (int i=0; i<_imageNamesDict.count; i++) {
        NSString *key = [NSString stringWithFormat:@"%d", i];
        [_imageArray addObject:[NSImage imageNamed:[_imageNamesDict objectForKey:key]];
    }

// When I want to draw a particular image in drawRect:

    int imageToDraw = 1;

    // Get a pointer to the necessary image:
    NSImage *theImage = [_imageArray objectAtIndex:imageToDraw];

   // Draw the image
    NSRect theRect = NSMakeRect (100,100, 0, 0);
    [theImage drawInRect:theRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];

This all appears to work properly, but with one quirk. I have noticed a small amount of lag that happens in drawing the display, but only when drawing a new image for the first time. Once each image has been seen at least once, I can re-draw any desired image with no lag whatsoever.

Is it that I am not loading the images properly, or is there some way that I can pre-cache each image when I create the objects to add to the for loop?

Thanks!

tom1990
  • 602
  • 8
  • 17
  • 2
    This won't even run because you've defined _imageArray as an NSMutableDictionary instead of an NSMutableArray. – rdelmar Dec 16 '12 at 23:04
  • 1
    Dictionaries are not ordered relationships. Rather than attempt to force one to be by using keys that are strings that represent numbers that are indexes, why not just use an array? – Peter Hosey Dec 16 '12 at 23:52
  • Oops, thats a typo! Sorry, I will edit the post to correct this! And thats a good point, I am not sure where my logic was to use the NSDictionary rather than the array came from come to think about it! Using an array would make managing the plist easier as well! – tom1990 Dec 18 '12 at 12:36

1 Answers1

2

Assuming you have overcome the "... NSMutableDictionary instead of an NSMutableArray ..." problem pointed out in the comments, you are loading the images properly.

The lag you are describing is because [NSImage imageNamed: ] doesn't do all the work required to draw the image, so that is happening on your first draw.

You could probably get rid of the lag by drawing the images into an offscreen buffer as you add them to your array, something like:

// Create an offscreen buffer to draw in.
newImage = [[NSImage alloc] initWithSize:imageRect.size];
[newImage lockFocus];

for (int i=0; i<_imageNamesDict.count; i++) {
    NSString *key = [NSString stringWithFormat:@"%d", i];
    NSImage *theImage = [NSImage imageNamed:[_imageNamesDict objectForKey:key]];
    [_imageArray addObject: theImage];
    [theImage drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
}
[newImage unlockFocus];
[newImage release];
Smilin Brian
  • 980
  • 8
  • 18
  • Thank you for your answer, I did not realise that was the case! That works fine and prevents the lag I was experiencing. As per the comments above I will change the imageNames to be an NSArray instead, which will also allow me to implement the load loop using fast enumeration. – tom1990 Dec 18 '12 at 12:43