Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor improvements and tidying up of SwiftUI tech test #6

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified AppScreenshot1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified AppScreenshot2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 36 additions & 10 deletions iOSTest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
4707CD60287DCE82005C7D16 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4707CD5F287DCE82005C7D16 /* NetworkService.swift */; };
4707CD6E2886B3F0005C7D16 /* Rating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4707CD6D2886B3F0005C7D16 /* Rating.swift */; };
4707CD702886B976005C7D16 /* AuthorityDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4707CD6F2886B976005C7D16 /* AuthorityDetailView.swift */; };
4707CD722886BBAD005C7D16 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4707CD712886BBAD005C7D16 /* Launch Screen.storyboard */; };
4F21164029477C22003BE2A5 /* AuthorityListViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F21163F29477C22003BE2A5 /* AuthorityListViewModelTests.swift */; };
4F211642294785E7003BE2A5 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F211641294785E7003BE2A5 /* ContentView.swift */; };
E7EDD57328EB3ECE00B0393B /* AuthorityListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7EDD57228EB3ECE00B0393B /* AuthorityListViewModel.swift */; };
/* End PBXBuildFile section */

Expand All @@ -39,8 +40,10 @@
4707CD5F287DCE82005C7D16 /* NetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = "<group>"; };
4707CD6D2886B3F0005C7D16 /* Rating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rating.swift; sourceTree = "<group>"; };
4707CD6F2886B976005C7D16 /* AuthorityDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorityDetailView.swift; sourceTree = "<group>"; };
4707CD712886BBAD005C7D16 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
4707CD772886E7E6005C7D16 /* iOSTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4F21163F29477C22003BE2A5 /* AuthorityListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorityListViewModelTests.swift; sourceTree = "<group>"; };
4F211641294785E7003BE2A5 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
4F21C1FF2943898300ED66F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
E7EDD57228EB3ECE00B0393B /* AuthorityListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorityListViewModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand All @@ -66,6 +69,7 @@
isa = PBXGroup;
children = (
4707CD4C287DCCE8005C7D16 /* iOSTest */,
4F21163D29477BFC003BE2A5 /* iOSUnitTests */,
4707CD4B287DCCE8005C7D16 /* Products */,
);
sourceTree = "<group>";
Expand All @@ -82,6 +86,7 @@
4707CD4C287DCCE8005C7D16 /* iOSTest */ = {
isa = PBXGroup;
children = (
4F21C1FF2943898300ED66F8 /* Info.plist */,
E7EDD57128EB3E7E00B0393B /* App */,
4707CD51287DCCEC005C7D16 /* Assets.xcassets */,
4707CD61288047F8005C7D16 /* UI */,
Expand Down Expand Up @@ -126,6 +131,14 @@
path = UI;
sourceTree = "<group>";
};
4F21163D29477BFC003BE2A5 /* iOSUnitTests */ = {
isa = PBXGroup;
children = (
4F21163F29477C22003BE2A5 /* AuthorityListViewModelTests.swift */,
);
path = iOSUnitTests;
sourceTree = "<group>";
};
E7EDD56E28EB3DE900B0393B /* AuthorityList */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -156,7 +169,7 @@
isa = PBXGroup;
children = (
4707CD4D287DCCE8005C7D16 /* UpdatediOSTestApp.swift */,
4707CD712886BBAD005C7D16 /* Launch Screen.storyboard */,
4F211641294785E7003BE2A5 /* ContentView.swift */,
);
path = App;
sourceTree = "<group>";
Expand Down Expand Up @@ -214,6 +227,7 @@
};
4707CD762886E7E6005C7D16 = {
CreatedOnToolsVersion = 13.4.1;
LastSwiftMigration = 1400;
TestTargetID = 4707CD49287DCCE8005C7D16;
};
};
Expand Down Expand Up @@ -242,7 +256,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4707CD722886BBAD005C7D16 /* Launch Screen.storyboard in Resources */,
4707CD55287DCCEC005C7D16 /* Preview Assets.xcassets in Resources */,
4707CD52287DCCEC005C7D16 /* Assets.xcassets in Resources */,
);
Expand All @@ -264,6 +277,7 @@
files = (
4707CD50287DCCE8005C7D16 /* AuthorityListView.swift in Sources */,
4707CD702886B976005C7D16 /* AuthorityDetailView.swift in Sources */,
4F211642294785E7003BE2A5 /* ContentView.swift in Sources */,
E7EDD57328EB3ECE00B0393B /* AuthorityListViewModel.swift in Sources */,
4707CD4E287DCCE8005C7D16 /* UpdatediOSTestApp.swift in Sources */,
4707CD5D287DCD20005C7D16 /* Authority.swift in Sources */,
Expand All @@ -276,6 +290,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4F21164029477C22003BE2A5 /* AuthorityListViewModelTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -414,10 +429,9 @@
DEVELOPMENT_ASSET_PATHS = "\"iOSTest/Preview Content\"";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iOSTest/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -443,10 +457,9 @@
DEVELOPMENT_ASSET_PATHS = "\"iOSTest/Preview Content\"";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iOSTest/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -466,33 +479,46 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.Gabby.UpdatediOSTestTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UpdatediOSTest.app/UpdatediOSTest";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOSTest";
};
name = Debug;
};
4707CD7F2886E7E6005C7D16 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.Gabby.UpdatediOSTestTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UpdatediOSTest.app/UpdatediOSTest";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOSTest";
};
name = Release;
};
Expand Down
20 changes: 20 additions & 0 deletions iOSTest/App/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// ContentView.swift
// iOSTest
//
// Created by m.houghton on 12/12/2022.
//

import SwiftUI

struct ContentView: View {
var body: some View {
AuthorityListView()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
53 changes: 0 additions & 53 deletions iOSTest/App/Launch Screen.storyboard

This file was deleted.

2 changes: 1 addition & 1 deletion iOSTest/App/UpdatediOSTestApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwiftUI
struct UpdatediOSTestApp: App {
var body: some Scene {
WindowGroup {
AuthorityListView()
ContentView()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xFF",
"green" : "0xFF",
"red" : "0xFF"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
15 changes: 15 additions & 0 deletions iOSTest/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Launch Screens can now be done entirely within Info.plist without the need to maintain a storyboard.

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UILaunchScreen</key>
<dict>
<key>UIColorName</key>
<string>LaunchScreenBackground</string>
<key>UIImageName</key>
<string>FSALogo</string>
<key>UIImageRespectsSafeAreaInsets</key>
<true/>
</dict>
</dict>
</plist>
22 changes: 13 additions & 9 deletions iOSTest/NetworkService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@ import Foundation


protocol NetworkProvider {
func getAuthorities() async throws -> Result<[Authority], Error>
func getAuthorities() async throws -> AuthoritiesResponse
}

class NetworkService: NetworkProvider {

enum AuthoritiesFetcherError: Error {
case invalidURL
case missingData
}

private static let baseUrl = "https://api.ratings.food.gov.uk"

func getAuthorities() async throws -> Result<[Authority], Error> {
func getAuthorities() async throws -> AuthoritiesResponse {
guard let url = URL(string: NetworkService.baseUrl + "/authorities/basic") else {
return .failure(AuthoritiesFetcherError.invalidURL)
throw AuthoritiesFetcherError.invalidURL
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated this to make use of the throw in the method signature

}

var urlRequest = URLRequest(url: url)
Expand All @@ -26,6 +21,15 @@ class NetworkService: NetworkProvider {
let (data, _) = try await URLSession.shared.data(for: urlRequest)

let authoritiesResult = try JSONDecoder().decode(AuthoritiesResponse.self, from: data)
return .success(authoritiesResult.authorities)
return authoritiesResult
}
}

extension NetworkService {
enum AuthoritiesFetcherError: Error {
case invalidURL
case unexpected(error: Error)
}
}


34 changes: 28 additions & 6 deletions iOSTest/UI/AuthorityList/AuthorityListView.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import SwiftUI

struct AuthorityListView: View {
@StateObject var viewModel = ViewModel()
@StateObject private var viewModel = AuthorityListViewModel()
@State private var showingCopyright = false

var body: some View {
VStack(alignment: .leading) {
NavigationView {
if viewModel.loading {
if viewModel.isLoading {
ProgressView()
} else if viewModel.error {
Text("Network Error")
} else if viewModel.hasError {
networkErrorView
} else {
List {
ForEach(viewModel.authorities, id: \.self) { authority in
Expand All @@ -19,16 +20,37 @@ struct AuthorityListView: View {
}
}
.navigationTitle("Local Authorities")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
Button {
showingCopyright.toggle()
} label: {
Image(systemName: "info.circle")
}
}
.alert("Copyright © 2022 Infinity Works, Part of Accenture.", isPresented: $showingCopyright) {
} message: {
Text("All rights reserved.")
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new launch screen loses the copyright message, so I added it as a toolbar button alert instead.

}
}.task {
await viewModel.update()
}
}
}

var networkErrorView: some View {
VStack {
Image(systemName: "wifi.exclamationmark")
Text("Network Error")
.font(.headline)
Text("Something went wrong...")
.font(.subheadline)
.foregroundColor(.gray)
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple error view for if network request fails.

}

struct ContentView_Previews: PreviewProvider {
struct AuthorityListView_Previews: PreviewProvider {
static var previews: some View {
AuthorityListView()
}
Expand Down
Loading