Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize a property in iOS UITableViewController

I am working on a UITableViewController

@interface GinkgoDeliveryOrdersTableViewController : UITableViewController

@property PFQuery * query;
@property NSArray * products;

@end

How shall I initialize these two properties? Currently, I am doing lazy initialization:

@implementation GinkgoDeliveryOrdersTableViewController

@synthesize query = _query;
@synthesize products = _products;

- (void) initQuery {
    _query = [PFQuery queryWithClassName:@"_Product"];
}

- (void) initProducts {
    if(! _query)
        [self initQuery];
    _products = [_query findObjects];
}

As a result, every time I want to use these two properties, I have to do something like this:

if(! self.products)
        [self initProducts];

and

if(! self.query)
        [self initQuery];

I feel I am doing something wrong here. Is there a cleaner way to do this? Thank you very much!

like image 831
Ra1nWarden Avatar asked Nov 25 '13 19:11

Ra1nWarden


2 Answers

If the values are not being set from the outside then they shouldn't be read/write properties. Make them read-only and use lazy loading in the "getter" method.

@interface GinkgoDeliveryOrdersTableViewController : UITableViewController

@property (nonatomic, readonly) PFQuery * query;
@property (nonatomic, readonly) NSArray * products;

@end


@implementation GinkgoDeliveryOrdersTableViewController

@synthesize query = _query;
@synthesize products = _products;

- (PFQuery *)query {
    if (!_query) {
        _query = ...
    }

    return _query;
}

Do the same for the products getter.

Note that in your original code there was no need for the @synthesize lines but in this updated code they are needed because otherwise the ivar wouldn't be auto generated due to the explicit getter method.

like image 77
rmaddy Avatar answered Oct 24 '22 11:10

rmaddy


When you create a @property the compiler creates setters and getters for you automatically.

// Let's say you create a public property in your header file (.h)
@property NSObject *var;

// You synthesize your property in your implementation file (.m)
@synthesize var = _var;

// What does the compiler creates for you?
// A getter that by default has the same name as your variable 
- (NSObject *)var
{
    return _var;
}

// A setter that by default is called "set" + "Var" (your variable name with first letter in uppercase)
- (void)setVar:(NSObject *)var
{
    _var = var;
}

Lazy instantiation is a design pattern where you chose to wait until the very last moment to instantiate your objects. So, in your case, it would be in the getter. When someone tries to read a property that was not yet used it is time to instantiate them :D

This is what I think you want :D

// GinkgoDeliveryOrdersTableViewController.h
@interface GinkgoDeliveryOrdersTableViewController : UITableViewController

@property PFQuery *query;
@property NSArray *products;

@end

// GinkgoDeliveryOrdersTableViewController.m
@implementation GinkgoDeliveryOrdersTableViewController

@synthesize query = _query;
@synthesize products = _products;

// SETTERS
- (void)setQuery:(PFQuery *)query {
    _query = query;
}

- (void)setQuery:(NSArray *)products {
    _products = array;
}

// GETTERS
- (PFQuery *)query {
    if (!_query)
        _query = [PFQuery queryWithClassName:@"_Product"];

    return _query;
}

- (NSArray *)products {
    if (!_products)
        _products = [_query findObjects];

    return _products;
}
  • @synthesize for primitive types allocates the space required for the variable.
  • @synthesize for pointers to objects allocates the space required for the pointer only. You have to allocate and initialize your property.
  • Do not use _var outside of setters and getters. Use self.var instead.
  • you can change the default name for your setter and getter

@property (nonatomic, strong, setter=setVariable:, getter=getVariable) NSObject *var;

  • rmaddy has the perfect answer... but I had mine saved as a draft already... I'll be faster to answer next time...
like image 4
GabrielOshiro Avatar answered Oct 24 '22 12:10

GabrielOshiro