3

I have a protocol like this:

protocol Datable {
    var date: NSDate { get set }
}

struct DEPref: Datable {
   var date: NSDate
}

struct DEPObs: Datable {
   var date: NSDate
}

func fetchDepRefs() -> [DEPRef] {...}
func fetchDepObss() -> [DEPObs] {...}

I would like to create an array of DEPref and DEPObs in order to sort the final list.

I have tried many things but the compiler complains. Example:

var depRefList: Array<Datable> = fetchDepRefs()
var depObsList: Array<Datable> = fetchDepObss()
var allDeps = ...

An error in the first line "Cannot convert value of type [DEPref] to specified type Array"

samir
  • 4,501
  • 6
  • 49
  • 76
  • 1
    See [this Q&A](http://stackoverflow.com/questions/37188580/why-isnt-somestruct-convertible-to-any) for more info about why that type conversion fails. – Hamish Aug 15 '16 at 07:43
  • If you feel an answer solved the problem, please mark it as 'accepted' by clicking the green check mark. This helps keep the focus on older SO which still don't have answers. – sineil Aug 18 '16 at 00:45

3 Answers3

3

I'm very new to Swift/iOS programming, but something like this works for me.

func fetchDepRefs() -> Array<Datable> {return Array<Datable>()}

var depRefList = fetchDepRefs()
var testDEPref = DEPref(date: NSDate())
var testDEPref2 = DEPref(date: NSDate())

depRefList.append(testDEPref)
depRefList.append(testDEPref2)

for ref in depRefList {
    print(ref.date)
}

Your functions could also return [Datable]

eg.

func fetchDepRefs() -> [Datable] {return [Datable]()}

This also works for your scenario

Edit:

Or if you're looking for type safety in your functions, the following code will also work

func fetchDepRefs() -> [DEPref] {return [DEPref]()}
func fetchDepObss() -> [DEPObs] {return [DEPObs]()}

var depRefList = fetchDepRefs()
var depObsList = fetchDepObss()

var allDeps: [Datable] = [Datable]()

In this you can add elements from depRefList and depObsList to allDeps and everything will work fine.

Edit again:

This is a fully working example of what you're trying to achieve. In this I'm using the map function to transform the elements of the given arrays to Datable objects

protocol Datable {
    var date: NSDate { get set }
}

struct DEPref: Datable {
   var date: NSDate
}

struct DEPObs: Datable {
   var date: NSDate
}

func fetchDepRefs() -> [DEPref] {return [DEPref]()}
func fetchDepObs() -> [DEPObs] {return [DEPObs]()}

var depRefs = fetchDepRefs()
var depObs = fetchDepObs()

var ref1 = DEPref(date: NSDate())
var obs1 = DEPObs(date: NSDate())

depRefs.append(ref1)
depObs.append(obs1)

var allDeps = depRefs.map{$0 as Datable} + depObs.map{$0 as Datable}


for x in allDeps {
    print("I'm in allDeps array: \(x.date)")
}
sineil
  • 307
  • 2
  • 5
  • 18
  • Thanks for your answer, but i would like to keep my functions "fetchs" with the specific return type and not return the protocol. How you can merge the two arrays depRefList and depObsList ? – samir Aug 15 '16 at 00:40
  • If you see my latest edit I've done exactly that. :) – sineil Aug 15 '16 at 00:40
  • My goal is to merge the two arrays and then sort the final array by date – samir Aug 15 '16 at 00:42
  • There are other stackoverflow questions re. merging Swift arrays. The code I've given you allows you to create an array of Datable objects, that you can use to merge both DEPref and DEPObs arrays. See here for merging the contents of two arrays: http://stackoverflow.com/questions/25146382/how-do-i-concatenate-or-merge-arrays-in-swift – sineil Aug 15 '16 at 00:43
  • Do you tried to merge the two arrays before posting the response ? – samir Aug 15 '16 at 00:46
  • I think if you tried to experiment & google your problems with the examples I gave you'd have been able to do what you set out to do. I've updated my original answer with a fully working solution that I've tested. – sineil Aug 15 '16 at 00:58
2

Are you running Swift 2 on iOS? The following runs successfully on Swift 3.

   http://swiftlang.ng.bluemix.net/#/repl/57b13a01133614f70db3347e

protocol Datable {
    var date: NSDate { get set }
}

struct Type1: Datable {
   var date: NSDate
}

struct Type2: Datable {
   var date: NSDate
}

var x : Datable = Type1(date:NSDate())
var y : Datable = Type2(date:NSDate())

var array : [Datable] = [x, y]

var x2 : Datable = Type1(date:NSDate())
var y2 : Datable = Type2(date:NSDate())

array.append(x2)
array.append(y2)
Lightbeard
  • 4,011
  • 10
  • 49
  • 59
0

The easiest way is use map:

var depRefList: Array<Datable> = fetchDepRefs().map { $0 as Datable }
var depObsList: Array<Datable> = fetchDepObss().map { $0 as Datable }
var allDeps = (depRefList + depObsList)
            .sort { $0.date.timeIntervalSince1970 > $1.date.timeIntervalSince1970 }

since depRefList is [Datable], and fetchDepRefs() is [DEPref], Thay are different type, So it's neccecary to transfer [DEPref] to [Datable], The map function will do this for you. The flowing code:

var depRefList: Array<Datable> = fetchDepRefs().map { $0 as Datable }

is equal to:

let depRefs: [DEPref] = fetchDepRefs()

var datables = [Datable]()

for depRef in depRefs {
    let datable = depRef as Datable
    datables.append(datable)
}

var depRefList: Array<Datable> = datables
beeth0ven
  • 1,857
  • 15
  • 18