I want use SensorKit data for research purposes in my current app.
I have applied for and received permission from Apple to access SensorKit Data. I have granting all the necessary permissions. But no data retrieved.
I am using didCompleteFetch for retrieving data from Sensorkit. CompleteFetch method calls but find the data. Below is my SensorKitManager Code.
import SensorKit
import Foundation
protocol SensorManagerDelegate: AnyObject {
func didFetchPhoneUsageReport(_ reports: [SRPhoneUsageReport])
func didFetchAmbientLightSensorData(_ data: [SRAmbientLightSample])
func didFailFetchingData(error: Error)
}
class SensorManager: NSObject, SRSensorReaderDelegate {
private let phoneUsageReader: SRSensorReader
private let ambientLightReader: SRSensorReader
weak var delegate: SensorManagerDelegate?
override init() {
self.phoneUsageReader = SRSensorReader(sensor: .phoneUsageReport)
self.ambientLightReader = SRSensorReader(sensor: .ambientLightSensor)
super.init()
self.phoneUsageReader.delegate = self
self.ambientLightReader.delegate = self
}
func requestAuthorization() {
let sensors: Set<SRSensor> = [.phoneUsageReport, .ambientLightSensor]
guard phoneUsageReader.authorizationStatus != .authorized || ambientLightReader.authorizationStatus != .authorized else {
log("Already authorized. Fetching data directly...")
fetchSensorData()
return
}
SRSensorReader.requestAuthorization(sensors: sensors) { [weak self] error in
DispatchQueue.main.async {
if let error = error {
self?.log("Authorization failed: \(error.localizedDescription)", isError: true)
self?.delegate?.didFailFetchingData(error: error)
} else {
self?.log("Authorization granted.")
self?.fetchSensorData()
}
}
}
}
func fetchSensorData() {
guard let fromDate = Calendar.current.date(byAdding: .day, value: -1, to: Date()) else {
log("Failed to calculate 'from' date.", isError: true)
return
}
let fromTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: fromDate.timeIntervalSinceReferenceDate)
let toTime = SRAbsoluteTime.fromCFAbsoluteTime(_cf: Date().timeIntervalSinceReferenceDate)
let phoneUsageRequest = SRFetchRequest()
phoneUsageRequest.from = fromTime
phoneUsageRequest.to = toTime
phoneUsageRequest.device = SRDevice.current
let ambientLightRequest = SRFetchRequest()
ambientLightRequest.from = fromTime
ambientLightRequest.to = toTime
ambientLightRequest.device = SRDevice.current
phoneUsageReader.fetch(phoneUsageRequest)
ambientLightReader.fetch(ambientLightRequest)
}
// ✅ Delegate Methods
func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest) {
Task.detached {
if reader.sensor == .phoneUsageReport {
if let samples = reader.fetch(fetchRequest) as? [SRPhoneUsageReport] {
DispatchQueue.main.async { [weak self] in
self?.delegate?.didFetchPhoneUsageReport(samples)
}
}
} else if reader.sensor == .ambientLightSensor {
if let samples = reader.fetch(fetchRequest) as? [SRAmbientLightSample] {
DispatchQueue.main.async { [weak self] in
self?.delegate?.didFetchAmbientLightSensorData(samples)
}
}
}
}
}
func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool {
return true
}
func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, failedWithError error: any Error) {
DispatchQueue.main.async { [weak self] in
self?.delegate?.didFailFetchingData(error: error)
}
}
// MARK: - Logging Helper
private func log(_ message: String, isError: Bool = false) {
if isError {
print("❌ [SensorManager] \(message)")
} else {
print("✅ [SensorManager] \(message)")
}
}
}
And ViewController
import UIKit
import SensorKit
class ViewController: UIViewController {
private var sensorManager: SensorManager!
override func viewDidLoad() {
super.viewDidLoad()
setupSensorManager()
}
private func setupSensorManager() {
sensorManager = SensorManager()
sensorManager.delegate = self
sensorManager.requestAuthorization()
}
}
// MARK: - SensorManagerDelegate
extension ViewController: SensorManagerDelegate {
func didFetchPhoneUsageReport(_ reports: [SRPhoneUsageReport]) {
for report in reports {
print("Total Calls: (report.totalOutgoingCalls + report.totalIncomingCalls)")
print("Outgoing Calls: (report.totalOutgoingCalls)")
print("Incoming Calls: (report.totalIncomingCalls)")
print("Total Call Duration: (report.totalPhoneCallDuration) seconds")
}
}
func didFetchAmbientLightSensorData(_ data: [SRAmbientLightSample]) {
for sample in data {
print(sample)
}
}
func didFailFetchingData(error: Error) {
print("Failed to fetch data: \(error.localizedDescription)")
}
}
Could anyone please assist me in resolving this issue? Any guidance or troubleshooting steps would be greatly appreciated.
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I released an app for iPhone (and it's could be downloaded for iPad also), and now I developered another app for iPad version with the same code and logic but I modified the layout to fit bigger screen and make better user experience and appearance.
Howevert the app review rejected my release due to the duplicate content, how can I solve it?
Topic:
UI Frameworks
SubTopic:
General
I want to add the option to choose an alternative icon inside the app.
Is there a way to load an icon asset from within the app? I downloaded Apple’s alternative icon sample, which is supposed to show a list of icons to choose from, but even in the sample, it did not work.
So the current solution is to add every alternative icon along with another image asset of the same image to display to the user. This sounds like a waste of bytes.
Thank you in advance for any help.
Topic:
UI Frameworks
SubTopic:
General
Hi,
I have an existing Mac app on the App Store with a couple of widgets as part of the app. I want to now add a new widget to the WidgetBundle. When I build the updated app with Xcode, and then run the updated app, the widgets list doesn't seem to get updated in Notification Center or in the WidgetKit Simulator.
I do have the App Store version installed in the /Applications folder as well, so there might be some conflict. What's the trick to getting the widgets list to run the debug version?
I think it can be dismissed with dismiss() onInAppPurchaseCompletion action handler but I have no reason to handle it, and if it's not handled it will show error alerts for you (see documentation).
How can I dismiss it and still benefit from default onInAppPurchaseCompletion action?
Thanks,
I've been trying to add a header to the tabSection of the tabview in tvos 18+ .
init(
@TabContentBuilder<SelectionValue> content: () -> Content,
@ViewBuilder header: () -> Header
) where Header : View, Footer == EmptyView
Here the ehader clearly conforms to View but i cant quite fit the label with uiimage as the icon into this. This Label when i add it to any other view, the image is in the specified 50 x 50 size but inside header it functions weirdly to be of a huge size. but also to note, if i simply hav an icon here, it is correct. So what is the problem here.. can someone help me? im supposed to add the user profile and name in the header. I dont think there's any other way
Hello.
I use NavigationStack for navigating in app. I have 4 screens - A, B, C, D. In some moment I have path [A, B, C] for NavigationStack. After user did action I should show path [A, B, D]. In other hands I should replace screen C with screen D.
struct HomeView: View {
@ObservedObject var viewModel: HomeViewModel
var body: some View {
NavigationStack(path: $viewModel.path) {
ContentView()
.navigationDestination(for: HomeViewModel.Path.self) { destination in
// B, C, D views here...
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Solution looks like same as for UIKit. I replaced last item in stack. It works, but "push" animation broke.
var updatedPath = self.path
updatedPath.removeLast()
updatedPath.append(newPathItem)
self.path = updatedPath
I found suggest in Internet that you can remove view from stack after some delay. But it has some magic. For example 1 second delay works properly on iOS 18, but cause crash on iOS 16. 1 millisecond delay works on iOS 16, but sometimes didn't.
self.path.append(newPathItem)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
UIView.setAnimationsEnabled(false)
self.path.remove(at: self.path.count - 2)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
UIView.setAnimationsEnabled(true)
}
}
It is easy task to replace current top screen in UINavigationController of UIKit. How I can do it properly in SwiftUI and save animation?
I want to truncate text from head with max 2 lines.
I try the following code
import SwiftUI
struct ContentView: View {
@State var content: String = "Hello world! wef wefwwfe wfewe weweffwefwwfwe wfwe"
var body: some View {
VStack {
Text(content)
.lineLimit(nil)
.truncationMode(.head)
.frame(height: 50)
Button {
content += content
} label: {
Text("Double")
}
.buttonStyle(.borderedProminent)
}
.frame(width: 200, height: 1000)
.padding()
}
}
#Preview {
ContentView()
}
It show result like this, this is not what I want.
I am facing same issue with major crash while coming out from this function.
Basically using collectionView.dequeReusableCell with size calculation.
func getSizeOfFavouriteCell(_ collectionView: UICollectionView, at indexPath: IndexPath, item: FindCircleInfoCellItem) -> CGSize { guard let dummyCell = collectionView.dequeueReusableCell( withReuseIdentifier: TAButtonAddCollectionViewCell.reuseIdentifier, for: indexPath) as? TAButtonAddCollectionViewCell else { return CGSize.zero }
dummyCell.title = item.title
dummyCell.subtitle = item.subtitle
dummyCell.icon = item.icon
dummyCell.layoutIfNeeded()
var targetSize = CGSize.zero
if viewModel.favoritesDataSource.isEmpty.not,
viewModel.favoritesDataSource.count > FindSheetViewControllerConstants.minimumFavoritesToDisplayInSection {
targetSize = CGSize(width: collectionView.frame.size.width / 2, height: collectionView.frame.height)
var estimatedSize: CGSize = dummyCell.systemLayoutSizeFitting(targetSize)
if estimatedSize.width > targetSize.width {
estimatedSize.width = targetSize.width
}
return CGSize(width: estimatedSize.width, height: targetSize.height)
}
}
We have resolve issue with size calculation with checking nil. Working fine in xcode 15 and 16+.
Note: Please help me with reason of crash? Is it because of xCode 16.2 onwards **strict check on UICollectionView **
I'm implementing a Map with user location customization in SwiftUI using iOS 17+ MapKit APIs. When using the selection parameter with Map, the default blue dot user location becomes tappable but shows an empty annotation view. However, using UserAnnotation makes the location marker non-interactive.
My code structure:
import SwiftUI
import MapKit
struct UserAnnotationSample: View {
@State private var position: MapCameraPosition = .userLocation(fallback: .automatic)
@State private var selectedItem: MapSelection<MKMapItem>?
var body: some View {
Map(position: $position, selection: $selectedItem) {
// UserAnnotation()
}
.mapControls {
MapUserLocationButton()
}
}
}
Key questions:
How can I replace the empty annotation view with a custom avatar when tapping the user location?
Is there a way to make UserAnnotation interactive with selection?
Should I use tag modifier for custom annotations? What's the proper way to associate selections?
I have a controller that displays a pdf using UIDocumentInteractionController as the presented view.
When users open it up, it shows fine.
User gets the app backgrounded and session timed out.
After timed out, when the app is brought to foreground, I bring our loginVC by removing the old VC used to show the UIDocumentInteractionController.
All the crashes are happening at this point.
I am not able to reproduce it, but our alert systems show we have crashes happening.
The code that shows the pdf is straight forward
documentViewController = UIDocumentInteractionController()
documentViewController?.delegate = self
documentViewController?.url = url
documentViewController?.presentPreview(animated: true)
and we reset it to nil in delegate documentInteractionControllerDidEndPreview
Based on the crash trace, it seems like the crash happens when our login VC replaces it and only when pdf was displayed. The reason of stressing ONLY because when we have other viewcontroller present and they are removed in a similar way, we do not see any issue.
So we always replace first and then add a new one
childViewController.willMove(toParent: nil)
childViewController.viewIfLoaded?.removeFromSuperview()
childViewController.removeFromParent()
addChild(childViewController)
view.addSubview(childViewController.view)
childViewController.view.frame = view.bounds
childViewController.didMove(toParent: self)
Raised a ticket with Apple, but I haven't heard back, and it's been a month. Posting here in case anyone experiences the same and has any solutions. I saw some related posts, and solution was to remove the pdf the moment the app goes to the background, but I am trying to find some alternate solution if possible.
Topic:
UI Frameworks
SubTopic:
UIKit
Hey Everyone,
I can't see to ActiveLabel as it says there is no active module. Please help me.
Thanks,
Ben
import UIKit
import ActiveLabel
protocol TweetCellDelegate: AnyObject {
func handleProfileImageTapped(_ cell: TweetCell)
func handleReplyTapped(_ cell: TweetCell)
func handleLikeTapped(_ cell: TweetCell)
}
class TweetCell: UICollectionViewCell {
Hello, the LocalizedStringKey does not work in the live activity. What do you suggest me to use in order to get localization in the live activity?
Why is the pitch slider always visible in the SwiftUI tvOS map view? It doesn't even appear to be supported there, let alone the fact that I specify mapControlVisibility(.hidden). Am I missing something or is Apple? See attached screenshot. This really messes up my UI.
Here is my code:
import SwiftUI
import MapKit
struct ContentView: View {
@State var position = MapCameraPosition.region(MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)))
var body: some View {
Map(position: $position)
.mapControlVisibility(.hidden)
.mapStyle(.standard(pointsOfInterest: .including(.airport)))
}
}
Has anyone gotten custom buttons to work on top of tvOS Map()? I've tried many variations of
FocusState
focusSection
.defaultFocus()
and as soon as the map appears at startup the buttons never get focus again. They are on a ZStack over the map. I could post code but truthfully nothing works for me. I'm wondering if anyone has successfully put focusable buttons on top of the map view.
Our MacOS app has for some time been able to create so-called "add-on" services, which are dynamically written to individual bundles in ~/Library/Services/ (as opposed to being statically defined in the app's Info.plist). These worked fine for a long time until recently. They still appear in other app Services menus, but do not get as far as calling the specified instance method in our app. Does anyone know if add-on services are no longer supported? Perhaps due to some new security constraint? The documentation on app services in general seems to be out of date.
I did try copying the add-on service definition from the add-on plist into the app's Info.plist. That seemed to work, so the basic specification doesn't seem to have changed.
Topic:
UI Frameworks
SubTopic:
AppKit
I have the MainView as the active view if the user is logged in(authenticated). the memory allocations when we run profile is pretty good. We have graphql fetching, we have token handling eg: This is All heap:
1 All Heap & Anonymous VM 13,90 MiB 65408 308557 99,10 MiB 373965 Ratio: %0.14, %0.86
After what i have checked this is pretty good for initialise and using multiple repositories eg. But when we change tabs:
1 All Heap & Anonymous VM 24,60 MiB 124651 543832 156,17 MiB 668483 Ratio: %0.07, %0.40
And that is not pretty good. So i guess we need to "kill" it or something. How? I have tried some techniques in a forum this was a recommended way:
public struct LazyView<Content: View>: View {
private let build: () -> Content
@State private var isVisible = false
public init(_ build: @escaping () -> Content) {
self.build = build
}
public var body: some View {
build()
Group {
if isVisible {
build()
} else {
Color.clear
}
}
.onAppear { isVisible = true }
.onDisappear { isVisible = false }
}
}
But this did not help at all. So under here is the one i use now. So pleace guide me for making this work.
import DIKit
import CoreKit
import PresentationKit
import DomainKit
public struct MainView: View {
@Injected((any MainViewModelProtocol).self) private var viewModel
private var selectedTabBinding: Binding<MainTab> {
Binding(
get: { viewModel.selectedTab },
set: { viewModel.selectTab($0) }
)
}
public init() {
// No additional setup needed
}
public var body: some View {
NavigationStack(path: Binding(
get: { viewModel.navigationPath },
set: { _ in }
)) {
TabView(selection: selectedTabBinding) {
LazyView {
FeedTabView()
}
.tabItem {
Label("Feed", systemImage: "house")
}
.tag(MainTab.feed)
LazyView {
ChatTabView()
}
.tabItem {
Label("Chat", systemImage: "message")
}
.tag(MainTab.chat)
LazyView {
JobsTabView()
}
.tabItem {
Label("Jobs", systemImage: "briefcase")
}
.tag(MainTab.jobs)
LazyView {
ProfileTabView()
}
.tabItem {
Label("Profile", systemImage: "person")
}
.tag(MainTab.profile)
}
.accentColor(.primary)
.navigationDestination(for: MainNavigationDestination.self) { destination in
switch destination {
case .profile(let userId):
Text("Profile for \(userId)")
case .settings:
Text("Settings")
case .jobDetails(let id):
Text("Job details for \(id)")
case .chatThread(let id):
Text("Chat thread \(id)")
}
}
}
}
}
import SwiftUI
public struct LazyView<Content: View>: View {
private let build: () -> Content
public init(_ build: @escaping () -> Content) {
self.build = build
}
public var body: some View {
build()
}
}
Xcode 16 iOS18 WKWebView里包含http图片时无法显示
Topic:
UI Frameworks
SubTopic:
UIKit
WKWebView cannot load and display HTTP image resources
Topic:
UI Frameworks
SubTopic:
UIKit
I have to decrease main window screen size when user open Immersive space in my project.
Using frame i try it but it not updated main window size it just update view frame.