我正在使用KVC来序列化NSObject
并尝试将其保存到NSUserDefaults
,这给了我一个Attempt to insert non-property value
当我尝试存储我的时候NSDictionary
.
以下是相关对象的属性MyClass
:
@interface MyClass : NSObject
@property (copy,nonatomic) NSNumber* value1;
@property (copy,nonatomic) NSNumber* value2;
@property (copy,nonatomic) NSString* value3;
@property (copy,nonatomic) NSString* value4;
@property (copy,nonatomic) NSString* value5;
@property (copy,nonatomic) NSString* value6;
@property (copy,nonatomic) NSString* value7;
@property (copy,nonatomic) NSString* value8;
@end
Run Code Online (Sandbox Code Playgroud)
什么时候保存MyClass,它出现在这里:
-(void)saveMyClass
{
NSArray* keys = [NSArray arrayWithObjects:
@"value1",
@"value2",
@"value3",
@"value4",
@"value5",
@"value6",
@"value7",
@"value8",
nil];
NSDictionary* dict = [self dictionaryWithValuesForKeys:keys];
for( id key in [dict …
Run Code Online (Sandbox Code Playgroud) 以下哪项更快,为什么?
CGFloat sum = 0;
for (UIView *v in self.subviews)
sum += v.frame.size.height;
Run Code Online (Sandbox Code Playgroud)
要么
CGFloat sum = [[self.subviews valueForKeyPath:@"@sum.frame.size.height"] floatValue];
Run Code Online (Sandbox Code Playgroud) 我创建了一个具有float属性的NSView子类,我想在Interface Builder中设置它.在"用户定义的运行时属性"部分中,唯一合适的类型是"数字".但是如果我想输入一个十进制数(使用.或者作为分隔符),它只会舍入到最接近的整数.这是一个错误还是故意的?如何定义浮点数而不是整数?
我有一个类型的对象,id
并想知道它是否包含给定的值keyPath
:
[myObject valueForKeyPath:myKeyPath];
Run Code Online (Sandbox Code Playgroud)
现在,我将它包装到一个@try{ } @catch{}
块中,以避免在找不到给定的keypath时出现异常.有没有更好的方法来做到这一点?检查给定的密钥路径是否存在而不处理异常?
非常感谢,
斯特凡
在一个nsobject中,你有一个属性"keyPath",你想要观察自己并使用它
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:nil];
Run Code Online (Sandbox Code Playgroud)
上述行是否会导致保留周期?
我提出这个问题是因为我想知道它是否是重写一堆setter函数的可行替代方案.
memory-leaks objective-c key-value-observing kvc retain-cycle
在我通过Monotouch切换到iOS开发之前,我使用ObjectiveC玩了一下.从那时起,我就开始关注"键值编码"(KVC).我从来没有理解它有什么好处,它背后的魔力是什么.
根据我的理解,它只是一个名称和值的集合,比如.NET NameValueCollection
:而不是设置anObject.Address = "An address Value"
你会写anObject.Properties["Address"] = "An address value"
.大.所以呢?因为这对我来说太容易了,我敢肯定不可能.
或者是因为.NET具有反射,因此不需要像键值编码那样的东西?我可以获取" anObject
" 的类型并使用反射来循环其所有属性并查找名为"Address"的那个,然后使用反射来设置值.这可能是KVC的类比吗?
我希望有人在ObjC和C#/ .NET中担任专业人员,他可以向我解释一下它带来的好处以及它将如何转化为.NET.请不要只指向Apple的文档.我知道这一切.我试图通过不了解KVC来查明我的编码生活中是否遗漏了某些东西?或者我是否可能在.NET中使用类似的东西而不知道如果我使用ObjC它会转换为KVC?
我无法弄清楚@UnionOfObjects提供的简单valueForKey:或valueForKeyPath:不能做什么.
@unionOfObjects运算符返回一个数组,该数组包含由运算符右侧的键路径指定的属性中的不同对象.与"@distinctUnionOfObjects"不同,不会删除重复的对象.以下示例返回事务中事务的收款人属性值:
Run Code Online (Sandbox Code Playgroud)NSArray *payees = [transactions valueForKeyPath:@"@unionOfObjects.payee"];
由此产生的收款人阵列包含以下字符串:绿色电力,绿色电力,绿色电力,汽车贷款,汽车贷款,汽车贷款,通用电缆,通用电缆,通用电缆,抵押贷款,抵押贷款,抵押贷款,动物医院.
在上面的例子中,
NSArray *payees = [transactions valueForKey:@"payee"];
Run Code Online (Sandbox Code Playgroud)
将返回相同的值数组,但代码更少.我错过了什么?
假设我们有一个person类型的对象,它有一个名为name的属性.
Person *p;
[p setValue:@"John" forKey:@"name"];
Run Code Online (Sandbox Code Playgroud)
这很好用.我想要做的是深入挖掘.假设类人员有另一个名为address的属性,该属性是Address类,并且有一个名为zipcode的字段.
是否有一种更简单的方法来分配这个人的邮政编码?也许更清洁,更清晰的东西?
[[p valueForKey:@"address"] setValue:@"234567" forKey:@"zipcode"];
Run Code Online (Sandbox Code Playgroud) 这是一个谜:
我调用setPrimitiveValue:forKey:
上NSManagedObject
.关键是对象的合法,持久,建模属性.但是,setPrimitiveValue:forKey:失败,通常为不同的任意属性设置值.文档说在调用setPrimitiveValue:forKey:
未建模的密钥时会出现这种行为.所以似乎Core Data认为密钥是未建模的.
奇怪的部分:
当密钥被硬编码为字符串文字时,原始值确实成功设置.它只在键是变量时失败.我正在使用的变量恰好从keyPath
参数传递observeValueForKeyPath:ofObject:change:context:
该keyPath
变量与字符串文字相同.isEqual:
返回true并且哈希值相等.的keyPath
变量的类型的__NSCFString
.有谁知道为什么setPrimitiveValue:forKey:
会有不同的表现?(此行为在OS X 10.9.1上)
更新信息更新:
行为不当的密钥追溯到从磁盘上的文件加载的字符串.以下示例是一个孤立的案例.如果将属性字符串"mainAttr"写入磁盘并重新读入,则setPrimitiveValue:forKey:
设置错误属性的值,而不是"mainAttr".
核心数据对象:
@interface Boo : NSManagedObject
@property (nonatomic, retain) NSNumber * mainAttr;
@property (nonatomic, retain) NSNumber * attr1;
@property (nonatomic, retain) NSNumber * attr2;
@property (nonatomic, retain) NSNumber * attr3;
@end
Run Code Online (Sandbox Code Playgroud)
-
#import "Boo.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSManagedObjectContext *context = managedObjectContext(); …
Run Code Online (Sandbox Code Playgroud) 我很高兴找到Swift 3的实现#keyPath()
,这将消除拼写错误并在编译时强制执行关键路径实际存在.比手动键入字符串要好得多.
https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md
class MyObject {
@objc var myString: String = "default"
}
// Works great
let keyPathString = #keyPath(MyObject.myString)
Run Code Online (Sandbox Code Playgroud)
在斯威夫特的文档列表类型被传递到#keyPath()
作为"属性名称".
属性名称必须是对Objective-C运行时中可用的属性的引用.在编译时,键路径表达式由字符串文字替换.
是否可以单独保存此"属性名称",然后传递#keyPath()
给创建一个字符串?
let propertyName = MyObject.myString // error. How do I save?
let string = #keyPath(propertyName)
Run Code Online (Sandbox Code Playgroud)
是否支持要求属于特定类型的属性名称?
// something like this
let typedPropertyName: MyObject.PropertyName = myString // error
let string = #keyPath(typedPropertyName)
Run Code Online (Sandbox Code Playgroud)
最终目标将与需要NSExpression
关键路径的API进行交互.我想编写方便的方法,将有效的属性名称作为参数,而不是随机密钥路径字符串.理想情况下,由特定类型实现的属性名称.
func doSomethingForSpecificTypeProperty(_ propertyName: MyObject.PropertyName) {
let keyPathString = #keyPath(propertyName)
let expression = NSExpression(forKeyPath: keyPathString)
// ... …
Run Code Online (Sandbox Code Playgroud) kvc ×10
objective-c ×5
ios ×4
iphone ×3
.net ×1
c# ×1
coding-style ×1
collections ×1
core-data ×1
ios5 ×1
ipad ×1
key-value ×1
keypaths ×1
memory-leaks ×1
nsdictionary ×1
retain-cycle ×1
swift ×1
xamarin.ios ×1
xcode ×1