【问题标题】:Store additional associated infomation in a UIView在 UIView 中存储其他相关信息
【发布时间】:2012-07-20 15:08:39
【问题描述】:

我在 SO 上阅读了很多关于 Gesture Recognizers 的文章 - 并设法编写了一个工作代码,当在 UIImage 上识别出长按时,会出现一个操作表:

{ ...
 UILongPressGestureRecognizer *longPressWall = [[[UILongPressGestureRecognizer alloc]
                                                               initWithTarget:self     action:@selector(deleteImage:)] autorelease];
                     longPressWall.minimumPressDuration = 0.4;
                     l.userInteractionEnabled=YES;
                     [l addGestureRecognizer:longPressWall];
... }


-(void)deleteImage:(UILongPressGestureRecognizer*)sender { 
    if(UIGestureRecognizerStateBegan == sender.state) {
        UIActionSheet *as = [[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:@"Close" destructiveButtonTitle:@"Delete Screenshot" otherButtonTitles: nil];
        [as showInView:masterView];
        [as release];
    }
}

因此,在这种情况下,向 Selector deleteImage: 发送信息有点棘手。 我想在调用 deleteImage 时向服务器发送 HTTP 请求,所以我需要一些来自视图的信息。

是否可以将信息存储到UIImageView 并从sender.view.myinfo 中检索(例如)?

【问题讨论】:

  • 也许你可以使用 imageView.tag 来存储一些带有数字的信息。
  • 在 MVC 世界中,您通常不希望在视图中“存储信息”。如果你想跟踪这样的事情,你可能会在你的控制器中跟踪它,或者更好的是,你的控制器使用的模型。因此,也许您有一些 NSMutableArray 来跟踪已删除的项目,并且在您删除时,从视图中删除图像(或者如果您不想删除它,则可能会使其变暗,直到您从服务器获得确认)然后让您的控制器在您用来跟踪这些内容的数组中添加已删除的项目。或类似的东西。
  • 虽然您确实不应该在视图中存储数据,但正如@nielsbot 所描述的那样,将指向数据的指针挂在它们上是很自然的。在这种情况下使用 objc_setAssociatedObject 不会违反 MVC,只要关联对象真的只是指向“关联对象”(它是模型的一部分)的指针。
  • @RobNapier 同意。当我看到人们滥用这一点时,它只会让我不寒而栗,在他们的视图中存储各种模型数据,而忽略了各种可能的风险。

标签: iphone objective-c ios xcode


【解决方案1】:

通过扩展,您可以向UIView 添加一个属性来存储您的关联值,如下所示:

import Foundation
import ObjectiveC

extension UIImageView
{
    struct Static {
        static var key = "key"
    }
    var myInfo:AnyObject? {
        get { 
            return objc_getAssociatedObject( self, &Static.key ) as AnyObject? 
        }
        set { 
            objc_setAssociatedObject( self, &Static.key,  newValue, .OBJC_ASSOCIATION_RETAIN) 
        }
    }
}

现在您可以在代码中的任何位置执行此操作

let anImageView = UIView()

// set your new property on any UIView:
anImageView.myInfo = <some object>

// get your proeprty from any UIView
myImage = anImageView.myInfo

上一个答案(相同的代码,但在 Objective-C 中)&lt;objc/runtime.h&gt; 中查看objc_setAssociatedObject()

我会将其作为一个类别来实现..(ARC 风格)

#import <objc/runtime.h>

@interface UIImageView (MyInfo)
@property ( nonatomic, strong ) id myInfo ;
@end

@implementation UIImageView (MyInfo)

-(void)setMyInfo:(id)info
{
    objc_setAssociatedObject( self, "_myInfo", info, OBJC_ASSOCIATION_RETAIN_NONATOMIC ) ;
}

-(id)myInfo
{
   return objc_getAssociatedObject( self, "_myInfo" ) ;
}

@end

现在你可以这样做了:

UIImage * myImage ;
myImage.myInfo = <some object>

【讨论】:

  • 我应该补充一下——如果有其他方法可以做到这一点,您可以先尝试一下。例如,您可以在网络请求中使用完成块吗?这允许您在创建块时捕获局部变量,并在您的请求完成时使用它们..
  • +1 - 虽然这太棒了(我根本不知道你能做到这一点),但我将不得不奖励 Diederik 的答案,因为它实现起来非常简单。谢谢。
  • 由你决定——尽管我总是喜欢组合(类别)与子类化。避免把自己画到角落里更容易。
  • nielsbot,如果我 #import &lt;objc/runtime.h&gt;,这将有效。我将不再需要使用标签。伟大的! +1
  • 这是在顶部..虽然没有表达为#import 声明..我想我可以改变它......
【解决方案2】:

显而易见的方法是使用 tag 属性。如果您需要更多信息,您始终可以继承 UIImageView 并添加额外的属性。

【讨论】:

  • 标签需要 nint,将项目 ID 存储在其中也对我有用
  • 我们可以在没有子类化的情况下实现这一点吗?可能正在使用 Swizzle 或 Category,但以更有效的方式?我想为此有一个集中的地方,我真的不想用创建的子类替换原始类。
【解决方案3】:

如果你想在你的 UIImageView(或任何 UIView)中存储一个字符串,请尝试以下操作-

在您的视图中设置可访问性标识符,“l”

{
    l.accessibilityIdentifier = @"your string here";
}

从您的手势识别器中获取 UIView,“l”:

-(void)deleteImage:(UILongPressGestureRecognizer*)sender { 
    if(UIGestureRecognizerStateBegan == sender.state) {

    UIView *view = sender.view;
    NSString *storedString = view.accessibilityIdentifier;

    }
}

storedString 是存储在 UIView 中的字符串。希望这对将来的任何人都有帮助!

【讨论】:

  • 你不应该那样做。
  • @shane,应该很明显。 accessibilityIdentifier 旨在用于自动化 UI 测试,而不是用于存储信息。
  • 如果这很明显,也许他不会建议这样做。如果您想成为更好的 stackoverflow 评论者,下次将其包含在您的原始评论中。干杯。
  • 可怜的谢恩。显然,当该属性被称为 -accessibilityIdentifier 时,您不应该在其中存储随机数据,并且 Apfelsaft 不需要进一步解释就可以了。下次要礼貌一点。
【解决方案4】:

不,您不能将信息保存到 imageView 实例中。即使找到 imageView 的可写字符串属性,这也是错误的做法。改为这样做:为 imegeview.tag 属性分配一个订单号,并为信息保留一个 NSMutableDictionary,因此,您将使用 imageView.tag 作为键,而信息将是值。

【讨论】:

  • 其实可以的,看我的回答
  • 对不起,我不熟悉这个
  • 谢谢你说我不称职,这导致我缺乏经验,通过强迫学习
猜你喜欢
  • 1970-01-01
  • 2012-03-26
  • 2015-11-08
  • 2012-01-20
  • 2019-03-11
  • 2018-02-16
  • 1970-01-01
  • 2019-07-31
  • 2012-10-09
相关资源
最近更新 更多