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!
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.
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._var outside of setters and getters. Use self.var instead.@property (nonatomic, strong, setter=setVariable:, getter=getVariable) NSObject *var;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With