Typecasting causing struct values to change (Swift)











up vote
3
down vote

favorite












After downcasting an array of structs, my Variables View window shows that all of the values in my struct have shifted "down" (will explain in a second). But when I print(structName), the values are fine. However, when I run an equality check on the struct, it once again behaves as though my values have shifted.



For example, I am trying to downcast Model A to ModelProtocol. var m = Model A and has the values {id: "1234", name: "Cal"}. When I downcast, m now has the values { id:"", name:"1234" }.



Actual Example Below:



Models that I want to downcast:



struct PrivateSchoolModel: Decodable, SchoolProtocol {
var id: String
var name: String
var city: String
var state: String
}
struct PublicSchoolModel: Decodable, SchoolProtocol {
var id: String
var name: String
var city: String
var state: String
var latitude: String
var longitude: String
}


Protocol I want to downcast to:



protocol SchoolProtocol {
var id: String { get set }
var name: String { get set }
var city: String { get set }
var state: String { get set }
var longitude: Float { get set }
var latitude: Float { get set }
}

extension SchoolProtocol {
var longitude: Float {
get { return -1.0 }
set {}
}
var latitude: Float {
get { return -1.0 }
set {}
}
}


Downcasting:



guard let downcastedArr = privateSchoolArray as? [SchoolProtocol] else { return  }


Result (item at index 0) or originalArr:



id = "1234"
name = "Leo High School"
city = "Bellview"
state = "WA"


Result (item at index 0) of downcastedArr:



id = ""
name = "1234"
city = "Leo High School"
state = "Bellview"


But if I print(downcastArr[0]), it will show:



id = "1234"
name = "Leo High School"
city = "Bellview"
state = "WA"


But if I try originalArray[0].id == downcastArr[0].id, it returns false



My Code with the problem:



class SchoolJSONHandler {
private enum JSONFile: String {
case publicSchool = "publicSchool"
case privateSchool = "privateSchool"
}

private lazy var privateSchoolArray = getPrivateSchools()
private lazy var publicSchoolArray = getPublicSchools()

func getSchoolArray(sorted: Bool, filtered: Bool, by stateAbbreviation: String?) -> [SchoolProtocol] {
var schools = combineArrays()

if sorted {
schools.sort(by: { $0.name < $1.name })
}

if filtered {
guard let abbr = stateAbbreviation else { return }
schools = schools.filter {
return $0.state == abbr
}
}

return schools
}

private func combineArrays() -> [SchoolProtocol] {
// EVERYTHING IS FINE IN NEXT LINE
let a = privateSchoolArray
// PROBLEM OCCURS IN NEXT 2 LINES WHEN DOWNCASTING
let b = privateSchoolArray as [SchoolProtocol]
let c = publicSchoolArray as [SchoolProtocol]
return b + c
}

private func getPublicSchools() -> [PublicSchoolModel] {
guard let jsonData = getJSONData(from: .publicSchool) else { return }
guard let schools = decode(jsonData: jsonData, using: [PublicSchoolModel].self) else { return }
return schools
}

private func getPrivateSchools() -> [PrivateSchoolModel] {
guard let jsonData = getJSONData(from: .privateSchool) else { return }
guard let schools = decode(jsonData: jsonData, using: [PrivateSchoolModel].self) else { return }
return schools
}

private func getJSONData(from resource: JSONFile) -> Data? {
let url = Bundle.main.url(forResource: resource.rawValue, withExtension: "json")!
do {
let jsonData = try Data(contentsOf: url)

return jsonData
}
catch {
print(error)
}

return nil
}

private func decode<M: Decodable>(jsonData: Data, using modelType: M.Type) -> M? {
do {
//here dataResponse received from a network request
let decoder = JSONDecoder()
let model = try decoder.decode(modelType, from:
jsonData) //Decode JSON Response Data

return model
} catch let parsingError {
print("Error", parsingError)
}

return nil
}
}


And then it is just called in another class by schoolJSONHandler.getSchoolArray(sorted: true, filtered: true, by: "WA")










share|improve this question


























    up vote
    3
    down vote

    favorite












    After downcasting an array of structs, my Variables View window shows that all of the values in my struct have shifted "down" (will explain in a second). But when I print(structName), the values are fine. However, when I run an equality check on the struct, it once again behaves as though my values have shifted.



    For example, I am trying to downcast Model A to ModelProtocol. var m = Model A and has the values {id: "1234", name: "Cal"}. When I downcast, m now has the values { id:"", name:"1234" }.



    Actual Example Below:



    Models that I want to downcast:



    struct PrivateSchoolModel: Decodable, SchoolProtocol {
    var id: String
    var name: String
    var city: String
    var state: String
    }
    struct PublicSchoolModel: Decodable, SchoolProtocol {
    var id: String
    var name: String
    var city: String
    var state: String
    var latitude: String
    var longitude: String
    }


    Protocol I want to downcast to:



    protocol SchoolProtocol {
    var id: String { get set }
    var name: String { get set }
    var city: String { get set }
    var state: String { get set }
    var longitude: Float { get set }
    var latitude: Float { get set }
    }

    extension SchoolProtocol {
    var longitude: Float {
    get { return -1.0 }
    set {}
    }
    var latitude: Float {
    get { return -1.0 }
    set {}
    }
    }


    Downcasting:



    guard let downcastedArr = privateSchoolArray as? [SchoolProtocol] else { return  }


    Result (item at index 0) or originalArr:



    id = "1234"
    name = "Leo High School"
    city = "Bellview"
    state = "WA"


    Result (item at index 0) of downcastedArr:



    id = ""
    name = "1234"
    city = "Leo High School"
    state = "Bellview"


    But if I print(downcastArr[0]), it will show:



    id = "1234"
    name = "Leo High School"
    city = "Bellview"
    state = "WA"


    But if I try originalArray[0].id == downcastArr[0].id, it returns false



    My Code with the problem:



    class SchoolJSONHandler {
    private enum JSONFile: String {
    case publicSchool = "publicSchool"
    case privateSchool = "privateSchool"
    }

    private lazy var privateSchoolArray = getPrivateSchools()
    private lazy var publicSchoolArray = getPublicSchools()

    func getSchoolArray(sorted: Bool, filtered: Bool, by stateAbbreviation: String?) -> [SchoolProtocol] {
    var schools = combineArrays()

    if sorted {
    schools.sort(by: { $0.name < $1.name })
    }

    if filtered {
    guard let abbr = stateAbbreviation else { return }
    schools = schools.filter {
    return $0.state == abbr
    }
    }

    return schools
    }

    private func combineArrays() -> [SchoolProtocol] {
    // EVERYTHING IS FINE IN NEXT LINE
    let a = privateSchoolArray
    // PROBLEM OCCURS IN NEXT 2 LINES WHEN DOWNCASTING
    let b = privateSchoolArray as [SchoolProtocol]
    let c = publicSchoolArray as [SchoolProtocol]
    return b + c
    }

    private func getPublicSchools() -> [PublicSchoolModel] {
    guard let jsonData = getJSONData(from: .publicSchool) else { return }
    guard let schools = decode(jsonData: jsonData, using: [PublicSchoolModel].self) else { return }
    return schools
    }

    private func getPrivateSchools() -> [PrivateSchoolModel] {
    guard let jsonData = getJSONData(from: .privateSchool) else { return }
    guard let schools = decode(jsonData: jsonData, using: [PrivateSchoolModel].self) else { return }
    return schools
    }

    private func getJSONData(from resource: JSONFile) -> Data? {
    let url = Bundle.main.url(forResource: resource.rawValue, withExtension: "json")!
    do {
    let jsonData = try Data(contentsOf: url)

    return jsonData
    }
    catch {
    print(error)
    }

    return nil
    }

    private func decode<M: Decodable>(jsonData: Data, using modelType: M.Type) -> M? {
    do {
    //here dataResponse received from a network request
    let decoder = JSONDecoder()
    let model = try decoder.decode(modelType, from:
    jsonData) //Decode JSON Response Data

    return model
    } catch let parsingError {
    print("Error", parsingError)
    }

    return nil
    }
    }


    And then it is just called in another class by schoolJSONHandler.getSchoolArray(sorted: true, filtered: true, by: "WA")










    share|improve this question
























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      After downcasting an array of structs, my Variables View window shows that all of the values in my struct have shifted "down" (will explain in a second). But when I print(structName), the values are fine. However, when I run an equality check on the struct, it once again behaves as though my values have shifted.



      For example, I am trying to downcast Model A to ModelProtocol. var m = Model A and has the values {id: "1234", name: "Cal"}. When I downcast, m now has the values { id:"", name:"1234" }.



      Actual Example Below:



      Models that I want to downcast:



      struct PrivateSchoolModel: Decodable, SchoolProtocol {
      var id: String
      var name: String
      var city: String
      var state: String
      }
      struct PublicSchoolModel: Decodable, SchoolProtocol {
      var id: String
      var name: String
      var city: String
      var state: String
      var latitude: String
      var longitude: String
      }


      Protocol I want to downcast to:



      protocol SchoolProtocol {
      var id: String { get set }
      var name: String { get set }
      var city: String { get set }
      var state: String { get set }
      var longitude: Float { get set }
      var latitude: Float { get set }
      }

      extension SchoolProtocol {
      var longitude: Float {
      get { return -1.0 }
      set {}
      }
      var latitude: Float {
      get { return -1.0 }
      set {}
      }
      }


      Downcasting:



      guard let downcastedArr = privateSchoolArray as? [SchoolProtocol] else { return  }


      Result (item at index 0) or originalArr:



      id = "1234"
      name = "Leo High School"
      city = "Bellview"
      state = "WA"


      Result (item at index 0) of downcastedArr:



      id = ""
      name = "1234"
      city = "Leo High School"
      state = "Bellview"


      But if I print(downcastArr[0]), it will show:



      id = "1234"
      name = "Leo High School"
      city = "Bellview"
      state = "WA"


      But if I try originalArray[0].id == downcastArr[0].id, it returns false



      My Code with the problem:



      class SchoolJSONHandler {
      private enum JSONFile: String {
      case publicSchool = "publicSchool"
      case privateSchool = "privateSchool"
      }

      private lazy var privateSchoolArray = getPrivateSchools()
      private lazy var publicSchoolArray = getPublicSchools()

      func getSchoolArray(sorted: Bool, filtered: Bool, by stateAbbreviation: String?) -> [SchoolProtocol] {
      var schools = combineArrays()

      if sorted {
      schools.sort(by: { $0.name < $1.name })
      }

      if filtered {
      guard let abbr = stateAbbreviation else { return }
      schools = schools.filter {
      return $0.state == abbr
      }
      }

      return schools
      }

      private func combineArrays() -> [SchoolProtocol] {
      // EVERYTHING IS FINE IN NEXT LINE
      let a = privateSchoolArray
      // PROBLEM OCCURS IN NEXT 2 LINES WHEN DOWNCASTING
      let b = privateSchoolArray as [SchoolProtocol]
      let c = publicSchoolArray as [SchoolProtocol]
      return b + c
      }

      private func getPublicSchools() -> [PublicSchoolModel] {
      guard let jsonData = getJSONData(from: .publicSchool) else { return }
      guard let schools = decode(jsonData: jsonData, using: [PublicSchoolModel].self) else { return }
      return schools
      }

      private func getPrivateSchools() -> [PrivateSchoolModel] {
      guard let jsonData = getJSONData(from: .privateSchool) else { return }
      guard let schools = decode(jsonData: jsonData, using: [PrivateSchoolModel].self) else { return }
      return schools
      }

      private func getJSONData(from resource: JSONFile) -> Data? {
      let url = Bundle.main.url(forResource: resource.rawValue, withExtension: "json")!
      do {
      let jsonData = try Data(contentsOf: url)

      return jsonData
      }
      catch {
      print(error)
      }

      return nil
      }

      private func decode<M: Decodable>(jsonData: Data, using modelType: M.Type) -> M? {
      do {
      //here dataResponse received from a network request
      let decoder = JSONDecoder()
      let model = try decoder.decode(modelType, from:
      jsonData) //Decode JSON Response Data

      return model
      } catch let parsingError {
      print("Error", parsingError)
      }

      return nil
      }
      }


      And then it is just called in another class by schoolJSONHandler.getSchoolArray(sorted: true, filtered: true, by: "WA")










      share|improve this question













      After downcasting an array of structs, my Variables View window shows that all of the values in my struct have shifted "down" (will explain in a second). But when I print(structName), the values are fine. However, when I run an equality check on the struct, it once again behaves as though my values have shifted.



      For example, I am trying to downcast Model A to ModelProtocol. var m = Model A and has the values {id: "1234", name: "Cal"}. When I downcast, m now has the values { id:"", name:"1234" }.



      Actual Example Below:



      Models that I want to downcast:



      struct PrivateSchoolModel: Decodable, SchoolProtocol {
      var id: String
      var name: String
      var city: String
      var state: String
      }
      struct PublicSchoolModel: Decodable, SchoolProtocol {
      var id: String
      var name: String
      var city: String
      var state: String
      var latitude: String
      var longitude: String
      }


      Protocol I want to downcast to:



      protocol SchoolProtocol {
      var id: String { get set }
      var name: String { get set }
      var city: String { get set }
      var state: String { get set }
      var longitude: Float { get set }
      var latitude: Float { get set }
      }

      extension SchoolProtocol {
      var longitude: Float {
      get { return -1.0 }
      set {}
      }
      var latitude: Float {
      get { return -1.0 }
      set {}
      }
      }


      Downcasting:



      guard let downcastedArr = privateSchoolArray as? [SchoolProtocol] else { return  }


      Result (item at index 0) or originalArr:



      id = "1234"
      name = "Leo High School"
      city = "Bellview"
      state = "WA"


      Result (item at index 0) of downcastedArr:



      id = ""
      name = "1234"
      city = "Leo High School"
      state = "Bellview"


      But if I print(downcastArr[0]), it will show:



      id = "1234"
      name = "Leo High School"
      city = "Bellview"
      state = "WA"


      But if I try originalArray[0].id == downcastArr[0].id, it returns false



      My Code with the problem:



      class SchoolJSONHandler {
      private enum JSONFile: String {
      case publicSchool = "publicSchool"
      case privateSchool = "privateSchool"
      }

      private lazy var privateSchoolArray = getPrivateSchools()
      private lazy var publicSchoolArray = getPublicSchools()

      func getSchoolArray(sorted: Bool, filtered: Bool, by stateAbbreviation: String?) -> [SchoolProtocol] {
      var schools = combineArrays()

      if sorted {
      schools.sort(by: { $0.name < $1.name })
      }

      if filtered {
      guard let abbr = stateAbbreviation else { return }
      schools = schools.filter {
      return $0.state == abbr
      }
      }

      return schools
      }

      private func combineArrays() -> [SchoolProtocol] {
      // EVERYTHING IS FINE IN NEXT LINE
      let a = privateSchoolArray
      // PROBLEM OCCURS IN NEXT 2 LINES WHEN DOWNCASTING
      let b = privateSchoolArray as [SchoolProtocol]
      let c = publicSchoolArray as [SchoolProtocol]
      return b + c
      }

      private func getPublicSchools() -> [PublicSchoolModel] {
      guard let jsonData = getJSONData(from: .publicSchool) else { return }
      guard let schools = decode(jsonData: jsonData, using: [PublicSchoolModel].self) else { return }
      return schools
      }

      private func getPrivateSchools() -> [PrivateSchoolModel] {
      guard let jsonData = getJSONData(from: .privateSchool) else { return }
      guard let schools = decode(jsonData: jsonData, using: [PrivateSchoolModel].self) else { return }
      return schools
      }

      private func getJSONData(from resource: JSONFile) -> Data? {
      let url = Bundle.main.url(forResource: resource.rawValue, withExtension: "json")!
      do {
      let jsonData = try Data(contentsOf: url)

      return jsonData
      }
      catch {
      print(error)
      }

      return nil
      }

      private func decode<M: Decodable>(jsonData: Data, using modelType: M.Type) -> M? {
      do {
      //here dataResponse received from a network request
      let decoder = JSONDecoder()
      let model = try decoder.decode(modelType, from:
      jsonData) //Decode JSON Response Data

      return model
      } catch let parsingError {
      print("Error", parsingError)
      }

      return nil
      }
      }


      And then it is just called in another class by schoolJSONHandler.getSchoolArray(sorted: true, filtered: true, by: "WA")







      swift struct casting protocols downcasting






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 11 at 1:50









      connorvo

      889




      889





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53245165%2ftypecasting-causing-struct-values-to-change-swift%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53245165%2ftypecasting-causing-struct-values-to-change-swift%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          List item for chat from Array inside array React Native

          Thiostrepton

          Caerphilly