Проблема, которая будет описана, относится к моему предыдущему вопросу: string .withCString и UnsafeMutablePointer(mutating: cstring), завернутые в функцию, которая была моим первым подходом к обработке нулевых строк (путем помещения withCString в функцию) и к вопросу, который задал Меки: Почему я не могу передать необязательную строку Swift в функцию C, которая разрешает указатели NULL?
Представьте, что есть c-функция, например:
unsigned long randomSign(char *pin, char *tag_signature, char *tag_data, char *xyz);
Я знаю, что функция работает правильно, если я оборачиваю 4 замыкания string.withCString вокруг соответствующей быстрой функции:
// pin, tag_signature, tag_data and xyz are optional Strings so they may be nil which is a problem for my result.
// corresponding swift function:
// randomSign(pin: UnsafeMutablePointer<Int8>!, tag_signature: UnsafeMutablePointer<Int8>!, tag_data: UnsafeMutablePointer<Int8>!, xyz: UnsafeMutablePointer<Int8>!)
let result = pin.withCString { s1 in return
tag_signature.withCString {s2 in return
tag_data.withCString {s3 in return
xyz.withCString { s4 in return
randomSign(UnsafeMutablePointer(mutating: s1), UnsafeMutablePointer(mutating: s2), UnsafeMutablePointer(mutating: s3), UnsafeMutablePointer(mutating: s4))
}}}}
Итак, Мартин R ответил на более простой пример, что нет необходимости оборачивать замыкания вокруг randomSign(arguments) и UnsafeMutablePointer (мутируя: ...), потому что он также может брать строки и преобразовывать их. Но когда я опускаю замыкания и использую их, как описано Мартином Р, это работало при первом запуске на симуляторе сразу после запуска mac, но при последовательных вызовах randomSign-Function возврат скажет мне, что, например, tag_signature или пин-код будут недействительными (но на самом деле они действительны, и я не знаю почему?!).
Это приводит меня к проблеме, что мне нужны замыкания withCString (на данный момент), но я должен обрабатывать nil-Strings, что приведет к сбою приложения, когда оно должно вернуть результат, потому что оно не может оценить randomSign-Function.
Поэтому я попытался подогнать приведенный ниже подход (также предложенный @Martin R) к Swift 3, но я не тренировался, чтобы адаптировать его.
//Swift-2 written by Martin R
protocol CStringConvertible {
func withCString<Result>(@noescape f: UnsafePointer<Int8> throws -> Result) rethrows -> Result
}
extension String: CStringConvertible { }
extension Optional where Wrapped: CStringConvertible {
func withOptionalCString<Result>(@noescape f: UnsafePointer<Int8> -> Result) -> Result {
if let string = self {
return string.withCString(f)
} else {
return f(nil)
}
}
}
//Swift 3: ???
Если кто-нибудь может сказать мне, почему моя функция работает только тогда, когда я использую withCString, а не когда я ее отклоняю, я был бы очень благодарен, а также, если кто-нибудь знает, как решить проблему, т.е. правильно перевести код swift-2 в работающий swift -3 код.