我刚开始看看Objective-C和Cocoa,以便玩iPhone SDK.我对C malloc和free概念感到相当舒服,但Cocoa的引用计数方案让我很困惑.一旦你理解了它,我就被告知它非常优雅,但我还没有超过驼峰.
怎么办release,retain和autorelease工作有什么关于他们使用的约定?
(或者失败了,你读了什么帮助你得到它?)
我正在努力完成这个难题.
__strong是所有Objective-C可保留对象指针的默认值,如NSObject,NSString等.这是一个强大的参考.ARC -release在范围的末尾与a平衡.
__unsafe_unretained等于旧的方式.它用于弱指针而不保留可保留对象.
__weak就像__unsafe_unretained不同之处在于它是一个自动归零弱引用这意味着该指针将零一旦引用的对象被释放被设置为.这消除了悬空指针和EXC_BAD_ACCESS错误的危险.
但到底有什么__autoreleasing好处呢?我很难找到关于何时需要使用此限定符的实际示例.我相信它只适用于期望指针指针的函数和方法,例如:
- (BOOL)save:(NSError**);
Run Code Online (Sandbox Code Playgroud)
要么
NSError *error = nil;
[database save:&error];
Run Code Online (Sandbox Code Playgroud)
在ARC下必须以这种方式声明:
- (BOOL)save:(NSError* __autoreleasing *);
Run Code Online (Sandbox Code Playgroud)
但这太模糊了,我想完全理解为什么.我找到的代码片段将__autoreleasing放在两颗星之间,这对我来说很奇怪.类型是NSError**(一个指针指向NSError),那么为什么要放在__autoreleasing星星之间而不是简单地放在前面NSError**呢?
此外,可能还有其他必须依赖的情况__autoreleasing.
它说,在WWDC14演示文稿的第17页上
使用Objective-C?还是要管理自动释放池
autoreleasepool {/*code*/}
那是什么意思?这是否意味着如果我的代码库没有任何Objective-C文件,autoreleasepool {}是不必要的?
在一个相关问题的答案中,有一个例子autoreleasepool可以是有用的:
- (void)useALoadOfNumbers {
for (int j = 0; j < 10000; ++j) {
@autoreleasepool {
for (int i = 0; i < 10000; ++i) {
NSNumber *number = [NSNumber numberWithInt:(i+j)];
NSLog(@"number = %p", number);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果上面的代码被autoreleasepool删除后转换成Swift ,那么Swift是否足够聪明,知道该number变量应该在第一个之后发布}(就像其他语言一样)?
今天,我已经将我的xCode更新为4.2版本,而且我想禁用ARC,我也用谷歌搜索.但无法解决我的问题.根据搜索结果,在目标设置中,我找不到'Objective-C自动引用计数'项,因此没有机会将其设置为NO.我逐个找到该项目,并使用搜索字段.
一个人知道最新的Xcode4.2,如何禁用项目的ARC,而不是特定的文件.
非常感谢.
我是Xcode 4.2的新手,我还没有完全掌握ARC的速度.但是,我确实读到@autoreleasepool取代了自动释放池的手动使用,并且在引擎盖下做了一些特殊的魔法来与ARC玩得很好.
然而,当我在Xcode 4.2中启动一个新项目时,特别关闭了ARC选项,我仍然在模板代码中获得了@autoreleasepool语句.
这是什么交易?
autorelease用于返回的函数对象,因此调用者不会获得所有权,被调用者将来会释放该对象.
但是,ARC能够计算调用者的所有权并在使用后释放它,也就是说,它可以像C++中的智能指针一样行为.使用ARC,它可以摆脱自动释放,因为自动释放是非确定性的.
我问这个问题的原因是我确实看到返回的对象在ARC中比非ARC代码更早地调用dealloc.这让我认为ARC可以像Smart Pointer一样,并且可以使autorelease无用.这是真的还是可能的?我唯一可以考虑自动释放有用的是多线程或网络代码,因为在对象传递时计算所有权可能并不容易.
谢谢你的想法.
这是一个新的编辑,使事情清楚:
与自动释放
+ (MyClass*) myClass
{
return [[[MyCClass alloc] init] autorelease];
}
- doSomething
{
MyClass *obj = [MyClass myClass];
}
Run Code Online (Sandbox Code Playgroud)
使用ARC:
+ (MyClass*) myClass
{
return [[MyCClass alloc] init]; // no autorelease
}
- doSomething
{
MyClass *obj = [MyClass myClass];
// insert [obj release]
}
Run Code Online (Sandbox Code Playgroud)
所以,我们真的不需要自动释放.
memory-management reference-counting objective-c ios automatic-ref-counting
我想澄清一些事情.
可以说我有以下代码:
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
for (int i = 0; i < 5000000; i++) {
NSString *s = [NSString stringWithFormat:@"Hello, %@!", @"World"];
}
}
Run Code Online (Sandbox Code Playgroud)
这将在此函数调用中创建500万个自动释放的字符串.我希望这可以保留这些对象直到应用程序终止,因为我看到的唯一的@autoreleasepool是在main.m中包装应用程序实例化的那个.但事实并非如此.在这个函数调用结束时,它们似乎都被调用了它们并从内存中删除.
这个文件:
"应用程序工具包在事件循环的每个循环开始时在主线程上创建自动释放池,并在最后将其排出,从而释放处理事件时生成的任何自动释放的对象."
这对我来说很有意义,但这是在UIKit下,而不是Application Kit.我的问题是,UIKit/Cocoa Touch在这种情况下做了同样的事情,还是有另一种解释我的对象被释放?
谢谢!
我对Apple材料感到困惑.
我们通过3种方式管理内存,它们是:
我怀疑自动参考计数和手动参考计数之间的区别是什么.
有人可以解释一下吗?
iphone garbage-collection memory-management automatic-ref-counting
我写了一些Objective-C似乎工作得很好的应用程序,除了不断增长的内存占用.我在最新版本的Xcode 4.6.2下使用ARC.我的系统是10.7.5.
我很新Objective-C,需要一些帮助来弄清楚我的记忆是怎么回事.我已经将问题缩小到解释为什么以下基本代码行为与它一样.
此代码添加在Xcode提供的基于Cilla的基于Cocoa的应用程序模板中(启用了ARC).
案例A.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
NSDate* d;
for(int i=0; i<1000000; i++){
d = [[NSDate alloc] init];
}
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期进行,ARC即时回收内存.即,内存使用历史非常平坦.当for循环结束时,该应用程序需要大约25MB的内存.
案例B
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
NSDate* d;
for(int i=0; i<1000000; i++){
d = [NSDate date];
}
}
Run Code Online (Sandbox Code Playgroud)
这里的事情对我来说真的很神秘.当刚刚运行应用程序时,(实际)内存使用量不断增加到大约53MB,然后永远保持在那里.
但是,在运行分配探查器工具时,我可以看到在for循环结束时,所有对象都被释放,非常像您对自动释放池所期望的那样.此外,用@autoreleasepool {}括起for循环的主体使得案例B的行为类似于案例A(如预期的那样).
那么,三个问题:
[NSDate date]和alloc init对象有什么区别?(我认为这里的其他问题几乎没有.)我正在使用ARC和应用程序崩溃说收到内存警告.我直接在设备(iPhone 4与iOS 7.0.2)上测试应用程序,并使用iOS 6的SDK的XCode 5编译.我使用过苹果乐器,我分配了大约20MB的LiveBytes.

4-5分钟后,我的应用程序有30mb的内存.

在设备上编译和测试应用程序后,我会在几分钟之后看到崩溃,就在内存警告消息之后.为什么不使用仪器发生碰撞?但是我试图将这个问题清除一个月并且不能得到礼物,我真的需要帮助.看起来我没有任何泄漏,但我找不到哪里出错了.提前感谢任何建议.
我的应用程序在具有0.5GB内存的设备上崩溃.但是,在Xcode中分析内存使用情况 - 它很少超过140MB.我用过仪器来检查泄漏,没有一个是重要的.
但是,当我运行我的应用程序时,"其他进程"使用的内存总是非常高.这是发射后的休息状态:
我在代码的循环的每个循环中添加了1秒的延迟,并发现在每个循环中,"其他进程"每个对象增加大约3MB的内存使用量,直到在0.5GB设备上,它耗尽并崩溃.
这个问题表明这些是使用该内存的其他应用程序,但我关闭了所有其他应用程序,其用法与我的循环代码直接相关.
什么可以在其他进程中使用内存,实际上是在我的应用程序中运行?为什么我的"其他进程"耗尽了这么多内存?
为了了解我正在做什么,我从Parse中提取数据,然后遍历返回的每个对象并从数据中创建SKNode子类对象.我将此节点添加到数组(供参考)和场景.这是我在主线程上做的代码,添加了延迟.NB线:
self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];
Run Code Online (Sandbox Code Playgroud)
是一个BFTask,所以异步.而且我将数组分成更小的批次,因此我可以看到增量内存使用量,因为每个批次都被绘制.如果我试图立刻绘制整个批次,OOM会立即发生......
- (void)drawNewRelationships
{
_batches = [NSMutableArray array];
_index = 0;
[_playerMini fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) {
[ParseQuery getNewRelationshipsForMini:_playerMini current:_miniRows.relationshipIds withBlock:^(NSMutableArray *newRelationships) {
_batches = [self batchArrays:3 fromArray:newRelationships];
_index = 0;
[self drawBatches];
}];
}];
}
- (void)drawBatches
{
if ([_batches objectAtIndex:_index]) {
[self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];
_index++;
if (_index < [_batches count]) {
[self performSelector:@selector(drawBatches) withObject:nil afterDelay:1];
}
}
}
Run Code Online (Sandbox Code Playgroud)
该节点包含其他数据(几个数组,自定义对象),我尝试运行应用程序并删除所有数据.我试过在主线程和后台线程上运行.我尝试过使用BFTask来异步处理事情.我尝试的所有内容都以相同的行为结束 - 创建这些SKNode对象会在"其他进程"中占用内存,直到在低内存设备上崩溃.
值得注意的是,这种行为自iOS9以来才开始发生.
基本上,什么可以在"其他过程"中使用所有这些内存,我如何释放它?
更新 …
memory-management instruments parse-platform sprite-kit ios9
我已阅读如何在 Xcode Instruments 中演示内存泄漏和僵尸对象?但这是针对 Objective-c 的。这些步骤不适用。
通过阅读这里,我了解到僵尸是以下物体:
不太确定这与访问已释放的对象有何不同。
我的意思是在 Swift 中你可以这样做:
var person : Person? = Person(name: "John")
person = nil
print(person!.name)
Run Code Online (Sandbox Code Playgroud)
人员被解除分配了吗?是的!
我们是否试图指出这一点?是的!
那么有人可以分享导致创建悬空指针的最常见错误吗?
如果我想创建一个UIImage,那么下面两行代码的区别是什么:
UIImage *img = [UIImage imageWithCGImage:cgImage];
UIImage *img = [[UIImage alloc] initWithCGImage:cgImage];
Run Code Online (Sandbox Code Playgroud)
这只是"同一个目的,不同手段"的案例吗?
objective-c ×6
ios ×3
xcode ×3
iphone ×2
swift ×2
cocoa ×1
cocoa-touch ×1
crash ×1
debugging ×1
instruments ×1
ios5 ×1
ios9 ×1
memory ×1
nszombie ×1
sprite-kit ×1
xcode4.2 ×1