Skip to content

Commit 1c3a22c

Browse files
committed
Upgrade "Drawing-and-Animation"
1 parent eb39d92 commit 1c3a22c

20 files changed

+413
-199
lines changed

Drawing-and-Animation/AppDelegate.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import UIKit
1111
@UIApplicationMain
1212
class AppDelegate: UIResponder, UIApplicationDelegate {
1313

14-
15-
1614
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1715
// Override point for customization after application launch.
1816
return true
@@ -23,7 +21,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2321
}
2422

2523
// MARK: UISceneSession Lifecycle
26-
2724
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
2825
// Called when a new scene session is being created.
2926
// Use this method to select a configuration to create the new scene with.
@@ -36,6 +33,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
3633
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
3734
}
3835

39-
4036
}
41-

Drawing-and-Animation/ContentView.swift

Lines changed: 0 additions & 23 deletions
This file was deleted.

Drawing-and-Animation/HikeDetail.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ struct HikeDetail: View {
2323
.frame(height: 200, alignment: .center)
2424

2525
HStack(spacing: 25) {
26-
ForEach(buttons.identified(by: \.0)) { value in
26+
ForEach(buttons, id: \.0) { value in
2727
Button(action: {
2828
self.dataToShow = value.1
2929
}) {
3030
Text(verbatim: value.0)
3131
.font(.system(size: 15))
32-
.color(value.1 == self.dataToShow
32+
.foregroundColor(value.1 == self.dataToShow
3333
? Color.gray
3434
: Color.accentColor)
3535
.animation(nil)
@@ -40,10 +40,8 @@ struct HikeDetail: View {
4040
}
4141
}
4242

43-
#if DEBUG
4443
struct HikeDetail_Previews: PreviewProvider {
4544
static var previews: some View {
4645
HikeDetail(hike: hikeData[0])
4746
}
4847
}
49-
#endif

Drawing-and-Animation/HikeView.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct HikeView: View {
1414
var transition: AnyTransition {
1515
let insertion = AnyTransition.move(edge: .trailing)
1616
.combined(with: .opacity)
17-
let removal = AnyTransition.scale()
17+
let removal = AnyTransition.scale
1818
.combined(with: .opacity)
1919
return .asymmetric(insertion: insertion, removal: removal)
2020
}
@@ -33,7 +33,7 @@ struct HikeView: View {
3333
}
3434

3535
Spacer()
36-
36+
3737
Button(action: {
3838
withAnimation {
3939
self.showDetail.toggle()
@@ -46,7 +46,7 @@ struct HikeView: View {
4646
.padding()
4747
}
4848
}
49-
49+
5050
if showDetail {
5151
HikeDetail(hike: hike)
5252
.transition(transition)
@@ -55,7 +55,6 @@ struct HikeView: View {
5555
}
5656
}
5757

58-
#if DEBUG
5958
struct HikeView_Previews: PreviewProvider {
6059
static var previews: some View {
6160
VStack {
@@ -65,4 +64,3 @@ struct HikeView_Previews: PreviewProvider {
6564
}
6665
}
6766
}
68-
#endif
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//
2+
// LandmarkDetail.swift
3+
// Drawing-and-Animation
4+
//
5+
// Created by Willie on 2019/10/11.
6+
//
7+
8+
import SwiftUI
9+
10+
struct LandmarkDetail: View {
11+
@EnvironmentObject var userData: UserData
12+
var landmark: Landmark
13+
14+
var landmarkIndex: Int {
15+
userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
16+
}
17+
18+
var body: some View {
19+
VStack {
20+
MapView(coordinate: landmark.locationCoordinate)
21+
.edgesIgnoringSafeArea(.top)
22+
.frame(height: 300)
23+
24+
CircleImage(image: landmark.image)
25+
.offset(x: 0, y: -130)
26+
.padding(.bottom, -130)
27+
28+
VStack(alignment: .leading) {
29+
HStack {
30+
Text(verbatim: landmark.name)
31+
.font(.title)
32+
33+
Button(action: {
34+
self.userData.landmarks[self.landmarkIndex]
35+
.isFavorite.toggle()
36+
}) {
37+
if self.userData.landmarks[self.landmarkIndex]
38+
.isFavorite {
39+
Image(systemName: "star.fill")
40+
.foregroundColor(Color.yellow)
41+
} else {
42+
Image(systemName: "star")
43+
.foregroundColor(Color.gray)
44+
}
45+
}
46+
}
47+
48+
HStack(alignment: .top) {
49+
Text(verbatim: landmark.park)
50+
.font(.subheadline)
51+
Spacer()
52+
Text(verbatim: landmark.state)
53+
.font(.subheadline)
54+
}
55+
}
56+
.padding()
57+
58+
Spacer()
59+
}
60+
}
61+
}
62+
63+
struct LandmarkDetail_Preview: PreviewProvider {
64+
static var previews: some View {
65+
let userData = UserData()
66+
return LandmarkDetail(landmark: userData.landmarks[0])
67+
.environmentObject(userData)
68+
}
69+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// LandmarkList.swift
3+
// Drawing-and-Animation
4+
//
5+
// Created by Willie on 2019/10/11.
6+
//
7+
8+
import SwiftUI
9+
10+
struct LandmarkList: View {
11+
@EnvironmentObject private var userData: UserData
12+
13+
var body: some View {
14+
NavigationView {
15+
List {
16+
Toggle(isOn: $userData.showFavoritesOnly) {
17+
Text("Show Favorites Only")
18+
}
19+
20+
ForEach(userData.landmarks) { landmark in
21+
if !self.userData.showFavoritesOnly || landmark.isFavorite {
22+
NavigationLink(
23+
destination: LandmarkDetail(landmark: landmark)
24+
.environmentObject(self.userData)
25+
) {
26+
LandmarkRow(landmark: landmark)
27+
}
28+
}
29+
}
30+
}
31+
.navigationBarTitle(Text("Landmarks"))
32+
}
33+
}
34+
}
35+
36+
struct LandmarksList_Previews: PreviewProvider {
37+
static var previews: some View {
38+
ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
39+
LandmarkList()
40+
.previewDevice(PreviewDevice(rawValue: deviceName))
41+
.previewDisplayName(deviceName)
42+
}
43+
.environmentObject(UserData())
44+
}
45+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// LandmarkRow.swift
3+
// Drawing-and-Animation
4+
//
5+
// Created by Willie on 2019/10/11.
6+
//
7+
8+
import SwiftUI
9+
10+
struct LandmarkRow: View {
11+
var landmark: Landmark
12+
13+
var body: some View {
14+
HStack {
15+
landmark.image
16+
.resizable()
17+
.frame(width: 50, height: 50)
18+
Text(verbatim: landmark.name)
19+
Spacer()
20+
21+
if landmark.isFavorite {
22+
Image(systemName: "star.fill")
23+
.imageScale(.medium)
24+
.foregroundColor(.yellow)
25+
}
26+
}
27+
}
28+
}
29+
30+
struct LandmarkRow_Previews: PreviewProvider {
31+
static var previews: some View {
32+
Group {
33+
LandmarkRow(landmark: landmarkData[0])
34+
LandmarkRow(landmark: landmarkData[1])
35+
}
36+
.previewLayout(.fixed(width: 300, height: 70))
37+
}
38+
}

Drawing-and-Animation/Models/Data.swift

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import CoreLocation
1010
import UIKit
1111
import SwiftUI
1212

13+
let landmarkData: [Landmark] = load("landmarkData.json")
1314
let hikeData: [Hike] = load("hikeData.json")
1415

1516
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
@@ -35,60 +36,35 @@ func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
3536
}
3637

3738
final class ImageStore {
38-
fileprivate typealias _ImageDictionary = [String: [Int: CGImage]]
39+
typealias _ImageDictionary = [String: CGImage]
3940
fileprivate var images: _ImageDictionary = [:]
4041

41-
fileprivate static var originalSize = 250
4242
fileprivate static var scale = 2
4343

4444
static var shared = ImageStore()
4545

46-
func image(name: String, size: Int) -> Image {
47-
let index = _guaranteeInitialImage(name: name)
46+
func image(name: String) -> Image {
47+
let index = _guaranteeImage(name: name)
4848

49-
let sizedImage = images.values[index][size]
50-
?? _sizeImage(images.values[index][ImageStore.originalSize]!, to: size * ImageStore.scale)
51-
images.values[index][size] = sizedImage
52-
53-
return Image(sizedImage, scale: Length(ImageStore.scale), label: Text(verbatim: name))
49+
return Image(images.values[index], scale: CGFloat(ImageStore.scale), label: Text(verbatim: name))
5450
}
5551

56-
fileprivate func _guaranteeInitialImage(name: String) -> _ImageDictionary.Index {
57-
if let index = images.index(forKey: name) { return index }
58-
52+
static func loadImage(name: String) -> CGImage {
5953
guard
6054
let url = Bundle.main.url(forResource: name, withExtension: "jpg"),
6155
let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil),
6256
let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
6357
else {
6458
fatalError("Couldn't load image \(name).jpg from main bundle.")
6559
}
66-
67-
images[name] = [ImageStore.originalSize: image]
68-
return images.index(forKey: name)!
60+
return image
6961
}
7062

71-
fileprivate func _sizeImage(_ image: CGImage, to size: Int) -> CGImage {
72-
guard
73-
let colorSpace = image.colorSpace,
74-
let context = CGContext(
75-
data: nil,
76-
width: size, height: size,
77-
bitsPerComponent: image.bitsPerComponent,
78-
bytesPerRow: image.bytesPerRow,
79-
space: colorSpace,
80-
bitmapInfo: image.bitmapInfo.rawValue)
81-
else {
82-
fatalError("Couldn't create graphics context.")
83-
}
84-
context.interpolationQuality = .high
85-
context.draw(image, in: CGRect(x: 0, y: 0, width: size, height: size))
63+
fileprivate func _guaranteeImage(name: String) -> _ImageDictionary.Index {
64+
if let index = images.index(forKey: name) { return index }
8665

87-
if let sizedImage = context.makeImage() {
88-
return sizedImage
89-
} else {
90-
fatalError("Couldn't resize image.")
91-
}
66+
images[name] = ImageStore.loadImage(name: name)
67+
return images.index(forKey: name)!
9268
}
9369
}
9470

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// Landmark.swift
3+
// Drawing-and-Animation
4+
//
5+
// Created by Willie on 2019/10/11.
6+
//
7+
8+
import SwiftUI
9+
import CoreLocation
10+
11+
struct Landmark: Hashable, Codable, Identifiable {
12+
var id: Int
13+
var name: String
14+
fileprivate var imageName: String
15+
fileprivate var coordinates: Coordinates
16+
var state: String
17+
var park: String
18+
var category: Category
19+
var isFavorite: Bool
20+
21+
var locationCoordinate: CLLocationCoordinate2D {
22+
CLLocationCoordinate2D(
23+
latitude: coordinates.latitude,
24+
longitude: coordinates.longitude)
25+
}
26+
27+
enum Category: String, CaseIterable, Codable, Hashable {
28+
case featured = "Featured"
29+
case lakes = "Lakes"
30+
case rivers = "Rivers"
31+
case mountains = "Mountains"
32+
}
33+
}
34+
35+
extension Landmark {
36+
var image: Image {
37+
ImageStore.shared.image(name: imageName)
38+
}
39+
}
40+
41+
struct Coordinates: Hashable, Codable {
42+
var latitude: Double
43+
var longitude: Double
44+
}

0 commit comments

Comments
 (0)