- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
问题
在我的arc项目中,我有一个管理对象的类,名为LazyMutableArray
。有些对象实际上是nil,但我的集合的用户永远不会知道这一点;因此,我将它设为NSMutableArray
的子类,它尝试执行“相同的操作”。特别是,对象在添加时被保留。
现在让我们看看其他方法的内存行为。原来NSArray
销毁方法是documented by Apple的一个例外,因为它们释放的不是自动释放的对象。
关于addObject:
+objectAtIndex:
+数组销毁的组合是否被苹果记录为永远不会自动删除,或者只是碰巧出现在我测试的示例和苹果包含的示例中,存在一些争论。
如何在子类中创建具有完全相同内存语义的方法?
最后更新
经过一番思考,我决定在这种情况下,基于NSMutableArray
的实现比基于NSPointerArray
的实现更合适。我要注意的是,新的类与前一个实现具有相同的retain
/autorelease
对。
多亏了rob napier,我发现对objectAtIndex:
方法的任何修改都不会改变这种行为,这回答了我最初关于这种方法的问题。
在实践层面上,一些人说任何方法都可以无缘无故地处理一对额外的retain
/autorelease
对;期望其他方法是不合理的,试图找出哪些方法做到了这一点,哪些没有做到这一点也是不合理的。这对我来说是一个很好的学习机会。
代码(基于NSMutableArray
)可在github获得:implementation,header,test(即-testLazyMutableMemorySemantics
)。
谢谢大家的参与。
为什么我试图将NSMutableArray
子类化:
我同意,子类化基础对象并不总是一个合适的解决方案。在这种情况下,我有对象(事实上,odata资源),其中大多数都有子对象。子对象数组最自然的类显然是NSArray
。在我看来,换一个班似乎没什么意义。
但是对于odata集合,这个“子对象数组”作为nsarray,必须有不同的实现。具体地说,对于1000个元素的集合,鼓励服务器以批(比如)20的形式返回集合,而不是一次返回所有集合。如果有其他模式适合这种情况,我洗耳恭听。
我是怎么找到这个的
我对这个集合进行了单元测试,可以将值放入数组,从数组中读取,等等。到目前为止,还不错。但是,我意识到返回对象会增加其保留计数。
我怎么看?假设我在lazy数组中插入两个对象,一个弱保持,一个强保持(参见代码*)。然后按预期,retain count oflazy
为1。但现在我读到元素:
XCTAssertEqual(weakSingleton, lazy[0], @"Correct element storage"); // line B
weakSingleton
可能会给我错误的信息,所以让我们尝试通过
lazy[0] = nil; // yep, does the right thing
XCTAssertNil(weakSingleton, @"Dropped by lazy array"); // line C <-- FAIL
-retainCount
没有被释放。
weakSingleton
来释放
@autorelease
。这一对的确切来源并不明显,但似乎来自
weakSingleton
(不幸的是,并非来自arc的
NSPointerArray -addPointer:
)。但是,我不想返回一个自动释放的对象,并使方法语义不同于它的超类!
[[object retain] autorelease]
所描述的行为本质上是,通过读取索引0处的对象,我实际上正在更改此对象的保留计数,这意味着我可能会遇到意外的错误。
@implementation LazyMutableArray {
NSPointerArray *_objects;
// Created lazily, only on -setCount:, insert/add object.
}
- (id)objectAtIndex:(NSUInteger)index {
@synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
// otherwise do something else to compute a return value
// but this branch is never called in this test
[self.delegate array:self missingObjectAtIndex:index];
@synchronized(self) {
if (index >= self.count) {
return nil;
}
__weak id object = [_objects pointerAtIndex:index];
if (object) {
return object;
}
}
@throw([NSException exceptionWithName:NSObjectNotAvailableException
reason:@"Delegate was not able to provide a non-nil element to a lazy array"
userInfo:nil]);
}
- (void)createObjects {
if (!_objects) {
_objects = [NSPointerArray strongObjectsPointerArray];
}
}
- (void)addObject:(id)anObject {
[self createObjects];
[_objects addPointer:(__bridge void*)anObject];
}
// Insert two objects into lazy array, one held weakly, one held strongly.
NSMutableArray * lazy = [LazyMutableArray new];
id singleton = [NSMutableArray new];
[lazy addObject:singleton];
__weak id weakSingleton = singleton;
singleton = [NSMutableDictionary new];
[lazy addObject:singleton];
XCTAssertNotNil(weakSingleton, @"Held by lazy array");
XCTAssertTrue(lazy.count == 2, @"Cleaning and adding objects");
// @autoreleasepool {
XCTAssertEqual(weakSingleton, lazy[0], @"Correct element storage");
XCTAssertEqual(singleton, lazy[1], @"Correct element storage");
// }
lazy = nil;
XCTAssertNotNil(singleton, @"Not dropped by lazy array");
XCTAssertNil(weakSingleton, @"Dropped by lazy array");
[LazyMutableArray -objectAtIndex]
或取消注释
lazy = [NSMutableArray new]
,则成功。
最佳答案
首先,我不会做这个子类。这正是NSPointerArray
的作用。把它包装成
NSArray
包含空值,那么
[NSArray arrayWithArray:lazyMutableArray]
的正确行为是什么?假设
lazyMutableArray
永远不能包含NULL的算法需要警惕这一事实。确实,你可以得到类似的处理不保留的
NSArray
作为
CFArray
;我从经验中说这就是为什么这种子类非常危险(为什么我几年前就不再这么做了)。不要创建一个子类,该子类不能在其超类可以使用的所有情况下使用(
LSP)。
如果您有一个具有新语义的集合,我将从
NSArray
对其进行子类化,并使其符合
NSObject
。看看
<NSFastEnumeration>
如何不是
NSPointerArray
的子类。这不是意外。面对同样的问题,注意苹果选择的方向。
到目前为止,你可能猜到它不仅仅是一个保留,它是自动保存的——在B行周围放置一个@ AutoReleLoad释放弱SuntLon。这似乎是因为A行的下弧转换为[[对象保留]自动释放]。但是,我不想返回一个自动释放的对象并让调用者记住这一点!
打电话的人不应该有其他的想法。调用方从不自由地假定方法不添加平衡的自动删除。如果来电者希望自动释放池耗尽,那是他们的责任。
所有这些都是说,如果不需要额外的自动操作,有一些好处,这是一个有趣的学习机会。
我将首先把这段代码简化为最简单的形式,完全不使用您的子类。只需探索
NSArray
的工作原理:
__weak id weakobject;
@autoreleasepool
{
NSPointerArray *parray = [NSPointerArray strongObjectsPointerArray];
{
id object = [NSObject new];
[parray addPointer:(__bridge void*)object];
weakobject = object;
}
parray = nil;
}
NSAssert(!weakobject, @"weakobject still exists");
NSPointerArray
,而不是通过arc修改接口。
关于objective-c - 如何在子类中复制NSArray内存语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19883056/
我正在尝试提升我的 javascript 编程技能(或者说我的编程技能时期 :)) 所以我试图理解一些语义: 第一行的“?”是什么意思?均值和“-distance”中的减号 第二行中的“+=”或“-=
我正在尝试在语义 UI 中执行复选框,但它不起作用,我无法弄清楚我做错了什么。 我包括jquery、semantic.min.js、checkbox.js 和semantic.min.css,然后我添
我正在构建一个 Spring 后端。我有一个 Controller ,它获取一个“搜索对象” - 一个具有 10 个字段的对象,其中只有一个应该被填充,所以搜索功能(我没有编写,但需要对其进行更改和重
我面临着编写更智能/高级的“相关内容”算法的挑战,并且不知道从哪里开始,所以我决定提出一个问题,是否有人会指出我正确的方向。 我们的数据库包含很多文章,到目前为止,我们使用关键字/标签查询了相关文章,
我正在尝试将通用字符串写入Rust中的数字函数,其中支持的类型为i16,i32,i64,u32,u64,f32和f64。 最初我有这个: fn str_to_num(s: &str, default_
假设我们在 hpp 文件中有一个带有唯一指针的简单结构: struct SomeType { SomeType() = default; ~SomeType(); st
这是同一预处理指令的多个问题。 1 - <> 还是 ""? 除了在 MSDN 中找到的信息: #include Directive (C-C++) 1.a:这两种符号有什么区别? 1.b:所有编译器都
所以基本上我有一个带有列表的简单系统,当我选择一个项目时,它会显示描述和绑定(bind)到该项目的图像。 项目:https://jsfiddle.net/jhnjcddh/2/ 问题是我需要在 JS
很抱歉问了一个愚蠢的问题,但有人能告诉我以下是什么意思吗 for ctype, (codename, name) in searched_perms: 我不明白括号里是怎么回事。 for ctype
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why do all these crazy function pointer definitions al
我正在学习 HTML5,并获得了一个将 CSS Zen Gardens 转换为 HTML5 语义版本的项目。我已经能够轻松地转换其中的大部分内容,但是底部的链接/导航给我带来了一些问题。 转换此/处理
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
我一直在我的 emacs c/c++ 开发设置中试验 cedet 和语义,除了一个小细节外,我对它非常满意。 我使用 ede-cpp-root-project 创建一个项目,并给出我的项目的根目录以及
引用问题自http://www.garfieldtech.com/blog/put-up-with-put (这是针对 Drupal 开源项目的,有点元,因为这里没有代码): GET、HEAD 和 P
我有以下代码。 let v_blue = UIView() v_blue.backgroundColor = UIColor.blueColor() l
我目前正在 objc.io 上阅读优秀的 Advanced Swift 书籍,但遇到了一些我不明白的问题。 如果您在操场上运行以下代码,您会注意到在修改字典中包含的结构时,下标访问会生成一个副本,但随
谁能给我一个关于 Flutter 上下文中语义概念的清晰解释(或链接)(它实际上是什么,何时使用,更新...)? 我在谷歌上搜索了很多,但到目前为止还没有找到任何好的解释。 非常感谢, 最佳答案 Di
这是我的代码 Was this what you wanted? It's good to see you again.
我有一个侧边栏,其中包含应用程序的主导航。它还包含一个 button 触发侧边栏的打开/关闭。在语义方面,标记应该是什么样的? 我应该把侧边栏放在一边,然后只在周围设置导航吗主导航,不包括打开/关闭触
考虑下面这行 Lisp 代码: (some-function 7 8 | 9) ;; some comment. note the extra indentation 该点位于“8”和
我是一名优秀的程序员,十分优秀!