在xcode中收集KVC访问器片段非常方便,因为它们很难手工完成.有没有人一直在使用4一段时间了解如何添加新的?
(...我们现在可以谈谈了,对吧?)
我时不时地注意到,我正在使用一个块来迭代一个集合,而不会写入任何共享数据或导致任何副作用.我考虑添加一个NSEnumerationConcurrent选项,然后决定反对它,因为我不知道什么时候值得使用.
所以我有一个特定的问题,一个更普遍的问题.
第一个问题:这是一个可能稍微有点人为的例子,它使用一个块同时做一些微不足道的事情:
CGFloat GetAverageHeight(NSArray* people)
{
NSUInteger count = [people count];
CGFloat* heights = malloc(sizeof(CGFloat) * count);
[people enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
^(id person, NSUInteger idx, BOOL* stop)
{
heights[idx] = [person height];
}];
CGFloat total= 0.0;
for (size_t i = 0 ; i < count ; i++) total += heights[i];
free(heights);
return total / count;
}
Run Code Online (Sandbox Code Playgroud)
忽略非并发枚举可能只是直接求和高度这一事实,而不需要调用malloc或函数的后半部分,在这里使用NSEnumerationConcurrent有什么意义吗?使用GCD(或任何NSEnumerationConcurrent在后台执行的操作)的开销是否会抵消同时获取平凡属性的收益?在使用NSEnumerationConcurrent值之前,块的工作需要多少微不足道的事情?
第二个问题:更一般地说,当我看到有机会这样做时,我应该考虑并发性(理论上:理论上这些API的重点是它们使并发性不是特殊情况而是更多部分的一般化妆一个程序),或者只是我应该使用的优化,如果我发现了一个特定的性能问题,并认为并发是答案(理由:并发代码中的错误是追踪的噩梦)?
我有一个核心数据实体"bid",它与许多"项目"有关系,称为"itemLink".
在IB中,我有一个文本字段绑定到"总计",这几乎可以工作.
在"bid.m"我有:
- (NSDecimalNumber *)total
{
return [self valueForKeyPath:@"itemLink.@sum.price"];
}
Run Code Online (Sandbox Code Playgroud)
我也有:
+ (NSSet *)keyPathsForValuesAffectingTotal {
return [NSSet setWithObjects:@"itemLink", nil];
}
Run Code Online (Sandbox Code Playgroud)
添加或删除项目时,"总计"按预期更新.但是,如果您更改了itemLink集合中的"项目",则总计不会刷新.如何让KVO查看链接的NSSet中的相关对象何时发生了变化?
谢谢
cocoa core-data objective-c key-value-observing cocoa-bindings
根据NSString的方法文档-UTF8String:
返回的C字符串将自动释放,就像返回的对象将被释放一样; 如果需要将C字符串存储在创建C字符串的自动释放上下文之外,则应复制C字符串.
所以在retain/release内存管理下,有以下方法:
- (const char*) giveMeACString
{
NSString* string = @"I'm a string!";
return [string UTF8String];
}
Run Code Online (Sandbox Code Playgroud)
是好的,只要调用方法处理返回的const char*,就像它自动释放的对象一样.
但是,根据我的意识,在垃圾收集下没有自动释放上下文.并且C类型不是垃圾收集的,因此它看起来不像GC那样会将返回的指针视为返回的对象.
它的生命周期是什么?它是否仍然在线程的runloop中可靠地"稍后"释放,或者它在GC下的行为与非GC下的行为不同?
我正在编写一个工具,可以从知道哪个类的实例变量被声明中受益__weak.
这些信息必须存在于运行时的某个地方,但有没有办法访问它,记录或以其他方式?(这是一个工具,所以我不太关心它打破更新)
据我了解,未实现的方法通过以下方式解决:
这个三步流程定义在哪里?我想自己处理它,因为NSInvocation可能对我的需求来说太重了.我有一个围绕运行时源,并没有真正看到任何东西.
它看起来像旧的运行时会调用前进:args:在接收器上,这样做但似乎已经从新的运行时.我猜这个过程必须由框架而不是运行时定义,因为如果运行时依赖于Cocoa到需要NSInvocation来处理消息的程度,那就太奇怪了.是否可能是在NSObject/NSProxy上调用的无证方法?
编辑:
它看起来像运行时声明,但从未定义,当objc_msgSend找不到实现时调用的C函数:
id objc_msgForward(id object,SEL message,...);
我不为Apple工作,所以我不知道Foundation如何实现这一点,但至少在Cocotron的情况下,他们使用:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,@selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,@selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
Run Code Online (Sandbox Code Playgroud)
添加forwardSelector:arguments:方法似乎不起作用,所以我猜这是特定于Cocotron.有人知道objc_msgForward基金会做了什么吗?
运行时API中有一个未记录的函数,该函数似乎(根据一些玩具程序而定)按照其名称的含义执行操作:
OBJC_EXPORT void objc_disposeClassPair(Class cls)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
Run Code Online (Sandbox Code Playgroud)
但是,详细信息在地面上很少。因此,与其说是一个问题,不如说是更多相关问题的集合:
偶尔使用泛型时,我会收到一条错误消息,指出"_"作为参数.它似乎没有记录.这是什么意思?
举个例子,我得到错误:
Cannot convert value of type 'JawDroppingFeat<Superhero>' to closure result type 'JawDroppingFeat<_>'
Run Code Online (Sandbox Code Playgroud)
当我尝试编译时:
protocol SuperheroType {
typealias Superpower
}
struct JawDroppingFeat<Superhero: SuperheroType where Superhero: Arbitrary, Superhero.Superpower: Arbitrary>: Arbitrary {
let subject: Superhero
let superpowerUsed: Superhero.Superpower
static var arbitrary: Gen<JawDroppingFeat<Superhero>> {
get {
return Gen.zip(Superhero.arbitrary, Superhero.Superpower.arbitrary)
.map{ (x: Superhero, y: Superhero.Superpower) in
JawDroppingFeat(subject: x, superpowerUsed: y)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Gen和Arbitrary类型来自SwiftCheck,相关声明如下:
public struct Gen<A> {
public static func zip<A, B>(gen1: SwiftCheck.Gen<A>, _ gen2: SwiftCheck.Gen<B>) -> SwiftCheck.Gen<(A, B)>
public func map<B>(f: …Run Code Online (Sandbox Code Playgroud) 也许如果调用一个MyClass对某个类型的MyClass不理解的方法是一个错误而不是一个警告,因为它可能是一个错误或将来会导致错误...
但是,为什么这个错误特定于ARC?ARC根据可可内存管理约定决定它需要保留/释放/自动释放的内容,这表明知道选择器的名称就足够了.因此,将SEL变量传递给它是有道理的performSelector:,因为在编译时不知道选择器是否是init/copy/new方法.但为什么在类接口中看到这一点或没有任何区别?
我是否遗漏了ARC的工作方式,或者铿锵警告是否有点不一致?
正如标题所说.如果我这样做,没有立即出错:
- (void) associateSelector:(SEL)value withPointer:(void*)key
{
objc_SetAssociatedObject(self, key, (id) value, OBJC_ASSOCIATION_ASSIGN);
}
Run Code Online (Sandbox Code Playgroud)
是否有充分理由谨慎使用它?
据我所知,在不兼容的函数指针之间进行转换,例如:
void aUnaryFunction(int a1)
{
/* .... */
}
void doSomethingWithFn()
{
typedef void(*BinaryFn)(int, const char*);
BinaryFn aBinaryFunction = (BinaryFn) &aUnaryFunction;
aBinaryFunction (3, "!!!");
}
Run Code Online (Sandbox Code Playgroud)
永远不应该这样做,因为根据C标准,"未定义的行为".
但是我不明白为什么,假设函数调用在C中工作的方式,这个例子是不安全的.我所做的只是无视一个论点.
假设int第一个参数的处理是一致的,所有会发生的是const char*将在doSomethingWithFn()调用时放入寄存器中aBinaryFunction,aUnaryFunction将按预期运行,并且const char*可能会被覆盖aUnaryFunction,但这很好,因为无论如何,别的什么都不会用.
我在这里遗漏了什么,或者这实际上是安全的吗?(或两者之间,或两者兼而有之?)
我正在考虑在我正在编写的库中使用异常进行内部错误处理.如果使用它们,库将使用arc构建并f-objc-arc-exceptions启用.
obj-c异常的一个问题是必须注意不要抛弃任何你不知道的异常安全的代码.编译文件时-fobjc-arc-exceptions,编译器异常添加的枚举代码是否安全?
据我所知,它应该是,因为我看不出有什么理由去做任何需要清理的事情.但如果在某处记录这种行为,我会更乐意使用它.
编辑:我应该澄清,当我说"使用异常进行内部错误处理"时,我说的是非致命错误.所以"异常安全"在这里意味着不应该有内存泄漏,没有未释放的锁等.
cocoa ×10
objective-c ×9
cocoa-touch ×2
c ×1
casting ×1
concurrency ×1
core-data ×1
generics ×1
ios ×1
macos ×1
swift ×1
xcode ×1
xcode4 ×1