2015-08-31 1 views
2

Я медленно переношу свою кодовую базу в Свифт и натолкнулся на странный сбой, где я заполняю AutoreleasingUnsafeMutablePointer<String?> с помощью строки, отличной от нуля. Вот некоторые сократили код:AutoreleasingUnsafeMutablePointer <String?> crash - ошибка в компиляторе?

extension String { 
    func getRegexVariableNamed(name: String, forRegexString regexString: String) -> String? { 
     /** ... **/ 
     return "TO BE IMPLEMENTED".lowercaseString // Using lowercase to prevent the compiler from inlining 
    } 
} 

class XYZ { 
    func extractInformation(info1: AutoreleasingUnsafeMutablePointer<String?>, info2: AutoreleasingUnsafeMutablePointer<String?>, info3: AutoreleasingUnsafeMutablePointer<String?>, info4: AutoreleasingUnsafeMutablePointer<String?>, fromSource source: String) -> Bool { 
     guard let vp = source.getRegexVariableNamed("ID", forRegexString: "vp=(?P<ID>\\d+)") else { 
      return false 
     } 

     info4.memory = vp 
     info1.memory = "ABC" 
     info2.memory = "DEF" 
     info3.memory = "GHI" + vp 
     return true 
    } 
} 

// Code in playground 
let obj = XYZ() 

let info1 = AutoreleasingUnsafeMutablePointer<String?>() 
let info2 = AutoreleasingUnsafeMutablePointer<String?>() 
let info3 = AutoreleasingUnsafeMutablePointer<String?>() 
let info4 = AutoreleasingUnsafeMutablePointer<String?>() 
if !obj.extractInformation(info1, info2: info2, info3: info3, info4: info4, fromSource: "") { 
    print("NO") 
}else{ 
    print("YES") 
} 

приложение (и то же самое относится и к детской площадке) падает с error: Playground execution aborted: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

Это исключение происходит по настройке строку в AutoreleasingUnsafeMutablePointer в методе extractInformation(...).

Я хотел проверить, не делаю ли я что-то неправильно здесь, прежде чем сообщать об этом как об ошибке для Apple.

BTW Я использую последнюю версию Xcode 7 beta (6) на OS X 10.10.5.

PS: Я знаю, что более быстрый подход будет заключаться в том, чтобы создать метод, который возвращает структуру вместо использования этих указателей автоопределения, но, как уже упоминалось, я медленно перемещаюсь из ObjC, поэтому мне это нужно (на данный момент) для обратной совместимости.

+0

Поскольку никто, кажется, не может указать на проблему в коде, а не на компилятор, я отправил эту ошибку Apple. –

ответ

1

С Xcode 7.0.1 я могу заставить ваш код работать с некоторыми изменениями.

Прежде всего, в Using Swift with Cocoa and Objective-C (Swift 2) руководстве («Autoreleasing указатели» глава), это говорит о том, что функция объявлена ​​как принимая AutoreleasingUnsafeMutablePointer<Type> может принять inout выражение того же Type.

Таким образом, код может быть изменен следующим образом:

let info1: String? 
let info2: String? 
let info3: String? 
let info4: String? 
if !obj.extractInformation(&info1, info2: &info2, info3: &info3, info4: &info4, fromSource: "") { 
    print("NO") 
}else{ 
    print("YES") 
} 

Но, это все еще не работает.

Тем не менее, на этой же странице в нем говорится, что AutoreleasingUnsafeMutablePointer<Type> применяется для класс Тип отображения. Я не знаю, является ли это причиной того, что он не работает, трудно угадать, что происходит позади, но если вы замените String на NSString, вы получите результат.

extension String { 
    func getRegexVariableNamed(name: String, forRegexString regexString: String) -> String? { 
     /** ... **/ 
     return "TO BE IMPLEMENTED".lowercaseString // Using lowercase to prevent the compiler from inlining 
    } 
} 

class XYZ { 
    func extractInformation(info1: AutoreleasingUnsafeMutablePointer<NSString?>, 
          info2: AutoreleasingUnsafeMutablePointer<NSString?>, 
          info3: AutoreleasingUnsafeMutablePointer<NSString?>, 
          info4: AutoreleasingUnsafeMutablePointer<NSString?>, 
          fromSource source: String) -> Bool { 
     guard let vp = source.getRegexVariableNamed("ID", forRegexString: "vp=(?P<ID>\\d+)") else { 
      return false 
     } 

     info4.memory = vp 
     info1.memory = "ABC" 
     info2.memory = "DEF" 
     info3.memory = "GHI" + vp 
     return true 
    } 
} 

// Code in playground 
let obj = XYZ() 

var info1: NSString? 
var info2: NSString? 
var info3: NSString? 
var info4: NSString? 
if !obj.extractInformation(&info1, info2: &info2, info3: &info3, info4: &info4, fromSource: "") { 
    print("NO") 
}else{ 
    print("YES") 
    info1    // "ABC" 
    info2    // "DEF" 
    info3    // "GHIto be implemented" 
    info4    // "to be implemented" 
} 
+0

Интересно, что он работает с NSString - так как даже чистый код Swift со String не работает. В конце концов я переписал все классы, которые использовали этот материал в Swift, и вложил все переменные в структуру, поэтому это уже не проблема. Но это определенно одна из проблем, которые заставляют меня думать, что Swift просто еще не готов к производству - как и большинство технологий Apple, они начинают использоваться через 2 года после введения ... –