-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e43180d
commit be72141
Showing
28 changed files
with
2,525 additions
and
0 deletions.
There are no files selected for viewing
535 changes: 535 additions & 0 deletions
535
0163-navigation-pt4/SwiftUINavigation/SwiftUINavigation.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
...wiftUINavigation/SwiftUINavigation.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
...ion/SwiftUINavigation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
11 changes: 11 additions & 0 deletions
11
...t4/SwiftUINavigation/SwiftUINavigation/Assets.xcassets/AccentColor.colorset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
...-pt4/SwiftUINavigation/SwiftUINavigation/Assets.xcassets/AppIcon.appiconset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "2x", | ||
"size" : "20x20" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "3x", | ||
"size" : "20x20" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "2x", | ||
"size" : "29x29" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "3x", | ||
"size" : "29x29" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "2x", | ||
"size" : "40x40" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "3x", | ||
"size" : "40x40" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "2x", | ||
"size" : "60x60" | ||
}, | ||
{ | ||
"idiom" : "iphone", | ||
"scale" : "3x", | ||
"size" : "60x60" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "1x", | ||
"size" : "20x20" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "2x", | ||
"size" : "20x20" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "1x", | ||
"size" : "29x29" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "2x", | ||
"size" : "29x29" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "1x", | ||
"size" : "40x40" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "2x", | ||
"size" : "40x40" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "1x", | ||
"size" : "76x76" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "2x", | ||
"size" : "76x76" | ||
}, | ||
{ | ||
"idiom" : "ipad", | ||
"scale" : "2x", | ||
"size" : "83.5x83.5" | ||
}, | ||
{ | ||
"idiom" : "ios-marketing", | ||
"scale" : "1x", | ||
"size" : "1024x1024" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
0163-navigation-pt4/SwiftUINavigation/SwiftUINavigation/Assets.xcassets/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
0163-navigation-pt4/SwiftUINavigation/SwiftUINavigation/ContentView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import SwiftUI | ||
|
||
enum Tab { | ||
case one, inventory, three | ||
} | ||
|
||
class AppViewModel: ObservableObject { | ||
@Published var inventoryViewModel: InventoryViewModel | ||
@Published var selectedTab: Tab | ||
|
||
init( | ||
inventoryViewModel: InventoryViewModel = .init(), | ||
selectedTab: Tab = .one | ||
) { | ||
self.inventoryViewModel = inventoryViewModel | ||
self.selectedTab = selectedTab | ||
} | ||
} | ||
|
||
struct ContentView: View { | ||
@ObservedObject var viewModel: AppViewModel | ||
|
||
var body: some View { | ||
TabView(selection: self.$viewModel.selectedTab) { | ||
Button("Go to 2nd tab") { | ||
self.viewModel.selectedTab = .inventory | ||
} | ||
.tabItem { Text("One") } | ||
.tag(Tab.one) | ||
|
||
NavigationView { | ||
InventoryView(viewModel: self.viewModel.inventoryViewModel) | ||
} | ||
.tabItem { Text("Inventory") } | ||
.tag(Tab.inventory) | ||
|
||
Text("Three") | ||
.tabItem { Text("Three") } | ||
.tag(Tab.three) | ||
} | ||
} | ||
} | ||
|
||
struct ContentView_Previews: PreviewProvider { | ||
static var previews: some View { | ||
ContentView(viewModel: .init(selectedTab: .inventory)) | ||
} | ||
} |
167 changes: 167 additions & 0 deletions
167
0163-navigation-pt4/SwiftUINavigation/SwiftUINavigation/Inventory.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import IdentifiedCollections | ||
import SwiftUI | ||
|
||
struct Item: Equatable, Identifiable { | ||
let id = UUID() | ||
var name: String | ||
var color: Color? | ||
var status: Status | ||
|
||
enum Status: Equatable { | ||
case inStock(quantity: Int) | ||
case outOfStock(isOnBackOrder: Bool) | ||
|
||
var isInStock: Bool { | ||
guard case .inStock = self else { return false } | ||
return true | ||
} | ||
} | ||
|
||
struct Color: Equatable, Hashable { | ||
var name: String | ||
var red: CGFloat = 0 | ||
var green: CGFloat = 0 | ||
var blue: CGFloat = 0 | ||
|
||
static var defaults: [Self] = [ | ||
.red, | ||
.green, | ||
.blue, | ||
.black, | ||
.yellow, | ||
.white, | ||
] | ||
|
||
static let red = Self(name: "Red", red: 1) | ||
static let green = Self(name: "Green", green: 1) | ||
static let blue = Self(name: "Blue", blue: 1) | ||
static let black = Self(name: "Black") | ||
static let yellow = Self(name: "Yellow", red: 1, green: 1) | ||
static let white = Self(name: "White", red: 1, green: 1, blue: 1) | ||
|
||
var swiftUIColor: SwiftUI.Color { | ||
.init(red: self.red, green: self.green, blue: self.blue) | ||
} | ||
} | ||
} | ||
|
||
class InventoryViewModel: ObservableObject { | ||
@Published var inventory: IdentifiedArrayOf<ItemRowViewModel> | ||
@Published var itemToAdd: Item? | ||
|
||
init( | ||
inventory: IdentifiedArrayOf<ItemRowViewModel> = [], | ||
itemToAdd: Item? = nil | ||
) { | ||
self.itemToAdd = itemToAdd | ||
self.inventory = [] | ||
|
||
for itemRowViewModel in inventory { | ||
self.bind(itemRowViewModel: itemRowViewModel) | ||
} | ||
} | ||
|
||
private func bind(itemRowViewModel: ItemRowViewModel) { | ||
itemRowViewModel.onDelete = { [weak self, item = itemRowViewModel.item] in | ||
withAnimation { | ||
self?.delete(item: item) | ||
} | ||
} | ||
self.inventory.append(itemRowViewModel) | ||
} | ||
|
||
func delete(item: Item) { | ||
withAnimation { | ||
_ = self.inventory.remove(id: item.id) | ||
} | ||
} | ||
|
||
func add(item: Item) { | ||
withAnimation { | ||
self.bind(itemRowViewModel: .init(item: item)) | ||
self.itemToAdd = nil | ||
} | ||
} | ||
|
||
func addButtonTapped() { | ||
self.itemToAdd = .init(name: "", color: nil, status: .inStock(quantity: 1)) | ||
|
||
Task { @MainActor in | ||
try await Task.sleep(nanoseconds: 500 * NSEC_PER_MSEC) | ||
self.itemToAdd?.name = "Bluetooth Keyboard" | ||
} | ||
} | ||
|
||
func cancelButtonTapped() { | ||
self.itemToAdd = nil | ||
} | ||
} | ||
|
||
struct InventoryView: View { | ||
@ObservedObject var viewModel: InventoryViewModel | ||
|
||
var body: some View { | ||
List { | ||
ForEach( | ||
self.viewModel.inventory, | ||
content: ItemRowView.init(viewModel:) | ||
) | ||
} | ||
.toolbar { | ||
ToolbarItem(placement: .primaryAction) { | ||
Button("Add") { self.viewModel.addButtonTapped() } | ||
} | ||
} | ||
.navigationTitle("Inventory") | ||
// .sheet(isPresented: self.$addItemIsPresented) { | ||
.sheet(unwrap: self.$viewModel.itemToAdd) { $itemToAdd in | ||
NavigationView { | ||
ItemView(item: $itemToAdd) | ||
.navigationTitle("Add") | ||
.toolbar { | ||
ToolbarItem(placement: .cancellationAction) { | ||
Button("Cancel") { self.viewModel.cancelButtonTapped() } | ||
} | ||
ToolbarItem(placement: .primaryAction) { | ||
Button("Save") { self.viewModel.add(item: itemToAdd) } | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
struct TestView: View { | ||
@State var collection = [1, 2, 3] | ||
|
||
var body: some View { | ||
ForEach(self.$collection, id: \.self) { $element in | ||
|
||
} | ||
} | ||
} | ||
|
||
// ForEach.init: (Binding<C>, (Binding<C.Element>) -> some View) -> ForEach | ||
// sheet(unwrap:): (Binding<V?>, (Binding<V>) -> some View) -> some View | ||
|
||
|
||
|
||
struct InventoryView_Previews: PreviewProvider { | ||
static var previews: some View { | ||
let keyboard = Item(name: "Keyboard", color: .blue, status: .inStock(quantity: 100)) | ||
|
||
NavigationView { | ||
InventoryView( | ||
viewModel: .init( | ||
inventory: [ | ||
.init(item: keyboard), | ||
.init(item: Item(name: "Charger", color: .yellow, status: .inStock(quantity: 20))), | ||
.init(item: Item(name: "Phone", color: .green, status: .outOfStock(isOnBackOrder: true))), | ||
.init(item: Item(name: "Headphones", color: .green, status: .outOfStock(isOnBackOrder: false))), | ||
], | ||
itemToAdd: nil // .init(name: "Mouse", color: .red, status: .inStock(quantity: 100)), | ||
) | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.