在 Swift 5/Swiftui 中重构一个 MapView(没有 Coordinators / UIViewRepresentables)
Refactor a MapView in Swift 5/Swiftui (Without Coordinators / UIViewRepresentables)
我现在有我想要的行为,但我想重构这段代码。我想将所有地图逻辑从我的视图中移除。
在持有这张地图的视图中,我有以下内容:
import SwiftUI
import MapKit
struct PostActivityView: View {
@EnvironmentObject var viewModel: ActivitiesViewModel
@EnvironmentObject var user: UserViewModel
@State var region: MKCoordinateRegion
@Binding var parentsTab: Tab
@State private var locations = [MKPointAnnotation]()
@State private var userTracking = MapUserTrackingMode.follow
.
.
.
ZStack{
Map(coordinateRegion: $region, interactionModes: [MapInteractionModes.all], showsUserLocation: true, userTrackingMode: $userTracking)
.frame( height: 386)
.frame(height: 256)
.cornerRadius(25.0)
.shadow(radius: 10.0, x: 20, y: 10)
Circle()
.fill(Color.blue)
.opacity(0.3)
.frame(width: 16, height: 16)
Circle()
.fill(Color.black)
.opacity(0.3)
.frame(width: 1, height: 1)
HStack {
Spacer()
VStack {
Spacer()
HStack(){
VStack(){
Button(action: {zoom()}) {Image(systemName: "location.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
.rotationEffect(.degrees(30))
}
}
VStack(){
Button(action: {saveCrosshairLocation()}) {
Image(systemName: "checkmark.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
}
}}}
}
}
还有这两个函数:
func saveCrosshairLocation() {
let newLocation = MKPointAnnotation()
newLocation.coordinate = self.region.center
self.locations.append(newLocation)
let local: CLLocation = CLLocation(latitude: self.region.center.latitude , longitude: self.region.center.longitude)
CLGeocoder().reverseGeocodeLocation(local) { (placemarks, error) in
guard error == nil else {
print("ReverseGeocode Error: \(String(describing: error))")
return
}
if let firstPlacemark = placemarks?.first {
print(firstPlacemark)
var addressString : String = ""
if firstPlacemark.name != nil {
addressString = addressString + firstPlacemark.name! + ", "
}else {
if firstPlacemark.subThoroughfare != nil {
addressString = addressString + firstPlacemark.subThoroughfare! + ", "
}
if firstPlacemark.thoroughfare != nil {
addressString = addressString + firstPlacemark.thoroughfare! + ", "
}
}
if firstPlacemark.subLocality != nil {
addressString = addressString + firstPlacemark.subLocality! + ", "
}
if firstPlacemark.locality != nil {
addressString = addressString + firstPlacemark.locality! + ", "
}
if firstPlacemark.country != nil {
addressString = addressString + firstPlacemark.country! + ", "
}
if firstPlacemark.postalCode != nil {
addressString = addressString + firstPlacemark.postalCode! + ", "
}
if firstPlacemark.region != nil {
addressString = addressString + "<\(local.coordinate.latitude),\(local.coordinate.longitude)>"
}
self.eventLocation = addressString
}
}
}
func zoom() {
let newZoom = 0.08
self.region = MKCoordinateRegion(center: user.getLocation(), span: MKCoordinateSpan(latitudeDelta: newZoom, longitudeDelta: newZoom))
}
我想将其重构为它自己的 CustomMapView.swift。我不确定 Map 是否与当前版本 swift 中的 MKMapView 相同。我不确定如何将它们绑定在一起。对于 customMapView,我希望有几个带有 @Binding 语法的变量,但同样,我在进行此重构时遇到了问题。
目标是让我成为更好的程序员,感谢您的帮助。
我主视图中的代码现在是:
Header:
struct PostActivityView: View {
@EnvironmentObject var viewModel: ActivitiesViewModel
@EnvironmentObject var user: UserViewModel
@State var region: MKCoordinateRegion
@Binding var parentsTab: Tab
@State private var locations = [MKPointAnnotation]()
@State private var userTracking = MapUserTrackingMode.follow
.
.
.
Body:
.
.
.
ForPlay_MapView(region: $region, userTracking: $userTracking, locations: $locations, eventLocation: $eventLocation)
.
.
.
地图视图现在是:
import SwiftUI
import MapKit
struct ForPlay_MapView : View {
@EnvironmentObject var user: UserViewModel
@Binding var region: MKCoordinateRegion
@Binding var userTracking: MapUserTrackingMode
@Binding var locations: [MKPointAnnotation]
@Binding var eventLocation: String
var body: some View {
ZStack{
Map(coordinateRegion: $region, interactionModes: [MapInteractionModes.all], showsUserLocation: true, userTrackingMode: $userTracking)
.frame( height: 386)
.frame(height: 256)
.cornerRadius(25.0)
.shadow(radius: 10.0, x: 20, y: 10)
Circle()
.fill(Color.blue)
.opacity(0.3)
.frame(width: 16, height: 16)
Circle()
.fill(Color.black)
.opacity(0.3)
.frame(width: 1, height: 1)
HStack {
Spacer()
VStack {
Spacer()
HStack(){
VStack(){
Button(action: {zoom()}) {Image(systemName: "location.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
.rotationEffect(.degrees(30))
}
}
VStack(){
Button(action: {saveCrosshairLocation()}) {
Image(systemName: "checkmark.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
}
}}}
}
}
}
func saveCrosshairLocation() {
let newLocation = MKPointAnnotation()
newLocation.coordinate = self.region.center
self.locations.append(newLocation)
let local: CLLocation = CLLocation(latitude: self.region.center.latitude , longitude: self.region.center.longitude)
CLGeocoder().reverseGeocodeLocation(local) { (placemarks, error) in
guard error == nil else {
print("ReverseGeocode Error: \(String(describing: error))")
return
}
if let firstPlacemark = placemarks?.first {
print(firstPlacemark)
var addressString : String = ""
if firstPlacemark.name != nil {
addressString = addressString + firstPlacemark.name! + ", "
}else {
if firstPlacemark.subThoroughfare != nil {
addressString = addressString + firstPlacemark.subThoroughfare! + ", "
}
if firstPlacemark.thoroughfare != nil {
addressString = addressString + firstPlacemark.thoroughfare! + ", "
}
}
if firstPlacemark.subLocality != nil {
addressString = addressString + firstPlacemark.subLocality! + ", "
}
if firstPlacemark.locality != nil {
addressString = addressString + firstPlacemark.locality! + ", "
}
if firstPlacemark.country != nil {
addressString = addressString + firstPlacemark.country! + ", "
}
if firstPlacemark.postalCode != nil {
addressString = addressString + firstPlacemark.postalCode! + ", "
}
if firstPlacemark.region != nil {
addressString = addressString + "<\(local.coordinate.latitude),\(local.coordinate.longitude)>"
}
self.eventLocation = addressString
}
}
}
func zoom() {
let newZoom = 0.08
self.region = MKCoordinateRegion(center: user.getLocation(), span: MKCoordinateSpan(latitudeDelta: newZoom, longitudeDelta: newZoom))
}
}
我现在有我想要的行为,但我想重构这段代码。我想将所有地图逻辑从我的视图中移除。
在持有这张地图的视图中,我有以下内容:
import SwiftUI
import MapKit
struct PostActivityView: View {
@EnvironmentObject var viewModel: ActivitiesViewModel
@EnvironmentObject var user: UserViewModel
@State var region: MKCoordinateRegion
@Binding var parentsTab: Tab
@State private var locations = [MKPointAnnotation]()
@State private var userTracking = MapUserTrackingMode.follow
.
.
.
ZStack{
Map(coordinateRegion: $region, interactionModes: [MapInteractionModes.all], showsUserLocation: true, userTrackingMode: $userTracking)
.frame( height: 386)
.frame(height: 256)
.cornerRadius(25.0)
.shadow(radius: 10.0, x: 20, y: 10)
Circle()
.fill(Color.blue)
.opacity(0.3)
.frame(width: 16, height: 16)
Circle()
.fill(Color.black)
.opacity(0.3)
.frame(width: 1, height: 1)
HStack {
Spacer()
VStack {
Spacer()
HStack(){
VStack(){
Button(action: {zoom()}) {Image(systemName: "location.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
.rotationEffect(.degrees(30))
}
}
VStack(){
Button(action: {saveCrosshairLocation()}) {
Image(systemName: "checkmark.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
}
}}}
}
}
还有这两个函数:
func saveCrosshairLocation() {
let newLocation = MKPointAnnotation()
newLocation.coordinate = self.region.center
self.locations.append(newLocation)
let local: CLLocation = CLLocation(latitude: self.region.center.latitude , longitude: self.region.center.longitude)
CLGeocoder().reverseGeocodeLocation(local) { (placemarks, error) in
guard error == nil else {
print("ReverseGeocode Error: \(String(describing: error))")
return
}
if let firstPlacemark = placemarks?.first {
print(firstPlacemark)
var addressString : String = ""
if firstPlacemark.name != nil {
addressString = addressString + firstPlacemark.name! + ", "
}else {
if firstPlacemark.subThoroughfare != nil {
addressString = addressString + firstPlacemark.subThoroughfare! + ", "
}
if firstPlacemark.thoroughfare != nil {
addressString = addressString + firstPlacemark.thoroughfare! + ", "
}
}
if firstPlacemark.subLocality != nil {
addressString = addressString + firstPlacemark.subLocality! + ", "
}
if firstPlacemark.locality != nil {
addressString = addressString + firstPlacemark.locality! + ", "
}
if firstPlacemark.country != nil {
addressString = addressString + firstPlacemark.country! + ", "
}
if firstPlacemark.postalCode != nil {
addressString = addressString + firstPlacemark.postalCode! + ", "
}
if firstPlacemark.region != nil {
addressString = addressString + "<\(local.coordinate.latitude),\(local.coordinate.longitude)>"
}
self.eventLocation = addressString
}
}
}
func zoom() {
let newZoom = 0.08
self.region = MKCoordinateRegion(center: user.getLocation(), span: MKCoordinateSpan(latitudeDelta: newZoom, longitudeDelta: newZoom))
}
我想将其重构为它自己的 CustomMapView.swift。我不确定 Map 是否与当前版本 swift 中的 MKMapView 相同。我不确定如何将它们绑定在一起。对于 customMapView,我希望有几个带有 @Binding 语法的变量,但同样,我在进行此重构时遇到了问题。
目标是让我成为更好的程序员,感谢您的帮助。
我主视图中的代码现在是:
Header:
struct PostActivityView: View {
@EnvironmentObject var viewModel: ActivitiesViewModel
@EnvironmentObject var user: UserViewModel
@State var region: MKCoordinateRegion
@Binding var parentsTab: Tab
@State private var locations = [MKPointAnnotation]()
@State private var userTracking = MapUserTrackingMode.follow
.
.
.
Body:
.
.
.
ForPlay_MapView(region: $region, userTracking: $userTracking, locations: $locations, eventLocation: $eventLocation)
.
.
.
地图视图现在是:
import SwiftUI
import MapKit
struct ForPlay_MapView : View {
@EnvironmentObject var user: UserViewModel
@Binding var region: MKCoordinateRegion
@Binding var userTracking: MapUserTrackingMode
@Binding var locations: [MKPointAnnotation]
@Binding var eventLocation: String
var body: some View {
ZStack{
Map(coordinateRegion: $region, interactionModes: [MapInteractionModes.all], showsUserLocation: true, userTrackingMode: $userTracking)
.frame( height: 386)
.frame(height: 256)
.cornerRadius(25.0)
.shadow(radius: 10.0, x: 20, y: 10)
Circle()
.fill(Color.blue)
.opacity(0.3)
.frame(width: 16, height: 16)
Circle()
.fill(Color.black)
.opacity(0.3)
.frame(width: 1, height: 1)
HStack {
Spacer()
VStack {
Spacer()
HStack(){
VStack(){
Button(action: {zoom()}) {Image(systemName: "location.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
.rotationEffect(.degrees(30))
}
}
VStack(){
Button(action: {saveCrosshairLocation()}) {
Image(systemName: "checkmark.circle.fill")
.background(Color.blue.opacity(0.75))
.foregroundColor(.white)
.font(.title)
.clipShape(Circle())
}
}}}
}
}
}
func saveCrosshairLocation() {
let newLocation = MKPointAnnotation()
newLocation.coordinate = self.region.center
self.locations.append(newLocation)
let local: CLLocation = CLLocation(latitude: self.region.center.latitude , longitude: self.region.center.longitude)
CLGeocoder().reverseGeocodeLocation(local) { (placemarks, error) in
guard error == nil else {
print("ReverseGeocode Error: \(String(describing: error))")
return
}
if let firstPlacemark = placemarks?.first {
print(firstPlacemark)
var addressString : String = ""
if firstPlacemark.name != nil {
addressString = addressString + firstPlacemark.name! + ", "
}else {
if firstPlacemark.subThoroughfare != nil {
addressString = addressString + firstPlacemark.subThoroughfare! + ", "
}
if firstPlacemark.thoroughfare != nil {
addressString = addressString + firstPlacemark.thoroughfare! + ", "
}
}
if firstPlacemark.subLocality != nil {
addressString = addressString + firstPlacemark.subLocality! + ", "
}
if firstPlacemark.locality != nil {
addressString = addressString + firstPlacemark.locality! + ", "
}
if firstPlacemark.country != nil {
addressString = addressString + firstPlacemark.country! + ", "
}
if firstPlacemark.postalCode != nil {
addressString = addressString + firstPlacemark.postalCode! + ", "
}
if firstPlacemark.region != nil {
addressString = addressString + "<\(local.coordinate.latitude),\(local.coordinate.longitude)>"
}
self.eventLocation = addressString
}
}
}
func zoom() {
let newZoom = 0.08
self.region = MKCoordinateRegion(center: user.getLocation(), span: MKCoordinateSpan(latitudeDelta: newZoom, longitudeDelta: newZoom))
}
}