I have a map tool app in MacOS which needs request Location permission to show MapUserLocationButton.
During development, the request for permission can pop up for the first run in my mac, but when it comes to the Apple review(Submission ID: 11f52f82-1d54-481a-9eed-880521fda2b3), they never see that.
My mac is Macbook air M2 2022, 14.5 (23F79).
Of course, enable App Sandbox - Location and fill up the Privacy - Location When in Use Usage Description
Code:
//
// LocationManager.swift
//
import MapKit
@Observable
class LocationManager: NSObject {
static let shared = LocationManager()
private let manager = CLLocationManager()
var isReady: Bool = false
var showingAlert = false
// var location: CLLocationCoordinate2D?
var isAuthorized: Bool {
#if os(macOS)
.authorized == manager.authorizationStatus
#else
.authorizedWhenInUse == manager.authorizationStatus
#endif
}
private override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
setup()
}
private func setup() {
isReady = isAuthorized
#if os(macOS)
if CLLocationManager.locationServicesEnabled() {
checkStatus()
} else {
showingAlert = true
}
#else
checkStatus()
#endif
}
private func checkStatus() {
switch manager.authorizationStatus {
case .notDetermined:
manager.startUpdatingLocation()
#if os(macOS)
#else
manager.requestWhenInUseAuthorization()
#endif
#if os(macOS)
case .restricted, .denied:
showingAlert = true
case .authorizedAlways, .authorizedWhenInUse:
manager.startUpdatingLocation()
#else
// case .authorizedWhenInUse:
// manager.requestLocation()
#endif
default:
break
}
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
isReady = isAuthorized
guard isReady else { return }
// manager.requestLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// location = locations.last?.coordinate
}
}
Post
Replies
Boosts
Views
Activity
RectangleView with TextView slide into screen in 3 seconds, but state of TextView changed after a second while sliding. Now you can see TextView stops sliding, jumps to the destination at once.
I Just want the RectangleView with the TextView as a whole when sliding, and do not change TextView's position whatever it rotates or keeps still when state changed.
GIF dmeo:
https://stackoverflow.com/questions/65795434/swiftui-view-with-animation-jumps-to-destination-when-state-changed
import SwiftUI
struct RotationEnvironmentKey: EnvironmentKey {
static let defaultValue: Bool = false
}
extension EnvironmentValues {
var rotation: Bool {
get { return self[RotationEnvironmentKey] }
set { self[RotationEnvironmentKey] = newValue }
}
}
struct AnimationTestView: View {
@State private var go = false
@State private var rotation = false
var body: some View {
VStack {
Button("Go!") {
go.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
rotation.toggle()
print("set rotation = \(rotation)")
}
}
Group {
if go {
RectangleView()
.transition(.slide)
.environment(\.rotation, rotation)
}
}.animation(.easeInOut(duration: 3.0), value: go)
}.navigationTitle("Animation Test")
}
}
struct RectangleView: View {
var body: some View {
Rectangle()
.frame(width: 200, height: 100)
.foregroundColor(.pink)
.overlay(TextView())
}
}
struct TextView: View {
@Environment(\.rotation) var rotation
@State private var animationRotating: Bool = false
let animation = Animation.linear(duration: 3.0).repeatForever(autoreverses: false)
var body: some View {
print("refresh, rotation = \(rotation)"); return
HStack {
Spacer()
if rotation {
Text("R")
.foregroundColor(.blue)
.rotationEffect(.degrees(animationRotating ? 360 : 0))
.animation(animation, value: animationRotating)
.onAppear { animationRotating = true }
.onDisappear { animationRotating = false }
} else {
Text("S")
}
}
}
}
I have a LazyVGrid, every item with is favorite button. and use combine to debounce user input($isFavoriteI), when isFavoriteO changed, then modify the items.
it works fine, but when i scroll the list, log will print: "X, isFavorite changed as false/true)", what cause isFavoriteO changed and why? because of item reusing in list? how to avoid it?
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
index 7, isFavorite changed as true
import SwiftUI
import Combine
struct Item {
var index: Int
var favorite: Bool
}
var items = [
Item(index: 0, favorite: true),
Item(index: 1, favorite: false),
Item(index: 2, favorite: true),
Item(index: 3, favorite: false),
Item(index: 4, favorite: true),
Item(index: 5, favorite: false),
Item(index: 6, favorite: true),
Item(index: 7, favorite: false),
// Item(index: 8, favorite: true),
// Item(index: 9, favorite: false),
// Item(index: 10, favorite: true),
// Item(index: 11, favorite: false),
// Item(index: 12, favorite: true),
// Item(index: 13, favorite: false),
// Item(index: 14, favorite: true),
// Item(index: 15, favorite: false),
// Item(index: 16, favorite: true),
// Item(index: 17, favorite: false),
// Item(index: 18, favorite: true),
// Item(index: 19, favorite: false),
]
struct ViewModelInListTestView: View {
var body: some View {
ScrollView(showsIndicators: false) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 200), spacing: 4, alignment: .center)], spacing: 4) {
ForEach(items, id: \.index) { item in
ItemView(item: item)
}
}
}.navigationTitle("ViewModel In List")
}
}
struct ItemView: View {
let item: Item
@ObservedObject var viewModel: ViewModel
init(item: Item) {
print("ItemView.init, \(item.index)")
self.item = item
self.viewModel = ViewModel(item: item)
}
var body: some View {
HStack {
Text("index \(item.index)")
Spacer()
Image(systemName: viewModel.isFavoriteI ? "heart.fill" : "heart")
.foregroundColor(viewModel.isFavoriteI ? .red : .white)
.padding()
.onTapGesture { onFavoriteTapped() }
.onChange(of: viewModel.isFavoriteO) { isFavorite in
setFavorite(isFavorite)
}
}
.frame(width: 200, height: 150)
.background(Color.gray)
}
func onFavoriteTapped() {
viewModel.isFavoriteI.toggle()
}
func setFavorite(_ isFavorite: Bool) {
print("index \(item.index), isFavorite changed as \(isFavorite)")
items[item.index].favorite = isFavorite
}
class ViewModel: ObservableObject {
@Published var isFavoriteI: Bool = false
@Published var isFavoriteO: Bool = false
private var subscriptions: SetAnyCancellable = []
init(item: Item) {
print("ViewModel.init, \(item.index)")
let isFavorite = item.favorite
isFavoriteI = isFavorite; isFavoriteO = isFavorite
$isFavoriteI
.print("index \(item.index) isFavoriteI:")
.dropFirst()
.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
.removeDuplicates()
.eraseToAnyPublisher()
.print("index \(item.index) isFavoriteO:")
.receive(on: DispatchQueue.main)
.assign(to: \.isFavoriteO, on: self)
.store(in: &subscriptions)
}
}
}