MVVM in Swift iOS The 2019 Stack Overflow Developer Survey Results Are In ...
Sort list of array linked objects by keys and values
What can I do if neighbor is blocking my solar panels intentionally?
Could an empire control the whole planet with today's comunication methods?
Are spiders unable to hurt humans, especially very small spiders?
Can each chord in a progression create its own key?
What would this chord progression be called?
One-dimensional Japanese puzzle
Are there continuous functions who are the same in an interval but differ in at least one other point?
What to do when moving next to a bird sanctuary with a loosely-domesticated cat?
Why did Peik Lin say, "I'm not an animal"?
How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time
What was the last x86 CPU that did not have the x87 floating-point unit built in?
Didn't get enough time to take a Coding Test - what to do now?
Button changing its text & action. Good or terrible?
Did the new image of black hole confirm the general theory of relativity?
How do spell lists change if the party levels up without taking a long rest?
What aspect of planet Earth must be changed to prevent the industrial revolution?
My body leaves; my core can stay
Can the Right Ascension and Argument of Perigee of a spacecraft's orbit keep varying by themselves with time?
Accepted by European university, rejected by all American ones I applied to? Possible reasons?
Homework question about an engine pulling a train
Am I ethically obligated to go into work on an off day if the reason is sudden?
Can withdrawing asylum be illegal?
University's motivation for having tenure-track positions
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)
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom: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
swift
$endgroup$
add a comment |
$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
swift
$endgroup$
add a comment |
$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
swift
$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
swift
asked 2 mins ago
stevenpcurtisstevenpcurtis
1227
1227
add a comment |
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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