2015-01-26 4 views
0

Я пытался сделать это так много, но быстрый компилятор жалуется на все, что я делаю. SourceKit и компилятор также аварийно завершаются, поэтому я больше не могу экспериментировать. Даже не вставлять некоторые println s. Я разрываю волосы.Создание массива типа протокола @objc из массивов конформеров

Я пытаюсь построить простой массив для представления табличного представления. «Строки» - это объекты Presentable, которые представляют собой всего лишь набор протоколов.

import Foundation 

// The protocols are all @objc 
typealias Presentable = protocol<Utterable, Displayable, Departure> 
typealias TableSection = (sectionTitle: String, rows: [Presentable]) 

1. Это не работает:

(buses, metros и т.д., все [Bus]?, [Metro]? и т.д., и эти классы соответствуют всем протоколам, которые Presentable)

private func asContent5() -> [TableSection] 
{ 
    var result: Array<TableSection> = [] 

    var deptsCollections: [[Presentable]?] = [ buses, metros, trains, trams, ships ] 
    for var i = 0; i<deptsCollections.count ; i++ { 
     if let departures = deptsCollections[i]? { 
      var newDeparturesArray: [Presentable] = [] 
      for dep in departures 
      { 
       newDeparturesArray.append(dep) // EXC_BAD_INSTRUCTION 
      } 
      let tuple: TableSection = (sectionTitle: "test", rows: newDeparturesArray) 
      result.append(tuple) 
     } 
    } 
    return result 
} 

консоли выход:

fatal error: NSArray element failed to match the Swift Array Element type 

2. Это «работает» (т. не врезаться во время выполнения), но я, кажется, не получить ни одного объекта в моем новом массиве:

private func asContent4() -> [TableSection] 
{ 
    var result: Array<TableSection> = [] 

    var deptsCollections: [AnyObject?] = [ buses, metros, trains, trams, ships ] 
    for var i = 0; i<deptsCollections.count ; i++ { 
     if let departures: [Presentable] = deptsCollections[i] as? [Presentable] { 
      var newDeparturesArray: [Presentable] = [] 
      for dep in departures 
      { 
       newDeparturesArray.append(dep as Presentable) 
      } 
      let tuple: TableSection = (sectionTitle: "test", rows: newDeparturesArray) 
      result.append(tuple) 
     } 
    } 
    return result 
} 

3. Это работает полностью:

private func asContent3() -> [TableSection] 
{ 
    var result: Array<TableSection> = [] 

    if let departures = buses { 
     var newDeparturesArray: [Presentable] = [] 
     for dep in departures { newDeparturesArray.append(dep as Presentable) } 
     let tuple: TableSection = (sectionTitle: "bus", rows: newDeparturesArray) 
     result.append(tuple) 
    } 

    if let departures = metros { 
     var newDeparturesArray: [Presentable] = [] 
     for dep in departures { newDeparturesArray.append(dep as Presentable) } 
     let tuple: TableSection = (sectionTitle: "metro", rows: newDeparturesArray) 
     result.append(tuple) 
    } 

    if let departures = trains { 
     var newDeparturesArray: [Presentable] = [] 
     for dep in departures { newDeparturesArray.append(dep as Presentable) } 
     let tuple: TableSection = (sectionTitle: "trains", rows: newDeparturesArray) 
     result.append(tuple) 
    } 

    if let departures = trams { 
     var newDeparturesArray: [Presentable] = [] 
     for dep in departures { newDeparturesArray.append(dep as Presentable) } 
     let tuple: TableSection = (sectionTitle: "trams", rows: newDeparturesArray) 
     result.append(tuple) 
    } 

    if let departures = ships { 
     var newDeparturesArray: [Presentable] = [] 
     for dep in departures { newDeparturesArray.append(dep as Presentable) } 
     let tuple: TableSection = (sectionTitle: "ships", rows: newDeparturesArray) 
     result.append(tuple) 
    } 

    return result 
} 

Все, что я хочу, чтобы взять мой buses, metros, trains, trams, ships и поместите их в [Presentable] каждый, без стены кода. Я начинаю верить, что это невозможно в Свифт, потому что мне кажется, что я переписал эти петли всеми возможными способами.

Что мне не хватает? Почему я не могу, кажется, повторить успешную попытку, а не повторять весь этот код?


Update

Это то, что происходит с Davids кодом:

тот же выход консоли, как описано выше, но на этот раз он выходит из строя при попытке получить доступ к TableSection :: строк (то есть случилось со мной и раньше). Это делает его крах:

println("index path s: \(indexPath.section) r: \(indexPath.row)") 
let section = tableContent[indexPath.section] 
println("row count: \(section.rows.count)") 
let departure: Presentable = section.rows[indexPath.row] // crash 

Console (я напечатал rows массив из переменных View):

index path s: 0 r: 0 
row count: 8 
fatal error: NSArray element failed to match the Swift Array Element type 
Printing description of section.rows: 
([protocol<Departure, Displayable, Utterable>]) rows = {} 

Является ли это только мне или не эти цифры складываются?

+0

Причина может быть объяснена здесь: http://stackoverflow.com/questions/24113354/array-element-cannot-be-bridged-to- object-c Ваш массив-мосты в 'var deptsCollections: [[Presentable]?] = [buses]' не будет работать –

+0

Может быть. Я смог назначить 'var myPresentables: [Представляемый]? = автобусы. Я знаю, что это сомнительное назначение, потому что массив имеет тип [Bus], а не [Presentable], но я не уверен, если это имеет значение. Он разбивает тип безопасности, но он скомпилирован, и он работал до тех пор, пока он был [@objc protocol] ... – Andreas

ответ

1

После создания кучу кода, что здесь не хватает, подхожу со следующим, что, кажется, работает, как вы ожидаете:

import Foundation 

@objc protocol Utterable {} 
@objc protocol Displayable {} 
@objc protocol Departure {} 

typealias Presentable = protocol<Utterable, Displayable, Departure> 
typealias TableSection = (sectionTitle: String, rows: [Presentable]) 

class Bus : Presentable {} 
class Metro : Presentable {} 
class Train : Presentable {} 
class Tram : Presentable {} 
class Ship : Presentable {} 

let buses : [Bus]? = nil 
let metros : [Metro]? = [ Metro() ] 
let trains : [Train]? = [ Train() ] 
let trams : [Tram]? = nil 
let ships : [Ship]? = [Ship()] 

let departments : [[Presentable]?] = [ buses, metros, trains, trams, ships] 

// filter out the non-nil departments that actually have elements 
let acceptable = departments.filter { $0?.count > 0 } 

// map the acceptable departments into sections, note that we force-unwrap 
// dept because we already verified in the step above that it must be 
// valid 
let sections : [TableSection] = acceptable.map { (sectionTitle:"test", rows: $0!) } 

Обратите внимание, что это использует несколько очень важных встроенных функций filter и map I 'd предлагают действительно копаться в них, так как они, плюс reduce - невероятно мощные встроенные модули, которые почти устраняют необходимость когда-либо вручную выполнять свою собственную итерацию массива.

Или, для компактности, вы можете использовать:

// or for compactness... 
let sections2 : [TableSection] = departments.filter({ $0?.count > 0 }) 
              .map({ (sectionTitle:"test", rows: $0!) }) 
+0

Мне нравится подход, и я попробовал ваш код. Он, похоже, не работает полностью:/Начиная с подозрения, что это из-за сломанной системы расширения Swift (см. Мой другой вопрос: http://stackoverflow.com/q/28131121/220820) – Andreas

+0

Извините за недостающий код. Было нецелесообразно добавлять его, поскольку существует иерархия с базовыми классами и по крайней мере одно расширение для каждого протокола, чтобы сохранить порядок вещей. Иногда я могу избежать ошибок во время выполнения, просто переместив принятие протокола из расширения в класс (т. Е. «Класс A: B» вместо «расширение A: B». Это странно. – Andreas

+0

Похоже, вам нужно добавить дополнительную информацию на ваш вопрос, так как там нет упоминания о расширении там :) –