Objective-C 正确复制 NSArray 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2338275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Objective-C copy an NSArray properly?
提问by kbanman
My iPhone app keeps crashing, and I've narrowed it down to this one line over the past bloody week:
我的 iPhone 应用程序不断崩溃,在过去的血腥一周中,我将其范围缩小到这一行:
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
I'm getting the right result from the above, but the app crashes after accessing it (EXC_BAD_ACCESS).
How do I just copy the contents of fetchResultsso that I can play around with it?
我从上面得到了正确的结果,但应用程序在访问它后崩溃 ( EXC_BAD_ACCESS)。我如何只复制 的内容fetchResults以便我可以玩弄它?
I've tried
我试过了
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];
but the only thing that doesn't crash the app is
但唯一不会使应用程序崩溃的是
NSArray *retVal = [[NSArray alloc] initWithArray:nil];
Could someone help me out? I'm thinking I'll need a lesson in Obj-C memory management.
有人可以帮我吗?我想我需要上一堂 Obj-C 内存管理课。
EDIT:Here's a more complete example of code that crashes:
编辑:这是一个更完整的崩溃代码示例:
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSMutableArray *retVal = [NSMutableArray arrayWithCapacity:0];
for(Job *job in fetchResults){
//NSLog(@"dev: %@",job.lastmod_device);
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[job.jobkey copy], @"entitykey",
[NSNumber numberWithInt:[job.lastmod_device timeIntervalSince1970]], @"job_lastmod_device",
[NSNumber numberWithInt:[job.lastmod_server timeIntervalSince1970]], @"job_lastmod_server",
[NSNumber numberWithInt:[job.customer.lastmod_device timeIntervalSince1970]], @"customer_lastmod_device",
[NSNumber numberWithInt:[job.customer.lastmod_server timeIntervalSince1970]], @"customer_lastmod_server",
[NSNumber numberWithInt:[job.productionschedule_lastmod_device timeIntervalSince1970]], @"productionschedule_lastmod_device",
[NSNumber numberWithInt:[job.productionschedule_lastmod_server timeIntervalSince1970]], @"productionschedule_lastmod_server", nil];
//NSLog(@"dict: %@", dict);
[retVal addObject:dict];
}
return retVal;
And the code that calls this method:
以及调用此方法的代码:
NSArray *arr2 = [self retrieveJobs];
(that's it; I never even use the variable)
(就是这样;我什至从不使用变量)
EDIT 2:Even just iterating over the fetched result with an empty for loop and doing nothing else with the fetchResultsobject makes the app crash. How is this even possible?
编辑 2:即使只是用一个空的 for 循环迭代获取的结果并且对fetchResults对象不做任何其他事情也会使应用程序崩溃。这怎么可能?
回答by bbum
You are thrashing; of these lines of code...
你在颠簸;这些代码行...
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];
The latter two are simple leaks. The first is one way of making a copy, but retVal = [fetchResults copy];is a better way to make a copy.
后两个是简单的泄漏。第一种是制作副本的一种方式,但它retVal = [fetchResults copy];是制作副本的更好方式。
But, of course, you don't need a copy at all. That isn't the problem. You go on to say that the only thing that doesn't crash is an empty result set.
但是,当然,您根本不需要副本。那不是问题。您继续说唯一不会崩溃的是空结果集。
That indicates one of two things; either your result set is corrupt (unlikely) or you are accessing the result set incorrectly (likely).
这表明两件事之一;您的结果集已损坏(不太可能),或者您访问的结果集不正确(可能)。
The "thrashing" is that you have asked a question about a crash without including either the backtrace of the crash or the location of the crash. Add those and you'll likely get an answer in short order.
“颠簸”是您提出了有关崩溃的问题,但没有包括崩溃的回溯或崩溃的位置。添加这些,您可能会在短时间内得到答案。
(And don't take offense at "thrashing" -- we all do it. Even after 20+ years of Objective-C, I still have to facepalm, step back, and think things through to get away from thrashing.)
(不要因为“颠簸”而生气——我们都这样做。即使在 Objective-C 使用了 20 多年之后,我仍然需要面对,退后一步,仔细思考以摆脱颠簸。)
回答by Carl Norum
NSArray *retVal = [fetchResults retain]should keep everything around for you. It doesn't make a copy, but I expect that's not really what you're trying to do. Your first attempt there should make a copy. They're all prone to leaking if you're not careful though (your second example leaks guaranteed). Are you sure you're not doing something else in the program that makes this part of the code fail?
NSArray *retVal = [fetchResults retain]应该为你保留一切。它不会复制,但我希望这不是您真正想要做的。你在那里的第一次尝试应该制作一个副本。如果您不小心,它们都容易泄漏(保证您的第二个示例泄漏)。你确定你没有在程序中做其他使这部分代码失败的事情吗?
Here are some options for doing a real copy if that's what you want:
如果这是您想要的,这里有一些用于制作真实副本的选项:
NSArray *retVal = [fetchResults copy];
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
Both of those return retained arrays to you.
这两个都将保留的数组返回给您。
回答by kubi
Are you sure the fetch request is returning data? According to the documentation:
您确定获取请求正在返回数据吗?根据文档:
An array of objects that meet the criteria specified by request fetched from the receiver and from the persistent stores associated with the receiver's persistent store coordinator. If an error occurs, returns nil. If no objects match the criteria specified by request, returns an empty array.
满足由从接收器和从与接收器的持久存储协调器关联的持久存储中提取的请求指定的标准的对象数组。如果发生错误,则返回 nil。如果没有对象与请求指定的条件匹配,则返回一个空数组。
Also, could you show the code where you access the array? Is it in the same method where you're executing the fetch request?
另外,您能否显示访问数组的代码?它是否与您执行提取请求的方法相同?
回答by Manjunath
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];
Are you sure that fetchResults contains result? Because there may be a chance that "fetchResults" object itself released and pointing to some garbage location. That is why you are getting crash. Check and inform whether fetchResults is a valid object or not.
您确定 fetchResults 包含结果吗?因为可能有机会“fetchResults”对象本身释放并指向某个垃圾位置。这就是为什么你会崩溃。检查并通知 fetchResults 是否为有效对象。
回答by Tim Glenn
To get a true copy without a reference to the original, you will need to do a DEEP copy. One method is to archive the array and unarchive it back into an NSArray.
要在不参考原件的情况下获得真正的副本,您需要进行深度复制。一种方法是存档数组并将其解压缩回 NSArray。

