Очень раздражает NSPredicate cra sh на iPhone 5 и iPad 4-го поколения с iOS 10.3 - PullRequest
1 голос
/ 18 января 2020

Как видно из названия этого вопроса, ниже мой код падает при инициализации NSPredicate. До сих пор я обнаружил, что сбой происходит только на iPhone 5 и iPad 4-го поколения с iOS 10.3. На других устройствах с таким же iOS 10.3 все ок.

func getPredicate(for serviceId: Int64, startingFrom step: Int) -> NSPredicate {
    let predicate = NSPredicate(format: "serverID == %i AND step == %i AND type == %@", 
                                serviceId, step, "button")
    return predicate
}

Это сообщение в блоге прекрасно описывает мою проблему, и у меня также есть та же проблема сбоя на 32-битных процессорных устройствах. Хотя решения, приведенные в посте, помогли мне прекратить сбой, но CoreData всегда возвращал nil результат, когда я использовал его в запросах на выборку.

Есть ли обходной путь для решения этой проблемы?

Инструменты разработки:

  • Версия XCode: 11.2.1
  • Версия Swift Language: Swift 5
  • Устройства: iPhone 5 и iPad 4-го поколения

1 Ответ

1 голос
/ 18 января 2020

Формат %i предназначен для форматирования значения типа C int, то есть 32-разрядного целого числа на всех текущих iOS платформах. Передача 64-разрядного целого числа вместо (в вашем случае: serviceId) - неопределенное поведение, которое может вызвать cra sh.

Правильный формат для 64-разрядного целого числа - %lli (для long long int), и правильный формат для Int (который может быть 32-разрядным или 64-разрядным) равен %li (для long int).

Так что это работает на обоих 32-разрядных и 64-разрядные устройства:

let predicate = NSPredicate(format: "serverID == %lli AND step == %li AND type == %@",
                            serviceId, step, "button")

«Более простым» способом является преобразование всех чисел в NSNumber, поскольку вам не нужно запоминать правильные форматы для различных целочисленных типов. NSNumber s являются «объектами» (экземплярами класса Objective- C) и могут быть просто отформатированы в формате %@:

let predicate = NSPredicate(format: "serverID == %@ AND step == %@ AND type == %@",
                            serviceId as NSNumber, step as NSNumber, "button")

Передача аргументов в виде argumentArray может работать случайно, но с неправильными форматами это все еще неопределенное поведение.

...