2014-09-16 3 views
6

я мог бы создать экземпляр класса из строки в примере ObjC.For, я определил новый класс DBCell через подклассы UITableViewCell, и я создаю экземпляр класса от имени этих правил:Как создать экземпляр класса и init из строки в Swift?

DBCell *cell=[tableView dequeueReusableCellWithIdentifier:cellClassname]; 
    if (cell==nil) { 
     Class cellClass=NSClassFromString(cellClassname); 
     cell=[cellClass alloc]; 
     cell=[cell initWithStyle:cellStyle reuseIdentifier:cellClassname]; 
    } 

Теперь мне нужно перенести коды Swift, я пересмотрели класс DBCell в Swift:

class DBCell: UITableViewCell { 
    var label:String? 
    var key:String? 
    var managedObject:NSManagedObject? 
    var delegate:AnyObject? 
    convenience override init(style: UITableViewCellStyle, reuseIdentifier: String!) { 
     self.init(style: style, reuseIdentifier: reuseIdentifier) 
     self.textLabel.font=UIFont.preferredFontForTextStyle(UIFontTextStyleCaption1) 
     self.backgroundColor=UIColor.blackColor() 
     self.textLabel.backgroundColor=UIColor.blackColor() 
    } 
    } 

Но как я могу создать экземпляр класса и вызывать соответствующую функцию инициализации?

+0

Я чувствую, что ваша проблема вызвана плохой архитектурой, главным образом отсутствием надлежащего использования полиморфизма. Не могли бы вы показать больше своего исходного кода obj-c? В чем разница между разными ячейками? – Sulthan

+0

@Sulthan Это довольно распространенный рисунок какао. Что вы подразумеваете под «правильно используемым полиморфизмом» в этом случае? Дело в том, что имена ячеек хранятся в раскадровке, что довольно удобно и полезно. Вопрос в том, как это сделать при сохранении безопасности типа Swift (и это разумный вопрос). –

ответ

15

Swift более статически типизирован, что делает его намного более безопасным во время работы. Например, если какая-либо из строк неверна, вы потерпите крах (или, в лучшем случае, спокойно ничего не делаете, что может быть хуже, чем сбой), и компилятор не может его поймать.

ОК, но как вы справляетесь с этим шаблоном? Лучший способ, IMO, в Swift должен быть явным и создавать сопоставление.

let cellMapping = [ 
    "DBCell": DBCell.self, 
] 

if let cellClass = cellMapping[cellClassName] { 
    let cell = cellClass(style: cellStyle, reuseIdentifier: cellClassName) 
    // use cell 
} 

Теперь, когда вы реорганизовать и изменить название DBCell, но пропустить строку в раскадровку, все будет просто продолжать работать, как и ожидалось, а не сбой или спокойно неудачу, как это было бы в ObjC.

Свифт действительно умный об этих сопоставлениях тоже. Тип cellMapping выше: [String: DBCell.Type], так что если бы у вас был специальный init для DBCell, он был бы доступен. Но если ваш словарь выглядел как:

let cellMapping = [ 
    "DBCell": DBCell.self, 
    "OtherCell": UITableViewCell.self 
] 

то тип [String: UITableViewCell.Type]. Swift автоматически определяет наиболее специфический класс, который охватывает все значения. Если вы добавили тип в этот список, который не использовал какой-либо метод, который вы действительно используете, Swift может поймать его во время компиляции. И если вы сделали ошибку, и добавил что-то даже не вид ячейки таблицы:

let cellMapping = [ 
    "DBCell": DBCell.self, 
    "OtherCell": UITableViewCell.self, 
    "BadCell": UICollectionViewCell.self 
] 

затем Swift даст вам время компиляции предупреждение о том, что вы создали AnyObject. Это действительно приятно писать безопасный, но гибкий код, все за стоимость словаря.

+0

Спасибо, это сработало! – user1190178

+0

Есть ли способ создать сопоставление ячеек, чтобы эта работа работала с разными типами? –

+0

Я не понимаю вопроса. Вы должны задать новый вопрос SO с подробностями конкретной проблемы. –