2015-04-30 3 views
0

В настоящее время я работаю над iOS-приложением, использующим Swift. У меня есть пользовательский DataSource, который должен знать тип модели, который он должен предоставить. У меня есть собственный протокол, который имеет один метод.Swift Compiler SegFault при инициализации объекта из типа

protocol JSONModel { 
    init(json: JSON) 
} 

Затем существует несколько моделей, реализующих протокол. Все они имеют разные свойства, но в любом случае одинаковы.

class CurrentDownload: JSONModel { 

    let someProperty: String 

    required init(json: JSON) { 
     someProperty = json["someProperty"].stringValue 
    } 

} 

Моя DataSource имеет свойство, которое имеет тип JSONModel.Type

private let modelClass: JSONModel.Type 

Когда я пытаюсь инициализировать новый экземпляр моего modelClass я получаю ошибку сегментации. Инициализация модели осуществляется с помощью

let model = modelClass(json: modelJSON) 

К сожалению, компилятор сработает на этой линии.

Swift Compiler Error 
Command failed due to signal: Segmentation fault: 11 
1. While emitting IR SIL function 

@_TFC14pyLoad_for_iOS21RemoteTableDataSourceP33_56149C9EC30967B4CD75284CC9032FEA14handleResponsefS0_FPSs9AnyObject_T_ for 'handleResponse' at RemoteTableDataSource.swift:59:13 

Есть ли у кого-нибудь идея о том, как исправить это или о том, как обойти эту проблему?

+0

Попробуйте перезагрузить xcode. – Thellimist

+0

Благодарим вас за ответ. Я попытался перезапустить Xcode, но, к сожалению, это не исправило мою проблему. – naglerrr

+0

Если вы скопировали этот фрагмент кода из сети, попробуйте переписать его вручную. Могут быть символы спецификации. Это могут привести к дополнительным значениям. – Thellimist

ответ

1

Я считаю, что эта проблема не слишком сложна.

Обычно с ошибками сегментации Swift возникают, когда вы пытаетесь установить значение константы (let) или пытаетесь установить значение того, что не было объявлено должным образом.

я могу обнаружить один такой экземпляр здесь:

required init(json: JSON) { 
    bytesLeft = json["someProperty"].stringValue 
} 

Там две вещи неправильно с этим примером. У вас есть (назначенный) инициализатор, который заканчивается без установки свойства someProperty, и вы не указали переменную bytesLeft.


Итак, теперь проблема (которую я действительно должен был замечен раньше), что * modelClass * только не является класс (или иначе Инициализационным типа). Чтобы не иметь прямого доступа к протоколу, вы можете получить доступ только к классу, соответствующему протоколу. Компилятор не заметил этого, потому что вы сделали что-то скрытое с . Тип.

Когда я говорю о доступе, я имею в виду функции и свойства, включая инициализаторы. Только класс может создать экземпляр класса, который сам по себе является типом экземпляра, а протоколы не могут иметь экземпляры bonafide. Если вы тщательно об этом подумаете, невозможно точно определить, что вы пытаетесь сделать здесь.Предположим, что мы имели протокол

protocol JSONModel { 
    init(json: JSON) 
} 

но два класса:

class CurrentDownload: JSONModel { 
    let someProperty: String 
    required init(json: JSON) { 
     //Some other code perhaps. 
     someProperty = json["someProperty"].stringValue 
    } 
} 

class FutureDownload: JSONModel { 
    let differentProperty: String 
    required init(json: JSON) { 
     //Different code. 
     differentProperty = json["differentProperty"].stringValue 
    } 
} 

тогда как раньше можно было бы утверждать, что

JSONModel.Type(json: JSON) 

(этот код эквивалентен код) должен составить и запустить, потому что мы дали реализацию init, теперь мы не можем отрицать, что есть путаница - какую реализацию мы должны использовать здесь? Он не может выбрать один, и большинство из них утверждают, что он не должен пытаться, и это не так.

Что вам нужно сделать, это инициализировать какой-то класс. Если вы ищете минимальный класс, который придерживается JSONModel и не более, вам нужно написать такой класс, например.

class BasicJSONModel: JSONModel { 
    let someProperty: String 
    required init(json: JSON) { 
     //Some other code perhaps. 
     someProperty = json["someProperty"].stringValue 
    } 
} 

Затем сделайте

private let modelClass: BasicJSONModel//.Type not needed with a class 

let model = modelClass(json: modelJSON) 

, конечно, это, вероятно, глупо и один может просто написать

let model = BasicJSONModel(json: modelJSON) 

Или вы могли бы просто написать общий суперкласс, если только использовать протокол является для этого:

class SuperJSONModel { 
    let someProperty: String//This is not needed of course and you could just strip down to the init only. 
    init(json: JSON) { 
     //Some other code perhaps. 
     someProperty = json["someProperty"].stringValue 
    } 
} 

, а затем вы хотите проверить, что какой-то объект «соответствует» тому, что было JSONModel, вы просто проверяете, что это подкласс SuperJSONModel.

+0

Большое спасибо за ваш ответ. К сожалению, ошибка, которую вы spottet делаете только при копировании источника в stackoverflow. Эта ошибка отсутствует в моем коде. Я исправил свой первоначальный вопрос, чтобы исправить это. Извините! – naglerrr

+0

Был другой взгляд. Вот так.^:) –

+0

Спасибо за ваш обширный ответ. Теперь я использую общий суперкласс, и все работает так, как ожидалось. Однако с этим подходом есть некоторые неприятности. 1) Все подклассы должны вызвать super.init (json: json) в своих инициализаторах. 2) Существует суперкласс с пустым инициализатором, и кто-то может инициализировать этот суперкласс. Суперкласс должен быть абстрактным и никогда не быть инициализирован напрямую. – naglerrr

 Смежные вопросы

  • Нет связанных вопросов^_^