在webview全屏打开Video视频前后获取设备的宽高结果不同 [UIScreen mainScreen].bounds对应的设备逻辑分辨率发生变化,导致根据分辨率显示的页面显示错误
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
Hi everyone,
I’m wondering about Core Data. When creating a private context using newBackgroundContext(), does it automatically set the parent to the view context, or is it independent?
Additionally, if I update objects in the context created by newBackgroundContext(), will the view context automatically notice the changes, and vice versa?
Lastly, are there other ways to set parent-child context relationships between contexts?
I'd appreciate it if anyone could clarify this for me.
Thanks in advance! 😊
I'm still discovering swift and the various frameworks. So I'm now trying to create scrolling composition with a grid - containing images - and an NSStackView at on top.
However, I'm running into a problem that might seem stupid, but when I try to wrap my NSCollectionView in another NSView and pointing the scrollView.documentView to, I can't scroll anymore... Even though it works fine when I set the scrollView.documentView to the NSCollectionView directly.
Working case:
override func viewDidLoad() {
super.viewDidLoad()
scrollView = NSScrollView(frame: .zero)
scrollView.hasVerticalScroller = true
scrollView.hasHorizontalScroller = false
scrollView.scrollerStyle = .overlay
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
vStack = NSStackView(frame: .zero)
vStack.orientation = .vertical
vStack.spacing = 12 * 2
vStack.translatesAutoresizingMaskIntoConstraints = false
let hStack = NSStackView()
hStack.orientation = .horizontal
hStack.spacing = 12
hStack.translatesAutoresizingMaskIntoConstraints = false
let label1 = NSTextField(labelWithString: "Collection")
hStack.addArrangedSubview(label1)
let layout = PinterestLayout()
layout.delegate = self
collectionView = NSCollectionView(frame: .zero)
collectionView.collectionViewLayout = layout
collectionView.dataSource = self
collectionView.delegate = self
collectionView
.register(
ArtCardCell.self,
forItemWithIdentifier: NSUserInterfaceItemIdentifier("ArtCardCell")
)
collectionView.backgroundColors = [.BG]
collectionView.translatesAutoresizingMaskIntoConstraints = false
// vStack.addArrangedSubview(hStack)
// vStack.addArrangedSubview(collectionView)
scrollView.documentView = collectionView
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
// vStack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
// vStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
// vStack.topAnchor.constraint(equalTo: scrollView.topAnchor),
// vStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
// vStack.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
collectionView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
// vStack.arrangedSubviews[0].leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 12),
// vStack.arrangedSubviews[0].trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -12),
// vStack.arrangedSubviews[0].topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 80)
])
collectionView.postsBoundsChangedNotifications = true
NotificationCenter.default.addObserver(self, selector: #selector(didScroll(_:)),
name: NSView.boundsDidChangeNotification,
object: collectionView.enclosingScrollView?.contentView
)
}
collectionView height: 3549.0
ScrollView height: 628.0
StackView height: --
Dysfunctional case:
override func viewDidLoad() {
super.viewDidLoad()
scrollView = NSScrollView(frame: .zero)
scrollView.hasVerticalScroller = true
scrollView.hasHorizontalScroller = false
scrollView.scrollerStyle = .overlay
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
vStack = NSStackView(frame: .zero)
vStack.orientation = .vertical
vStack.spacing = 12 * 2
vStack.translatesAutoresizingMaskIntoConstraints = false
let hStack = NSStackView()
hStack.orientation = .horizontal
hStack.spacing = 12
hStack.translatesAutoresizingMaskIntoConstraints = false
let label1 = NSTextField(labelWithString: "Collection")
hStack.addArrangedSubview(label1)
let layout = PinterestLayout()
layout.delegate = self
collectionView = NSCollectionView(frame: .zero)
collectionView.collectionViewLayout = layout
collectionView.dataSource = self
collectionView.delegate = self
collectionView
.register(
ArtCardCell.self,
forItemWithIdentifier: NSUserInterfaceItemIdentifier("ArtCardCell")
)
collectionView.backgroundColors = [.BG]
collectionView.translatesAutoresizingMaskIntoConstraints = false
vStack.addArrangedSubview(hStack)
vStack.addArrangedSubview(collectionView)
scrollView.documentView = vStack
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
vStack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
vStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
vStack.topAnchor.constraint(equalTo: scrollView.topAnchor),
vStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
vStack.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
collectionView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
vStack.arrangedSubviews[0].leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 12),
vStack.arrangedSubviews[0].trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -12),
vStack.arrangedSubviews[0].topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 80)
])
}
collectionView height: 508.0
ScrollView height: 628.0
StackView height: 628.0
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:]. Dequeued view: <Pezzano_Enterprises.BannerImageCollectionViewCell: 0x103af8370; baseClass = UICollectionViewCell; frame = (880 0; 440 130); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x6000003980a0>>; Collection view: <UICollectionView: 0x106030c00; frame = (0 0; 440 130); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600000de0240>; backgroundColor = <UIDynamicSystemColor: 0x6000017b0500; name = systemBackgroundColor>; layer = <CALayer: 0x600000337fe0>; contentOffset: {205.66666666666666, 0}; contentSize: {1320, 130}; adjustedContentInset: {0, 0, 0, 0}; layout: <UICollectionViewFlowLayout: 0x103b35720>; dataSource: <Pezzano_Enterprises.BannerTableViewCell: 0x10605d000; baseClass = UITableViewCell; frame = (0 0; 440 130); autoresize = W; layer = <CALayer: 0x600000336900>>>'
Topic:
UI Frameworks
SubTopic:
UIKit
I'm working on integrating the new format panel shown in the WWDC24 session "What's New in UIKit" under the Text Improvements section. So far, I've implemented long-press functionality on a text passage, allowing the editing options to appear. From there, you can go to Format > More..., which successfully opens the new format panel.
However, I would also like to add a button to programmatically display this format panel—similar to how the Apple Notes app has a button in the keyboard toolbar to open it.
Does anyone know how to achieve this?
Here's my current code for the text editor (I've enabled text formatting by setting allowsEditingTextAttributes to true):
struct TextEditorView: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let textEditorView = UITextView()
textEditorView.delegate = context.coordinator
textEditorView.allowsEditingTextAttributes = true
return textEditorView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextEditorView
init(_ uiTextView: TextEditorView) {
self.parent = uiTextView
}
func textViewDidChange(_ textView: UITextView) {
self.parent.text = textView.text
}
}
}
Thanks in advance for any guidance!
I would like to implement the same kind of behavior as the Dropoverapp application, specifically being able to perform a specific action when files are dragged (such as opening a window, for example).
I have written the code below to capture the mouse coordinates, drag, drop, and click globally. However, I don't know how to determine the nature of what is being dropped. Do you have any ideas on how to detect the nature of what is being dragged outside the application's scope?
Here is my current code:
import SwiftUI
import CoreGraphics
struct ContentView: View {
@State private var mouseX: CGFloat = 0.0
@State private var mouseY: CGFloat = 0.0
@State private var isClicked: Bool = false
@State private var isDragging: Bool = false
private var mouseTracker = MouseTracker.shared
var body: some View {
VStack {
Text("Mouse coordinates: \(mouseX, specifier: "%.2f"), \(mouseY, specifier: "%.2f")")
.padding()
Text(isClicked ? "Mouse is clicked" : "Mouse is not clicked")
.padding()
Text(isDragging ? "Mouse is dragging" : "Mouse is not dragging")
.padding()
}
.frame(width: 400, height: 200)
.onAppear {
mouseTracker.startTracking { newMouseX, newMouseY, newIsClicked, newIsDragging in
self.mouseX = newMouseX
self.mouseY = newMouseY
self.isClicked = newIsClicked
self.isDragging = newIsDragging
}
}
}
}
class MouseTracker {
static let shared = MouseTracker()
private var eventTap: CFMachPort?
private var runLoopSource: CFRunLoopSource?
private var isClicked: Bool = false
private var isDragging: Bool = false
private var callback: ((CGFloat, CGFloat, Bool, Bool) -> Void)?
func startTracking(callback: @escaping (CGFloat, CGFloat, Bool, Bool) -> Void) {
self.callback = callback
let mask: CGEventMask = (1 << CGEventType.mouseMoved.rawValue) |
(1 << CGEventType.leftMouseDown.rawValue) |
(1 << CGEventType.leftMouseUp.rawValue) |
(1 << CGEventType.leftMouseDragged.rawValue)
// Pass 'self' via 'userInfo'
let selfPointer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
guard let eventTap = CGEvent.tapCreate(
tap: .cghidEventTap,
place: .headInsertEventTap,
options: .defaultTap,
eventsOfInterest: mask,
callback: MouseTracker.mouseEventCallback,
userInfo: selfPointer
) else {
print("Failed to create event tap")
return
}
self.eventTap = eventTap
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
CGEvent.tapEnable(tap: eventTap, enable: true)
}
// Static callback function
private static let mouseEventCallback: CGEventTapCallBack = { _, eventType, event, userInfo in
guard let userInfo = userInfo else {
return Unmanaged.passUnretained(event)
}
// Retrieve the instance of MouseTracker from userInfo
let tracker = Unmanaged<MouseTracker>.fromOpaque(userInfo).takeUnretainedValue()
let location = NSEvent.mouseLocation
// Update the click and drag state
switch eventType {
case .leftMouseDown:
tracker.isClicked = true
tracker.isDragging = false
case .leftMouseUp:
tracker.isClicked = false
tracker.isDragging = false
case .leftMouseDragged:
tracker.isDragging = true
default:
break
}
// Call the callback on the main thread
DispatchQueue.main.async {
tracker.callback?(location.x, location.y, tracker.isClicked, tracker.isDragging)
}
return Unmanaged.passUnretained(event)
}
}
As of macOS Sequoia 15.1 (and probably earlier), in System Settings under Accessibility -> Display, there's a Text Size option that looks an awful lot like Dynamic Type on iOS:
I have an iOS app with robust support for Dynamic Type that I've brought to the Mac via Catalyst. Is there any way for me to opt this app into supporting this setting, maybe with some Info.plist key?
Calendar's Info.plist has a CTIgnoreUserFonts value set to true, but the Info.plist for Notes has no such value.
How can I test biometric on UI Tests in Swift / iOS 18? This code not working.
+ (void)successfulAuthentication {
notify_post("com.apple.BiometricKit_Sim.fingerTouch.match");
notify_post("com.apple.BiometricKit_Sim.pearl.match");
}
+ (void)unsuccessfulAuthentication {
notify_post("com.apple.BiometricKit_Sim.fingerTouch.nomatch");
notify_post("com.apple.BiometricKit_Sim.pearl.nomatch");
}
Hi,
Have been trying to work with MapkitJS for a website, but I'm stumped on once basic capability: I want to be able to click on a point of interest, and perform some actions such as:
Get its coordinates
Attach an annotation to it (e.g. a callout)
In my code, PointOfInterest's are selectable:
map.selectableMapFeatures = [
mapkit.MapFeatureType.PointOfInterest,
];
But when I click on one, I do see the marker pop up but nothing else (which is not much help since there is no additional information in the marker itself). I see no event getting triggered that I can do something with.
I am using an event listener as follows:
map.addEventListener('single-tap', (event) => {
const coordinate = map.convertPointOnPageToCoordinate(event.pointOnPage);
console.log('Map tapped at:', coordinate);
console.log('Map tapped event:', event);
...
I guess I have to grab the Place ID somehow but I don't know how to.
Thanks for any help.
Hi,
We are going to create a tvOS App with portrait display(HDMI screen will rotate 90 degree).
It seems there is no rotate setting in tvOS18, neither Xcode provide relative support.
As our investigation, we might need to rotate each UIKit component 90 degree by code to archive it.
Is there any better suggestion?
Thanks.
I am trying to convert a string field to an integer field in our database schema. However, the custom migration that I write doesn't seem to run.
My Model
//Run 1
//typealias Book = BookSchemaV1.Book
//Run 2
typealias Book = BookSchemaV2.Book
// MARK: - Migration Plan
enum BookModelMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] = [
BookSchemaV1.self,
BookSchemaV2.self
]
static var stages: [MigrationStage] = [migrateV1toV2]
static var oldBooks: [BookSchemaV1.Book] = []
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: BookSchemaV1.self,
toVersion: BookSchemaV2.self,
willMigrate: nil,
didMigrate: { context in
oldBooks = try context.fetch(FetchDescriptor<BookSchemaV1.Book>())
oldBooks.forEach { oldBook in
do {
let newBook = BookSchemaV2.Book(
bookID: String(oldBook.bookID),
title: oldBook.title
)
context.insert(newBook)
context.delete(oldBook)
try context.save()
} catch {
print("New model not saved")
}
}
}
)
}
// MARK: - Schema Versions
enum BookSchemaV1: VersionedSchema {
static var models: [any PersistentModel.Type] = [Book.self]
static var versionIdentifier = Schema.Version(1, 0, 0)
@Model
final class Book {
@Attribute(.unique) var bookID: Int
var title: String
init(
bookID: Int,
title: String
) {
self.bookID = bookID
self.title = title
}
}
}
enum BookSchemaV2: VersionedSchema {
static var models: [any PersistentModel.Type] = [Book.self]
static var versionIdentifier = Schema.Version(2, 0, 0)
@Model
class Book {
@Attribute(.unique) var bookID: String
var title: String
init(
bookID: String,
title: String
) {
self.bookID = bookID
self.title = title
}
}
}
@MainActor
class AppDataContainer {
static let shared = AppDataContainer()
let container: ModelContainer
private init() {
do {
let schema = Schema([Book.self])
let config = ModelConfiguration(schema: schema)
container = try ModelContainer(for: schema, migrationPlan: BookModelMigrationPlan.self, configurations: [config])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}
}
In iOS, when using a UICollectionView with horizontal scrolling and only one row of cells: if all the cells have the same width, the spacing between cells is determined by minimumLineSpacing. If the cell widths are different, the spacing between cells is controlled by minimumInteritemSpacing. However, when the cell widths are different and the collectionView's height is smaller than the height of the cells, the minimumInteritemSpacing is applied to the left side of the first cell, causing the left margin of the first cell to become wider. Why does this happen?
Topic:
UI Frameworks
SubTopic:
UIKit
I want to add a "bubble horizon" to a camera application to show if the user is keeping their phone level.
For this, I'm using the Motion Attitude functionality of CMMotionManager.
However, the output I'm getting is very inaccurate. I'm comparing it with Apple's own Measure app which is dead accurate, so the sensors are working fine. My own readings seem to be several degrees off.
Am I missing some calibration step or something?
- (void)processDeviceMotion:(CMDeviceMotion *)motion {
// use quaternions to avoid Gimbal Lock
CMQuaternion quat = motion.attitude.quaternion;
// calculate roll in degrees
double roll = atan2( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) );
roll = radiansToDegrees( roll );
NSLog( @"Roll: %f", roll );
}
Topic:
UI Frameworks
SubTopic:
General
Does anyone know any workaround for this? FB15522331
My code as long as you use the AVPictureInPictureController, open the PIP model, and then back to the desktop, my widget will refresh is invalid, I closed the PIP code mode, functions are normal refresh.
I don't know what the reason is, is the system made a refresh limit?
Using this adapted code snippet from the Apple Developer Documentation,
struct ContentView: View {
@State var nameComponents = PersonNameComponents()
var body: some View {
Form {
TextField(
"Proper name",
value: $nameComponents,
format: .name(style: .medium)
)
.onSubmit {
}
.disableAutocorrection(true)
.border(.secondary)
Text(nameComponents.debugDescription)
}
}
}
It runs and works as expected on my iOS device. When I use this same code in my macOS app, it has unexpected results. The validation mechanism (likely caused by format: .name(style: .medium) in order to bind the TextField to a PersonNameComponents instance, will not let me add spaces or delete all the text in the TextField. I have to write the first name in this format: "FirstLast" and then add a space in between the t and L. Are there any ways I can fix this on macOS while still binding my TextField to a PersonNameComponents instance?
The app added control widgets and crashed online。
SwiftU!
static ControlWidgetConfigurationAdaptor._makeWidgetConfiguration(widget inputs:)
The Maps app on macOS always zooms the same way (two fingers up to zoom in, two fingers down to zoom out) when the shift key is held down, regardless of whether natural scrolling is turned off. I'd like to replicate this same behavior using UIPanGestureRecognizer, but the translation is always inverted whenever I disable natural scrolling. How can I detect if natural scrolling is enabled or disabled when the pan gesture is detected?
let activityViewController = UIActivityViewController(activityItems: items,
applicationActivities: [])
activityViewController.popoverPresentationController?.barButtonItem = navigationController.topViewController?.navigationItem.rightBarButtonItem
navigationController.present(activityViewController, animated: true, completion: nil)
Crash logs
=====================================================
*** Assertion failure in -[_UIActivityContentCollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], UICollectionView.m:7588
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to dequeue a cell for a different registration or reuse identifier than the existing cell when reconfiguring an item, which is not allowed. You must dequeue a cell using the same registration or reuse identifier that was used to dequeue the cell originally to obtain the existing cell. Dequeued reuse identifier: UIActivityContentActionCellIdentifier; Original reuse identifier: UIActivityActionGroupCell; Existing cell: <UIActivityActionGroupCell: 0x10f19f220; baseClass = _UICollectionViewListCell; frame = (16 354; 358 30); clipsToBounds = YES; layer = <CALayer: 0x600000781740>>'
Hi all,
I am developing an app that scans barcodes using VisionKit, but I am facing some difficulties.
The accuracy level is not at where I hope it to be at. Changing the “qualityLevel” parameter from balanced to accurate made the barcode reading slightly better, but it is still misreading some cases. I previously implemented the same barcode scanning app with AVFoundation, and that had much better accuracy. I tested it out, and barcodes that were read correctly with AVFoundation were read incorrectly with VisionKit . Is there anyway to improve the accuracy of the barcode reading in VisionKit? Or is this something that is built in and the developer cannot change? Either way, any ideas on how to improve reading accuracy would help.
Thanks in advance!