21

I heard lazy loading technique quite helpful to increase the performance of the programme. I am developing games for iPhone. I am not sure how is the way to apply lazy loading in objective C. Could anyone show me the example please?

Thanks in advance

nevan king
  • 112,709
  • 45
  • 203
  • 241
Rocker
  • 1,467
  • 5
  • 14
  • 20

4 Answers4

31

The general pattern for lazy loading is always more or less the same:

- (Whatever *)instance
{
    if (_ivar == nil)
    {
        _ivar = [[Whatever alloc] init];
    }
    return _ivar;
}
  1. In your class, add an ivar of the type you need, and initialize that to nil in the constructor;
  2. Create a getter method for that ivar;
  3. In the getter, test for nil. If so, create the object. Otherwise, just return the reference to it.
Adrian Kosmaczewski
  • 7,956
  • 4
  • 33
  • 59
  • If you want to be able to set it as well, can you use @property and @synthesize? If so, what attributes (eg, nonatomic, strong, etc) do you assign the properties? – avance Jul 02 '13 at 23:14
  • 1
    `@synthesize` is no longer required as of the latest versions of Xcode, but yes, you can always define a `@property` and later override the setter and getter in your class implementation. The attributes (strong, weak, etc) should only be used then to reflect your own implementation; the compiler will you your code instead of generating any. Hope this helps. – Adrian Kosmaczewski Jul 08 '13 at 14:55
  • Are there any really easy libraries that help you achieve this? – fatuhoku Jan 23 '15 at 14:33
6

Here's an example of lazy loading from the Core Data template:

- (NSManagedObjectModel *)managedObjectModel
{
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
    return managedObjectModel;
}

The first time the managedObjectModel is asked for, it is created by the code. Any time after that, it already exists (!= nil) and is just returned. That's one example of lazy loading. There are other kinds, such as lazy loading of NIB files (loading them into memory only when they're needed).

nevan king
  • 112,709
  • 45
  • 203
  • 241
4

This would be the appropriate way according to Apple. I agree with them for multiple reasons:

  • An static variable inside a method will persist over multiple calls.
  • The dispatch_once function of GDC will guarantee that the given code block will only run once.
  • It's thread-safe.

Objective-C:

- (AnyClass*)instance {

    static AnyClass *shared = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        shared = [[AnyClass alloc] init];
    });

    return shared;
}
Igor Silva
  • 141
  • 1
  • 9
3

In your *.h class isDragging_msg and isDecliring_msg these 2 is BOOL value. and Dict_name NSMutableDictionary.

In view did load

Dict_name = [[NSMutableDictionary alloc] init];

In cell for row at index path

if ([dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]) 
{ 
    cell.image_profile.image=[dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
}
else
{
    if (!isDragging_msg && !isDecliring_msg)
    {
        [dicImages_msg setObject:[UIImage imageNamed:@"Placeholder.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]];
        [self performSelectorInBackground:@selector(downloadImage_3:) withObject:indexPath];
    }
    else
    {
        cell.image_profile.image=[UIImage imageNamed:@"Placeholder.png"];
    }
}

and for download image the function is:-

-(void)downloadImage_3:(NSIndexPath *)path
{
    NSAutoreleasePool *pl = [[NSAutoreleasePool alloc] init];

    NSString *str=[here Your image link for download];

    UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]]; 

    [dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"image name or image link same as cell for row"]];

    [tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

    [pl release];
}

and at last put these methods in your class

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    isDragging_msg = FALSE;     
    [tableview reloadData];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    isDecliring_msg = FALSE;
    [tableview reloadData]; 
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    isDragging_msg = TRUE;
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    isDecliring_msg = TRUE; 
}
Muhammad Rizwan
  • 3,470
  • 1
  • 27
  • 35