MVVM in Swift iOS The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Networking in iOS SwiftGetting WiFi SSID on iOS in SwiftSwift iOS - Call back functionsOptimize Data Sending/Querying to Parse Swift iOSRxSwift iOS Observable FIFO Queue Implementation in Swift 2Navigation controller in SwiftSwift/iOS: Subclassing UILabel and setting propertiesSwift/iOS component for label with clickable text buttonsiOS Memory Game - Swift 4Networking structure for Swift iOS app

When did F become S? Why?

Separating matrix elements by lines

Sub-subscripts in strings cause different spacings than subscripts

Was credit for the black hole image misappropriated?

My body leaves; my core can stay

Why did Peik Lin say, "I'm not an animal"?

how can a perfect fourth interval be considered either consonant or dissonant?

Why did they expect Astronaut Scott Kelley's telomere shortening to accelerate? (they got longer!)

Student Loan from years ago pops up and is taking my salary

Could an empire control the whole planet with today's comunication methods?

What information about me do stores get via my credit card?

Example of compact Riemannian manifold with only one geodesic.

What is the role of 'For' here?

One-dimensional Japanese puzzle

Would an alien lifeform be able to achieve space travel if lacking in vision?

"... to apply for a visa" or "... and applied for a visa"?

Why can't devices on different VLANs, but on the same subnet, communicate?

Is it ok to offer lower paid work as a trial period before negotiating for a full-time job?

Didn't get enough time to take a Coding Test - what to do now?

Accepted by European university, rejected by all American ones I applied to? Possible reasons?

Can the DM override racial traits?

ELI5: Why do they say that Israel would have been the fourth country to land a spacecraft on the Moon and why do they call it low cost?

Why are PDP-7-style microprogrammed instructions out of vogue?

Make it rain characters



MVVM in Swift iOS



The 2019 Stack Overflow Developer Survey Results Are In
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Networking in iOS SwiftGetting WiFi SSID on iOS in SwiftSwift iOS - Call back functionsOptimize Data Sending/Querying to Parse Swift iOSRxSwift iOS Observable FIFO Queue Implementation in Swift 2Navigation controller in SwiftSwift/iOS: Subclassing UILabel and setting propertiesSwift/iOS component for label with clickable text buttonsiOS Memory Game - Swift 4Networking structure for Swift iOS app



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0












$begingroup$


I've been implementing MVVM in Swift. I've looked at several implementations, many of which violate some aspects of MVVM and wanted to have a go with my own version that contains a Web request service.



View:



class BreachView: UIView 
var nameLabel = UILabel()
public override init(frame: CGRect)
let labelframe = CGRect(x: 0, y: 50, width: frame.width, height: 20)
nameLabel.frame = labelframe
nameLabel.backgroundColor = .gray
super.init(frame: frame)
self.addSubview(nameLabel)
backgroundColor = .red


required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")




ViewController
class ViewController: UIViewController



var breachesViewModel: BreachViewModelType!
var breachView : BreachView?

// to be called during testing
init(viewModel: BreachViewModelType)
breachesViewModel = viewModel
super.init(nibName: nil, bundle: nil)


// required when called from storyboard
required init?(coder aDecoder: NSCoder)
breachesViewModel = BreachViewModel()
super.init(coder: aDecoder)


override func viewDidLoad()
super.viewDidLoad()
breachesViewModel.fetchData [weak self] breaches in
guard let self = self else return
DispatchQueue.main.async
self.updateUI()




func updateUI()
breachView = BreachView(frame: view.frame)
breachesViewModel.configure(breachView!, number: 3)
view.addSubview(breachView!)





Protocol for dependency injection:



protocol BreachViewModelType 
func fetchData(completion: @escaping ([BreachModel]) -> Void)
func configure (_ view: BreachView, number index: Int)



ViewModel
class BreachViewModel : BreachViewModelType
var breaches = BreachModel



init() 
// add init for ClosureHTTPManager here, to allow it to be teestable in the future


func fetchData(completion: @escaping ([BreachModel]) -> Void)
ClosureHTTPManager.shared.get(urlString: baseUrl + breachesExtensionURL, completionBlock: [weak self] result in
guard let self = self else return
switch result
case .failure(let error):
print ("failure", error)
case .success(let dta) :
let decoder = JSONDecoder()
do

self.breaches = try decoder.decode([BreachModel].self, from: dta)
completion(try decoder.decode([BreachModel].self, from: dta))
catch
// deal with error from JSON decoding!


)


func numberItemsToDisplay() -> Int
return breaches.count


func configure (_ view: BreachView, number index: Int)
// set the name and data in the view
view.nameLabel.text = breaches[index].name





and HTTP manager



 class ClosureHTTPManager 
static let shared: ClosureHTTPManager = ClosureHTTPManager()

enum HTTPError: Error


case invalidURL
case invalidResponse(Data?, URLResponse?)


public func get(urlString: String, completionBlock: @escaping (Result<Data, Error>) -> Void)
guard let url = URL(string: urlString) else
completionBlock(.failure(HTTPError.invalidURL))
return


let task = URLSession.shared.dataTask(with: url) data, response, error in
guard error == nil else
completionBlock(.failure(error!))
return


guard
let responseData = data,
let httpResponse = response as? HTTPURLResponse,
200 ..< 300 ~= httpResponse.statusCode else
completionBlock(.failure(HTTPError.invalidResponse(data, response)))
return


completionBlock(.success(responseData))

task.resume()




Calling the API from



let baseUrl : String = "https://haveibeenpwned.com/api/v2"
let breachesExtensionURL : String = "/breaches"


Any comments on whether the implementation conforms to MVVM or not, typos, changes etc. are appreciated.



Git link: https://github.com/stevencurtis/MVVMWithNetworkService









share









$endgroup$


















    0












    $begingroup$


    I've been implementing MVVM in Swift. I've looked at several implementations, many of which violate some aspects of MVVM and wanted to have a go with my own version that contains a Web request service.



    View:



    class BreachView: UIView 
    var nameLabel = UILabel()
    public override init(frame: CGRect)
    let labelframe = CGRect(x: 0, y: 50, width: frame.width, height: 20)
    nameLabel.frame = labelframe
    nameLabel.backgroundColor = .gray
    super.init(frame: frame)
    self.addSubview(nameLabel)
    backgroundColor = .red


    required init?(coder aDecoder: NSCoder)
    fatalError("init(coder:) has not been implemented")




    ViewController
    class ViewController: UIViewController



    var breachesViewModel: BreachViewModelType!
    var breachView : BreachView?

    // to be called during testing
    init(viewModel: BreachViewModelType)
    breachesViewModel = viewModel
    super.init(nibName: nil, bundle: nil)


    // required when called from storyboard
    required init?(coder aDecoder: NSCoder)
    breachesViewModel = BreachViewModel()
    super.init(coder: aDecoder)


    override func viewDidLoad()
    super.viewDidLoad()
    breachesViewModel.fetchData [weak self] breaches in
    guard let self = self else return
    DispatchQueue.main.async
    self.updateUI()




    func updateUI()
    breachView = BreachView(frame: view.frame)
    breachesViewModel.configure(breachView!, number: 3)
    view.addSubview(breachView!)





    Protocol for dependency injection:



    protocol BreachViewModelType 
    func fetchData(completion: @escaping ([BreachModel]) -> Void)
    func configure (_ view: BreachView, number index: Int)



    ViewModel
    class BreachViewModel : BreachViewModelType
    var breaches = BreachModel



    init() 
    // add init for ClosureHTTPManager here, to allow it to be teestable in the future


    func fetchData(completion: @escaping ([BreachModel]) -> Void)
    ClosureHTTPManager.shared.get(urlString: baseUrl + breachesExtensionURL, completionBlock: [weak self] result in
    guard let self = self else return
    switch result
    case .failure(let error):
    print ("failure", error)
    case .success(let dta) :
    let decoder = JSONDecoder()
    do

    self.breaches = try decoder.decode([BreachModel].self, from: dta)
    completion(try decoder.decode([BreachModel].self, from: dta))
    catch
    // deal with error from JSON decoding!


    )


    func numberItemsToDisplay() -> Int
    return breaches.count


    func configure (_ view: BreachView, number index: Int)
    // set the name and data in the view
    view.nameLabel.text = breaches[index].name





    and HTTP manager



     class ClosureHTTPManager 
    static let shared: ClosureHTTPManager = ClosureHTTPManager()

    enum HTTPError: Error


    case invalidURL
    case invalidResponse(Data?, URLResponse?)


    public func get(urlString: String, completionBlock: @escaping (Result<Data, Error>) -> Void)
    guard let url = URL(string: urlString) else
    completionBlock(.failure(HTTPError.invalidURL))
    return


    let task = URLSession.shared.dataTask(with: url) data, response, error in
    guard error == nil else
    completionBlock(.failure(error!))
    return


    guard
    let responseData = data,
    let httpResponse = response as? HTTPURLResponse,
    200 ..< 300 ~= httpResponse.statusCode else
    completionBlock(.failure(HTTPError.invalidResponse(data, response)))
    return


    completionBlock(.success(responseData))

    task.resume()




    Calling the API from



    let baseUrl : String = "https://haveibeenpwned.com/api/v2"
    let breachesExtensionURL : String = "/breaches"


    Any comments on whether the implementation conforms to MVVM or not, typos, changes etc. are appreciated.



    Git link: https://github.com/stevencurtis/MVVMWithNetworkService









    share









    $endgroup$














      0












      0








      0





      $begingroup$


      I've been implementing MVVM in Swift. I've looked at several implementations, many of which violate some aspects of MVVM and wanted to have a go with my own version that contains a Web request service.



      View:



      class BreachView: UIView 
      var nameLabel = UILabel()
      public override init(frame: CGRect)
      let labelframe = CGRect(x: 0, y: 50, width: frame.width, height: 20)
      nameLabel.frame = labelframe
      nameLabel.backgroundColor = .gray
      super.init(frame: frame)
      self.addSubview(nameLabel)
      backgroundColor = .red


      required init?(coder aDecoder: NSCoder)
      fatalError("init(coder:) has not been implemented")




      ViewController
      class ViewController: UIViewController



      var breachesViewModel: BreachViewModelType!
      var breachView : BreachView?

      // to be called during testing
      init(viewModel: BreachViewModelType)
      breachesViewModel = viewModel
      super.init(nibName: nil, bundle: nil)


      // required when called from storyboard
      required init?(coder aDecoder: NSCoder)
      breachesViewModel = BreachViewModel()
      super.init(coder: aDecoder)


      override func viewDidLoad()
      super.viewDidLoad()
      breachesViewModel.fetchData [weak self] breaches in
      guard let self = self else return
      DispatchQueue.main.async
      self.updateUI()




      func updateUI()
      breachView = BreachView(frame: view.frame)
      breachesViewModel.configure(breachView!, number: 3)
      view.addSubview(breachView!)





      Protocol for dependency injection:



      protocol BreachViewModelType 
      func fetchData(completion: @escaping ([BreachModel]) -> Void)
      func configure (_ view: BreachView, number index: Int)



      ViewModel
      class BreachViewModel : BreachViewModelType
      var breaches = BreachModel



      init() 
      // add init for ClosureHTTPManager here, to allow it to be teestable in the future


      func fetchData(completion: @escaping ([BreachModel]) -> Void)
      ClosureHTTPManager.shared.get(urlString: baseUrl + breachesExtensionURL, completionBlock: [weak self] result in
      guard let self = self else return
      switch result
      case .failure(let error):
      print ("failure", error)
      case .success(let dta) :
      let decoder = JSONDecoder()
      do

      self.breaches = try decoder.decode([BreachModel].self, from: dta)
      completion(try decoder.decode([BreachModel].self, from: dta))
      catch
      // deal with error from JSON decoding!


      )


      func numberItemsToDisplay() -> Int
      return breaches.count


      func configure (_ view: BreachView, number index: Int)
      // set the name and data in the view
      view.nameLabel.text = breaches[index].name





      and HTTP manager



       class ClosureHTTPManager 
      static let shared: ClosureHTTPManager = ClosureHTTPManager()

      enum HTTPError: Error


      case invalidURL
      case invalidResponse(Data?, URLResponse?)


      public func get(urlString: String, completionBlock: @escaping (Result<Data, Error>) -> Void)
      guard let url = URL(string: urlString) else
      completionBlock(.failure(HTTPError.invalidURL))
      return


      let task = URLSession.shared.dataTask(with: url) data, response, error in
      guard error == nil else
      completionBlock(.failure(error!))
      return


      guard
      let responseData = data,
      let httpResponse = response as? HTTPURLResponse,
      200 ..< 300 ~= httpResponse.statusCode else
      completionBlock(.failure(HTTPError.invalidResponse(data, response)))
      return


      completionBlock(.success(responseData))

      task.resume()




      Calling the API from



      let baseUrl : String = "https://haveibeenpwned.com/api/v2"
      let breachesExtensionURL : String = "/breaches"


      Any comments on whether the implementation conforms to MVVM or not, typos, changes etc. are appreciated.



      Git link: https://github.com/stevencurtis/MVVMWithNetworkService









      share









      $endgroup$




      I've been implementing MVVM in Swift. I've looked at several implementations, many of which violate some aspects of MVVM and wanted to have a go with my own version that contains a Web request service.



      View:



      class BreachView: UIView 
      var nameLabel = UILabel()
      public override init(frame: CGRect)
      let labelframe = CGRect(x: 0, y: 50, width: frame.width, height: 20)
      nameLabel.frame = labelframe
      nameLabel.backgroundColor = .gray
      super.init(frame: frame)
      self.addSubview(nameLabel)
      backgroundColor = .red


      required init?(coder aDecoder: NSCoder)
      fatalError("init(coder:) has not been implemented")




      ViewController
      class ViewController: UIViewController



      var breachesViewModel: BreachViewModelType!
      var breachView : BreachView?

      // to be called during testing
      init(viewModel: BreachViewModelType)
      breachesViewModel = viewModel
      super.init(nibName: nil, bundle: nil)


      // required when called from storyboard
      required init?(coder aDecoder: NSCoder)
      breachesViewModel = BreachViewModel()
      super.init(coder: aDecoder)


      override func viewDidLoad()
      super.viewDidLoad()
      breachesViewModel.fetchData [weak self] breaches in
      guard let self = self else return
      DispatchQueue.main.async
      self.updateUI()




      func updateUI()
      breachView = BreachView(frame: view.frame)
      breachesViewModel.configure(breachView!, number: 3)
      view.addSubview(breachView!)





      Protocol for dependency injection:



      protocol BreachViewModelType 
      func fetchData(completion: @escaping ([BreachModel]) -> Void)
      func configure (_ view: BreachView, number index: Int)



      ViewModel
      class BreachViewModel : BreachViewModelType
      var breaches = BreachModel



      init() 
      // add init for ClosureHTTPManager here, to allow it to be teestable in the future


      func fetchData(completion: @escaping ([BreachModel]) -> Void)
      ClosureHTTPManager.shared.get(urlString: baseUrl + breachesExtensionURL, completionBlock: [weak self] result in
      guard let self = self else return
      switch result
      case .failure(let error):
      print ("failure", error)
      case .success(let dta) :
      let decoder = JSONDecoder()
      do

      self.breaches = try decoder.decode([BreachModel].self, from: dta)
      completion(try decoder.decode([BreachModel].self, from: dta))
      catch
      // deal with error from JSON decoding!


      )


      func numberItemsToDisplay() -> Int
      return breaches.count


      func configure (_ view: BreachView, number index: Int)
      // set the name and data in the view
      view.nameLabel.text = breaches[index].name





      and HTTP manager



       class ClosureHTTPManager 
      static let shared: ClosureHTTPManager = ClosureHTTPManager()

      enum HTTPError: Error


      case invalidURL
      case invalidResponse(Data?, URLResponse?)


      public func get(urlString: String, completionBlock: @escaping (Result<Data, Error>) -> Void)
      guard let url = URL(string: urlString) else
      completionBlock(.failure(HTTPError.invalidURL))
      return


      let task = URLSession.shared.dataTask(with: url) data, response, error in
      guard error == nil else
      completionBlock(.failure(error!))
      return


      guard
      let responseData = data,
      let httpResponse = response as? HTTPURLResponse,
      200 ..< 300 ~= httpResponse.statusCode else
      completionBlock(.failure(HTTPError.invalidResponse(data, response)))
      return


      completionBlock(.success(responseData))

      task.resume()




      Calling the API from



      let baseUrl : String = "https://haveibeenpwned.com/api/v2"
      let breachesExtensionURL : String = "/breaches"


      Any comments on whether the implementation conforms to MVVM or not, typos, changes etc. are appreciated.



      Git link: https://github.com/stevencurtis/MVVMWithNetworkService







      swift





      share












      share










      share



      share










      asked 5 mins ago









      stevenpcurtisstevenpcurtis

      1227




      1227




















          0






          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: "196"
          ;
          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',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          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%2fcodereview.stackexchange.com%2fquestions%2f217371%2fmvvm-in-swift-ios%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217371%2fmvvm-in-swift-ios%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

          名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局

          Prove that NP is closed under karp reduction?Space(n) not closed under Karp reductions - what about NTime(n)?Class P is closed under rotation?Prove or disprove that $NL$ is closed under polynomial many-one reductions$mathbfNC_2$ is closed under log-space reductionOn Karp reductionwhen can I know if a class (complexity) is closed under reduction (cook/karp)Check if class $PSPACE$ is closed under polyonomially space reductionIs NPSPACE also closed under polynomial-time reduction and under log-space reduction?Prove PSPACE is closed under complement?Prove PSPACE is closed under union?

          Is my guitar’s action too high? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)Strings too stiff on a recently purchased acoustic guitar | Cort AD880CEIs the action of my guitar really high?Μy little finger is too weak to play guitarWith guitar, how long should I give my fingers to strengthen / callous?When playing a fret the guitar sounds mutedPlaying (Barre) chords up the guitar neckI think my guitar strings are wound too tight and I can't play barre chordsF barre chord on an SG guitarHow to find to the right strings of a barre chord by feel?High action on higher fret on my steel acoustic guitar