在属性中将属性作为类似指针的参数传递是否安全?

时间:2014-08-08 01:29:57

标签: objective-c

我在我的数据库控制器类上创建一个便捷方法,该方法旨在为另一个项目提供两个子项目。这就是它的样子。

+ (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];

这有问题吗?静态分析器也抱怨,因为左边和右边的声明永远不会被读取(死存储),我希望能够解决这个...

3 个答案:

答案 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课程中添加rightItemMyItem方法。这避免了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];