Копия Objective C NSArray правильно?

Мое приложение для iPhone продолжает отказывать, и я сузил его к этой строке за прошлую кровавую неделю:

NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];

Я получаю правильный результат вышеупомянутого, но сбоев приложения после доступа к нему (EXC_BAD_ACCESS). Как я просто копирую содержание fetchResults так, чтобы я мог играть вокруг с ним?

Я попробовал

NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];

но единственная вещь, которая не разрушает приложение,

NSArray *retVal = [[NSArray alloc] initWithArray:nil];

Кто-то мог выручить меня? Я думаю, что мне будет нужен урок в управлении памятью Obj-C.

Править: Вот более полный пример кода, который отказывает:

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;

И код, который называет этот метод:

NSArray *arr2 = [self retrieveJobs];

(вот именно; я даже не использую переменную),

РЕДАКТИРОВАНИЕ 2: Даже просто выполнив итерации по выбранному результату с пустым для цикла и не делая ничто иное с fetchResults объект делает сбой приложения. Как это даже возможно?

6
задан kbanman 26 February 2010 в 11:59
поделиться

4 ответа

Конечно, это не обязательно лямбда. Любая переданная функция, например, приведенная ниже, будет работать

def numeric_compare(x, y):
   if x > y:
      return 1
   elif x == y:
      return 0
   else:  #x < y
      return -1

a = [5, 2, 3, 1, 4]
a.sort(numeric_compare)

Источник: Сортировка Python

Итак, в вашем случае...

def object_compare(x, y):
   if x.resultType > y.resultType:
      return 1
   elif x.resultType == y.resultType:
      return 0
   else:  #x.resultType < y.resultType
      return -1

a.sort(object_compare)

Вышеупомянутая лямбда, безусловно, самый компактный способ сделать это, но есть также использование operator.itemgetter .

import operator
#L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
map(operator.itemgetter(0), L)
#['c', 'd', 'a', 'b']
map(operator.itemgetter(1), L)
#[2, 1, 4, 3]
sorted(L, key=operator.itemgetter(1))
#[('d', 1), ('c', 2), ('b', 3), ('a', 4)]

Таким образом, вы бы использовали itemgetter ("resultType"). (При условии, что определен getitem .)

sorted(L, key=operator.itemgetter('resultType'))
-121--1274574-

Если вы абсолютно настаиваете на шифровании сборки, возможно, лучший способ сделать это - поместить программный код в сборки библиотеки классов и зашифровать их. Затем следует записать небольшой исполняемый файл-заглушку, который расшифровывает сборки в память и выполняет их.

Это очень плохая идея по двум причинам:

  1. Вам придется включить ключ шифрования в свою заглушку. Если 1337 хакер может эффективно использовать ваши отраженные сборки, он может так же легко украсть ваш ключ шифрования и расшифровать их сам. (В основном это Аналоговая дыра )
  2. Никому нет дела до вашего кода 1337. Прости, но это тяжелая любовь. Никто больше не думает, что чей-либо код почти так интересен, как автор.
-121--1399560-

Вы выполняете трэш; из этих строк кода...

NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];

Последние два являются простыми утечками. Первый - это один из способов создания копии, но retVal = [fetchResults copy]; - это лучший способ создания копии.

Но, конечно, вам вообще не нужна копия . Это не проблема. Далее вы говорите, что единственное, что не терпит краха - это пустой результирующий набор.

Это означает одну из двух вещей; либо результирующий набор поврежден (маловероятно), либо доступ к результирующему набору осуществляется неправильно (вероятно).

"Толчок" заключается в том, что вы задали вопрос о крушении, не указав ни обратную трассировку, ни место падения. Добавьте их, и вы, скорее всего, получите ответ в коротком порядке.

(И не обижайтесь на "трэш" - мы все это делаем. Даже после 20 с лишним лет Objective-C, мне все еще приходится идти лицом назад, отступать и продумывать вещи, чтобы уйти от трэша.)

19
ответ дан 8 December 2019 в 05:21
поделиться

Модуль devel может регистрировать запросы.

-121--3320593-

Правильный выбор зависит от целевой архитектуры.

MPI и PVM являются интерфейсами передачи сообщений, которые обычно используются для координации работы между узлами в системах кластерного типа (то есть несколькими независимыми вычислительными узлами с сетевыми соединениями). Потоки в их многочисленных формах используются для распределения работы по нескольким ядрам или процессорам в пределах одного образа системы (т.е. с общей памятью).

Также обратите внимание, что выбор не обязательно является взаимоисключающим. В аспирантуре я написал программу, которая использовала MPI для связи между узлами суперкомпьютера, и использовал pthreads для использования преимуществ SMP на каждом узле. Это не редкость в научных вычислениях.

-121--4180208-

NSArray * retVal = [fetchResults retain] должен держать все вокруг для вас. Он не делает копию, но я ожидаю, что это не то, что ты пытаешься сделать. Они все склонны к утечке, если вы не осторожны, хотя (ваш второй пример утечка гарантирована). Вы уверены, что не делаете что-то другое в программе, что делает эту часть кода неудачной?

Вот некоторые варианты для создания реальной копии, если это то, что вы хотите:

NSArray *retVal = [fetchResults copy];
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];

Оба из этих возвращенных сохраненных массивов для вас.

2
ответ дан 8 December 2019 в 05:21
поделиться

Вы уверены, что запрос на выборку возвращает данные? Согласно документации:

Массив объектов, который соответствует критериям, заданным запросом, полученным от получателя и из постоянных хранилищ, связанных с координатором постоянного хранилища получателя. В случае ошибки возвращает ноль. Если ни один объект не соответствует критериям, указанным в запросе, возвращает пустой массив.

Кроме того, не могли бы вы показать код доступа к массиву? Это тот же метод, в котором вы выполняете запрос на выборку?

1
ответ дан 8 December 2019 в 05:21
поделиться
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]];
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]];

Вы уверены, что fetchResults содержит результат? Потому что может быть вероятность, что сам объект «fetchResults» освободится и указывает на какое-то место для мусора . Вот почему вы терпите крах. Проверьте и сообщите, является ли fetchResults допустимым объектом.

1
ответ дан 8 December 2019 в 05:21
поделиться