我在我的数据库控制器类上创建一个便捷方法,该方法旨在为另一个项目提供两个子项目。这就是它的样子。
+ (void)getLeft:(out MySubItem *)left
right:(out MySubItem *)right
forItem:(MyItem *)item
{
...
left = aResult;
right = anotherResult;
}
在使用此方法的所有情况下,左侧和右侧都是强大的属性。
[Database getLeft:self.leftItem right:self.rightItem forItem:anItem];
这有问题吗?静态分析器也抱怨,因为左边和右边的声明永远不会被读取(死存储),我希望能够解决这个...
答案 0 :(得分:3)
这就是我使用块来解决同样问题的方法。语法有点丑陋,但我也一般都试图避免使用指针。
+ (void)valuesForItem(MyItem *)item completion:(void (^)(MySubItem *left, MySubItem *right))completion
{
...
completion(l, r);
}
[Database valuesForItem:anItem completion:^void(MySubItem *left, MySubItem *right){
self.leftItem = left;
self.rightItem = right;
}];
答案 1 :(得分:1)
更新:正如@JohnGibb在评论中提到的,一个更好的模式是根本不使用延迟加载。延迟初始化,特别是当它可能非常昂贵时,会产生非确定的行为,可能需要稍后重构,因为它会导致响应性打嗝或任何其他问题。
最好将加载与各种项目的使用分开。
不要使用pass-by-reference。并且不要使用块(除非您要构建一个通用的对象图遍历/访问模式,其中“访问者”块实际上非常方便 - 但这里不需要这样做。)
在leftItem
课程中添加rightItem
和MyItem
方法。这避免了pass-by-reference,保留了封装,因为MyItem
类现在负责所述关系(包括在子类中启用覆盖),这很简单,并且意味着调用者可以轻松选择仅向左或向右,根据需要。
更典型的OO模式:
@interface MyItem : SomeClass
@property(readonly) MySubItem *leftItem;
@property(readonly) MySubItem *rightItem;
@end
@implementation MyItem
- (void) loadUpDaStuff
{
...
}
- (MySubItem*) leftItem
{
if (self.notLoaded) [self loadUpDaStuff];
return _leftItem;
}
- (MySubItem*) rightItem
{
if (self.notLoaded) [self loadUpDaStuff];
return _rightItem;
}
或者,如果加载非常昂贵,则使用加载方法+完成块。
答案 2 :(得分:0)
你想要的是改变self.leftItem的值,所以你应该使用self.leftItem的地址(它是MySubItem *)作为参数,所以你应该使用MySubItem **
。
试一试:
+ (void)getLeft:(out MySubItem **)p_left
right:(out MySubItem **)p_right
forItem:(MyItem *)item
{
...
*p_left = aResult;
*p_right = anotherResult;
}
和
MySubItem *l = nil ;
MySubItem *r = nil ;
[Database getLeft:&l right:&r forItem:anItem];
self.leftItem = l ;
self.rightItem = r ;
更新:我找到了一个不需要两步的解决方案...我认为self.leftItem和self.rightItem是强大的属性,如果没有,请改用__weak。
+ (void)getLeft:(out NSObject * __strong *)p_left
right:(out NSObject * __strong *)p_right
forItem:(NSObject *)item
{
*p_left = nil;
*p_right = nil;
}
不能使用self.leftItem,而是使用_leftItem。
[Database getLeft:&_leftItem right:&_rightItem forItem:anItem];