Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone UIView作为字典键?_Iphone_Objective C_Uiview_Nsdictionary_Nscopying - Fatal编程技术网

Iphone UIView作为字典键?

Iphone UIView作为字典键?,iphone,objective-c,uiview,nsdictionary,nscopying,Iphone,Objective C,Uiview,Nsdictionary,Nscopying,我想要一个NSDictionary,它可以从UIViews映射到其他内容 但是,由于UIView没有实现NSCopying协议,因此我不能将它们直接用作字典键。您可以使用一个NSValue来保持指向UIView的指针,并将其用作键NSValues 可复制。但是,如果视图被破坏,NSValue将保存一个 垃圾指针。以下是实际代码(基于Yar的进一步建议): 虽然这并不是它们的真正目的,但您可以使用以下方法快速创建一个功能字典式的界面: 您甚至可以将其封装在一个类之类的东西中,即使用不可压缩的键;在

我想要一个
NSDictionary
,它可以从
UIView
s映射到其他内容


但是,由于UIView没有实现
NSCopying
协议,因此我不能将它们直接用作字典键。

您可以使用一个
NSValue
来保持指向
UIView
的指针,并将其用作键<代码>NSValues 可复制。但是,如果视图被破坏,
NSValue
将保存一个 垃圾指针。

以下是实际代码(基于Yar的进一步建议):


虽然这并不是它们的真正目的,但您可以使用以下方法快速创建一个功能字典式的界面:

您甚至可以将其封装在一个类
之类的东西中,即使用不可压缩的键;在这种情况下,您可能希望保留用作关键点的视图

类似这样(未经测试):

#导入“ThingWhatactSlikeAditionary,但带有不可复制的密钥.h”
#进口
静态字符关联u键;
@实现方式:什么是TactSlikeAdictionary,但具有不可复制的密钥
-(void)setObject:(id)obj forKey:(id)键
{
//如果obj为nil,但某些内容已被删除,则删除关联并释放密钥
//先前设定
如果(!obj){
if([self-objectForKey:key]){
objc_setAssociatedObject(键和关联键,nil,objc_关联保留);
[按键释放];
}
返回;
}
[保留钥匙];
//obj的保留/释放由关联对象功能处理
objc_setAssociatedObject(键和关联键、obj、objc_关联_RETAIN);
}
-(id)objectForKey:(id)键
{
返回objc_getAssociatedObject(键和关联键);
}
@结束

*名称可能需要一些工作。

与其存储指向视图的指针并冒垃圾问题的风险,不如给UIView一个标记并将标记的值存储在字典中。更安全。

我在Objective-C++提供的ARC下使用一个简单的解决方案

MyClass.mm:

#import <map>

@implementation MyClass
{
    std::map<UIView* __weak, UIColor* __strong> viewMap;
}

- (void) someMethod
{
    viewMap[self.someView] = [UIColor redColor];
}
#导入
@MyClass的实现
{
地图视图地图;
}
-(无效)某种方法
{
viewMap[self.someView]=[UIColor redColor];
}
在本例中,我通过使所有值都必须是
UIColor*
来进行更强的类型检查,这正是我所需要的。但是,如果希望允许任何对象作为值,也可以使用
id
作为值类型,例如:
std::map viewMap同样适用于键:
id\u弱,id\u强>视图映射


您还可以根据需要更改
\uuuu strong
\uuuu弱
属性。在我的例子中,视图已经由我使用的视图控制器保留,因此我认为没有必要使用强指针指向它们。

如果您在iOS 6之前不需要支持,NSMapTable(建议的)工作得很好,因为它可以在集合中的键上提供枚举器。对于所有文本字段通用的代码来说,这很方便,例如设置委托或将文本值与NSUserDefaults实例双向同步

在viewDidLoad中

self.userDefFromTextField = [NSMapTable weakToStrongObjectsMapTable];
[self.userDefFromTextField setObject:@"fooUserDefKey" forKey:self.textFieldFoo];
[self.userDefFromTextField setObject:@"barUserDefKey" forKey:self.textFieldBar];
// skipped for clarity: more text fields

NSEnumerator *textFieldEnumerator = [self.userDefFromTextField keyEnumerator];
UITextField *textField;
while (textField = [textFieldEnumerator nextObject]) {
    textField.delegate = self;
}
在视图中,将显示:

NSEnumerator *keyEnumerator = [self.userDefFromTextField keyEnumerator];
UITextField *textField;
while (textField = [keyEnumerator nextObject]) {
    textField.text = [self.userDefaults stringForKey:[self.textFields objectForKey:textField]];
}
在文本字段中:应更改字符范围:替换字符串:

NSString *resultingText = [textField.text stringByReplacingCharactersInRange:range withString:string];
if(resultingText.length == 0) return YES;

NSString *preferenceKey = [self.textFields objectForKey:textField];
if(preferenceKey) [self.userDefaults setString:resultingText forKey:preferenceKey];
return YES;

现在我要哭了,因为我在意识到我的iOS 5.1应用程序无法使用它之前实现了所有这些NSMapTable是在iOS 6中引入的。

一个简单的解决方案,当您只想将
UIView
作为键时,我偶尔会使用它来存储
UILabel
UIColor

NSArray<UIView *> *views = @[viewA,viewB,viewC,viewD];
NSArray *values = @[valueA,valueB,valueC,valueD];

for(int i = 0;i < 4;i++) {
    UIView *key = views[i];
    id value = values[i]
    //do something
}

id value = values[[views indexOfObject:key]]
NSArray*views=@[viewA、viewB、viewC、viewD];
NSArray*values=@[valueA,valueB,valueC,valueD];
对于(int i=0;i<4;i++){
UIView*键=视图[i];
id值=值[i]
//做点什么
}
id值=值[[views indexOfObject:key]]

Relevant:这听起来是个非常糟糕的主意。除非你没有意识到数据可能会变成垃圾(正如公认的答案所指出的那样)。@Yar可能像关联对象一样?你也可以使用
CFDictionary
NSHashMap
难以置信!我打算使用一个NSNumber,将UIView的哈希值作为一个int。我认为这更好。现在使用ARC时,您必须使用
valueWithNonretainedObject
@Yar。以下是Luviere和您自己建议的实际代码:NSMapTable也提供了这一点。c、 f.
[NSMapTable weaktostrongobjects可接受]
如何检查视图是否已解除分配?这是一个很好的解决方案!
NSEnumerator *keyEnumerator = [self.userDefFromTextField keyEnumerator];
UITextField *textField;
while (textField = [keyEnumerator nextObject]) {
    textField.text = [self.userDefaults stringForKey:[self.textFields objectForKey:textField]];
}
NSString *resultingText = [textField.text stringByReplacingCharactersInRange:range withString:string];
if(resultingText.length == 0) return YES;

NSString *preferenceKey = [self.textFields objectForKey:textField];
if(preferenceKey) [self.userDefaults setString:resultingText forKey:preferenceKey];
return YES;
NSArray<UIView *> *views = @[viewA,viewB,viewC,viewD];
NSArray *values = @[valueA,valueB,valueC,valueD];

for(int i = 0;i < 4;i++) {
    UIView *key = views[i];
    id value = values[i]
    //do something
}

id value = values[[views indexOfObject:key]]