Introduction
I created a simple app to test enabling Sign In with Google using Observable Objects in a SwiftUI Application. However, the app only functions properly (displaying the signed in user's name and email) with a UIKit App Delegate Life Cycle. The code of the App file for the SwiftUI life cycle and that of the app delegate and scene delegate files of the UIKit App Delegate life cycle should function identical; however, they do not.
Project Code
SwiftUI Lift Cycle
AppDelegate
import UIKit
import SwiftUI
import GoogleSignIn
class AppDelegate: NSObject, UIApplicationDelegate {
/* GoogleDelegate() is the observable object */
let googleDelegate = GoogleDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
GIDSignIn.sharedInstance()?.clientID = "CLIENT_ID"
GIDSignIn.sharedInstance()?.delegate = googleDelegate
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
}
App
@main
struct WidgiTubeApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var window: UIWindow? {
guard let scene = UIApplication.shared.connectedScenes.first,
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
let window = windowSceneDelegate.window else {
return nil
}
return window
}
@Environment(\.scenePhase) private var scenePhase
let googleDelegate = (UIApplication.shared.delegate as! AppDelegate).googleDelegate
var body: some Scene {
WindowGroup {
GoogleSignInView()
.environmentObject(googleDelegate)
}.onChange(of: scenePhase) { (phase) in
switch phase {
case .active:
GIDSignIn.sharedInstance().presentingViewController = window?.rootViewController
window?.makeKeyAndVisible()
case .inactive:
case .background:
default:
}
}
}
}
Using the SwiftUI Life Cycle the User Is signed in; however, the information does not update in the SwiftUI view. (The view is identical between the SwiftUI Life Cycle and UIKit Application Delegate Life Cycle.)
UIKit Application Delegate Life Cycle
App Delegate
DidFinishLaunchingWithOptions
GIDSignIn.sharedInstance().clientID = "CLIENT_ID"
GIDSignIn.sharedInstance().delegate = googleDelegate
return true
OpenURL
return GIDSignIn.sharedInstance().handle(url)
Scene Delegate
SceneWillConnectTo
let googleDelegate = (UIApplication.shared.delegate as! AppDelegate).googleDelegate
let contentView = ContentView().environmentObject(googleDelegate)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
GIDSignIn.sharedInstance()?.presentingViewController = window.rootViewController
self.window = window
window.makeKeyAndVisible()
}
Conclusion
Due to this, I have identified that there must be some issue that occurs when adapting the UIKit App Delegate code to the SwiftUI App Code. However, I cannot identify what the issue between the two life cycles is. It is my understanding that anything possible with the UIKit Delegate life cycle should theoretically be possible with SwiftUI. In the mean time, of course, there is no issue continuing with the UIKit Delegate; however, I was hoping to create a SwiftUI app. If anyone could help me identify where the issue lays between these two different life cycles, I would greatly appreciate it. Thanks!
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I have a SwiftUI macOS hierarchical table with 'children' initializer argument. Everything is working fine but I'd like to have expander arrows in different column. TableColumn definition order doesn't seem to have any effect nor has the order of properties in the model. Is there a way how to define which column should contain expander arrows?
I have a an exercise of taking a shuffled display of words and dragging and dropping them into the correct sequence to form a sentence.
I'm currently using .onDrag and .onDrop with a dropDelegate to perform these actions. However, in order the drag operation to start happening, the user needs to click the item for 1-2 seconds and then the drag can be performed. I would like to remove the need to long press the item before the drag or at least decrease the delay between clicking and dragging.
Has anyone found a work around for solution for this problem? I found one post where the person said the removed the magnification feature to help streamline the drag. I assume they are referring to the item you click being magnified and previewed during the drag operation of .onDrag. I cannot seem to find out how to remove that feature though or if it is even possible.
Here is a small snippet of my item with the .onDrag
func DragArea()->some View {
VStack(spacing: 40){
ForEach(shuffledRows, id: \.self){row in
HStack(spacing:45){
ForEach(row){item in
Text(item.value)
.font(.system(size: 28))
.padding(.vertical, 7)
.padding(.horizontal, item.padding)
.background{
RoundedRectangle(cornerRadius: 6, style: .continuous)
.stroke(.black, lineWidth: 3)
}
.onDrag{
return .init(contentsOf: URL(string: item.id))!
}
.opacity(item.isShowing ? 0 : 1)
.background{
RoundedRectangle(cornerRadius: 6, style: .continuous)
.fill(item.isShowing ? .gray.opacity(0.25) : .clear)
}
}
}//.frame(width: UIScreen.main.bounds.size.width - 200)
}
}
}
Greetings,
Context
Let's imagine 2 possible root Views: House and Castle.
They can both present a Room view and this room view can show a Bed view.
Let's also assume, for the sake of the example, that I want to pass the "$sheet" (Identifiable enum) from either House or Castle - which are 2 different enums - all the way to Bed, so that Bed can dismiss back to rootView. So I use a Binding.
Visually, the UI flow is
House --> \
Room --> Bed
Castle --> /
In RoomView and BedView, I expected to receive either a HouseSheet or a CastleSheet. So by receiving one at init, I set to a constant nil the other. For example, if I open a RoomView (or BedView) from a HouseView, the code would be
init(parentHouseSheet: Binding<HouseSheet?>) {
self._parentHouseSheet = parentHouseSheet
self._parentCastleSheet = .constant(nil)
self.from = .house
}
init(parentCastleSheet: Binding<CastleSheet?>) {
self._parentHouseSheet = .constant(nil)
self._parentCastleSheet = parentCastleSheet
self.from = .castle
}
Problem
My problem now is that the .constant(nil) appears to change and triggers a refresh!
By using a simple Self._printChanges() I get the following when I navigate to a BedView (from a House origin!).
RoomView: _parentCastleSheet changed. // Why? It's a binded constant and I'm not even touching RoomView at all.
BedView: @self, @identity, _parentCastleSheet changed.
BedView: @self, _parentCastleSheet changed. // Same why?
Full code
// House & Castle
enum BuildingOrigin: String {
case house
case castle
}
enum HouseSheet: String, Hashable, Identifiable {
case room
var id: String { return self.rawValue }
}
enum CastleSheet: String, Hashable, Identifiable {
case room
var id: String { return self.rawValue }
}
// I only show HouseView for this example.
struct HouseView: View {
@State private var sheet: HouseSheet?
var body: some View {
let _ = Self._printChanges()
VStack {
Button("Open Room (Sheet)") {
self.sheet = .room
}
}
.padding()
.sheet(item: $sheet) { sheet in
switch sheet {
case .room: RoomView(houseSheet: $sheet)
}
}
}
}
// Room
enum RoomViewDestination: String, Hashable {
case bed
}
struct RoomView: View {
@State private var path = NavigationPath()
@Binding var parentHouseSheet: HouseSheet?
@Binding var parentCastleSheet: CastleSheet?
let from: BuildingOrigin
init(houseSheet: Binding<HouseSheet?>) {
self._parentHouseSheet = houseSheet
self._parentCastleSheet = .constant(nil)
self.from = .house
}
init(castleSheet: Binding<CastleSheet?>) {
self._parentHouseSheet = .constant(nil)
self._parentCastleSheet = castleSheet
self.from = .castle
}
var body: some View {
let _ = Self._printChanges()
NavigationStack(path: $path) {
List {
NavigationLink(value: RoomViewDestination.bed) {
Text("Open Bed (Navigation)")
}
}
.navigationDestination(for: RoomViewDestination.self) { destination in
switch destination {
case .bed:
switch self.from {
case .house: BedView(parentHouseSheet: $parentHouseSheet)
case .castle: BedView(parentCastleSheet: $parentCastleSheet)
}
}
}
}
}
}
// Bed
struct BedView: View {
@Binding var parentHouseSheet: HouseSheet?
@Binding var parentCastleSheet: CastleSheet?
let from: BuildingOrigin
init(parentHouseSheet: Binding<HouseSheet?>) {
self._parentHouseSheet = parentHouseSheet
self._parentCastleSheet = .constant(nil)
self.from = .house
}
init(parentCastleSheet: Binding<CastleSheet?>) {
self._parentHouseSheet = .constant(nil)
self._parentCastleSheet = parentCastleSheet
self.from = .castle
}
var body: some View {
let _ = Self._printChanges()
Text("The \(from.rawValue) has a nice bed.")
}
}
Good morning,
I'm trying to use MusicKit functionalities in order to get last played songs and put them into a local DB, to be played later. Following the guide on developer.apple.com, I created the required AppServices integration:
Below is a minimal working version of what I'm doing:
func requestMusicAuthorization() async {
let status = await MusicAuthorization.request()
switch status {
case .authorized:
isAuthorizedForMusicKit = true
error = nil
case .restricted:
error = NSError(domain: "Music access is restricted", code: -10)
case .notDetermined:
break
case .denied:
error = NSError(domain: "Music access is denied", code: -10)
@unknown default:
break
}
}
on the SwiftUI ContentView there's something like that:
.onAppear {
Task {
await requestMusicAuthorization()
if MusicManager.shared.isAuthorizedForMusicKit {
let response = try await fetchLastSongs()
do {
let request = MusicRecentlyPlayedRequest<Song>()
let response = try await request.response()
var songs: [Song] = response.items.map { $0 }
// do some CloudKit handling with songs...
print("Recent songs: \(songs)")
} catch {
NSLog(error.localizedDescription)
}
}
}
}
Everything seems to works fine, but my console log is full of garbage like that:
MSVEntitlementUtilities - Process MyMusicApp PID[33633] - Group: (null) - Entitlement: com.apple.accounts.appleaccount.fullaccess - Entitled: NO - Error: (null)
Attempted to register account monitor for types client is not authorized to access: {(
"com.apple.account.iTunesStore"
)}
is there something I'm missing on? Should I ignore that and go forward with my implementation? Any help is really appreciated.
Hi ,
I have following scenario where I feel performance issue.
Use-case:
I have multiple Overlays(MKOverlay) rendered on MapView, and overlay needs to refresh on point Drag(MKPinAnnotation). I have custom logic to handle drag behaviour of annotation, on annotation drag I do update the overlay. As point update, I create new overlay with updated coordinate and re-render it. iT slow down the performance after few overlay added.
Additional Notes: Performance was quite good on iOS16 but on iOS17, it lags the perforce on point drag. When I say it the performance, it point drag lags so it slow the overlay rendering.
I am using MKMapView inside SwiftUI.
I am sharing code-snippet where it re-render the overlay. Please help with issue in my code implementation.
func renderSegments(mapView: MKMapView, segmentPoint: FencePointAnnotation, renderNeeded: Bool = true) {
mapViewModel.updateFencePointOrder()
guard let activeLayer = mapViewModel.activeLayer else {
debugPrint("Invalid active layer.")
return
}
let segments = mapViewModel.activeFence.connectedSegmentsOf(vertex: segmentPoint)
// Remove existing overlay.
for overlay in mapView.overlays {
if let overlay = overlay as? FenceOverlay {
if overlay.layerId == activeLayer.layerId {
mapView.removeOverlay(overlay)
}
} else if let overlay = overlay as? FenceSegmentPolyline {
if overlay.layerId == activeLayer.layerId {
for segment in segments.values where segment.identifier == overlay.identifier {
mapView.removeOverlay(overlay)
}
}
}
}
// When vertex removed the no need to add segment
if renderNeeded {
if let segments = mapViewModel.updatedSegements(segment: segments.map({$0.key})) {
let updatedSegments = mapView.updatedSegmentsWithOffset(segments: segments, layer: activeLayer)
mapView.addOverlays(updatedSegments)
}
}
}
I am observing infinite loop of view creation, deletion, and recreation when I move my app to background and bring back to foreground. I am clueless what is causing this repeated invocation of view body, so I tried Self._printChanges() inside the view body . But all I get is the following in console.
ChildView: @ self , _dismiss changed. //<--- This is the problematic view
ParentView: unchanged. //<--- This is parent view
The issue has also been reported on Apple developer forums but no solution found.
What are other options to debug this issue?
I am in the process of adding my company's brand font to our SwiftUI app. I am able to implement the font using the provided public APIs so that text styles / dynamic type and the font weight modifier in SwiftUI work correctly.
However we are unable to implement custom font in such a way that text styles / dynamic type, the font weight modifier, and the bold text accessibility setting all work at the same time. Am I missing an implementation detail so that all these features work correctly?
Font Setup
The font files were modified to better support SwiftUI:
The font style name metadata was modified to match the name the .fontWeight(...) modifier expects. This was done with Typelight.
The font weight value (100/200/300) was modified so that the underlying weight value matches the value the .fontWeight(...) modifier expects. See "Using custom fonts with SwiftUI" by Matthew Flint.
The font files were imported via the Info.plist.
Examples
Font Weight Comparison
San Fransisco:
Text("#100")
.font(.largeTitle)
.fontWeight(.ultraLight)
Overpass by Name:
Text("#100")
.font(.custom("Overpass-UltraLight", size: 34, relativeTo: .largeTitle))
Overpass by Weight:
Text("#100")
.fontWeight(.ultraLight)
.font(.custom("Overpass", size: 34, relativeTo: .largeTitle))
Legibility Weight Test
When using the .fontWeight(...) modifier, the custom font does not change weights when the bold text accessibility setting is enabled. Dynamic type size works as expected.
Normal legibility weight:
Bold legibility weight:
Dynamic Type Size:
Use UIFont
Using UIFont to load the custom font files and initializing a Font with the UIFont breaks dynamic type:
Bold type also does not work:
Custom Modifier
Creating a custom modifier allows us to support dynamic type and manually handle bold text. However it creates a conflicting API to SwiftUI's .fontWeight(...) modifier.
struct FontModifier: ViewModifier {
enum UseCase {
case paragraph
case headline
}
enum Weight {
case light
case regular
case heavy
}
@Environment(\.legibilityWeight) var legibilityWeight
var useCase: UseCase
var weight: Weight
init(_ useCase: UseCase, _ weight: Weight) {
self.useCase = useCase
self.weight = weight
}
var resolvedHeadlineWeight: String {
let resolvedLegibilityWeight = legibilityWeight ?? .regular
switch weight {
case .light:
switch resolvedLegibilityWeight {
case .regular:
return "Light"
case .bold:
return "Semibold"
@unknown default:
return "Light"
}
case .regular:
switch resolvedLegibilityWeight {
case .regular:
return "Regular"
case .bold:
return "Bold"
@unknown default:
return "Regular"
}
case .heavy:
switch resolvedLegibilityWeight {
case .regular:
return "Heavy"
case .bold:
return "Black"
@unknown default:
return "Heavy"
}
}
}
var resolvedParagraphWeight: Font.Weight {
switch weight {
case .light:
return .light
case .regular:
return .regular
case .heavy:
return .heavy
}
}
var resolvedFont: Font {
switch useCase {
case .paragraph:
return .system(.largeTitle).weight(resolvedParagraphWeight)
case .headline:
return .custom("Overpass-\(resolvedHeadlineWeight)", size: 34, relativeTo: .largeTitle)
}
}
func body(content: Content) -> some View {
content
.font(resolvedFont)
}
}
GridRow {
Text("Aa")
.modifier(FontModifier(.paragraph, .regular))
Text("Aa")
.modifier(FontModifier(.paragraph, .heavy))
Text("Aa")
.modifier(FontModifier(.headline, .regular))
Text("Aa")
.modifier(FontModifier(.headline, .heavy))
}
Font Environment Value
The font environment value does not contain font weight information when the fontWeight(...) modifier is used.:
struct DumpFontTest: View {
@Environment(\.font) var font
var body: some View {
Text("San Fransisco")
.onAppear {
print("------------")
dump(font)
}
}
}
Hello,
I am new to app development. I am trying to make an iMessage app. I created it and then added a SwiftUI view. It builds just fine and the view is visible on the storyboard, but the app is not present in iMessage on Simulator or on an actual device. What's wrong?
Thanks for any help.
import UIKit
import Messages
import SwiftUI
class MessagesViewController: MSMessagesAppViewController {
var hostingController: UIHostingController<CalendarView>?
override func viewDidLoad() {
super.viewDidLoad()
}
override func willBecomeActive(with conversation: MSConversation) {
super.willBecomeActive(with: conversation)
let swiftUIView = CalendarView()
let hostingController = UIHostingController(rootView: swiftUIView)
addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), hostingController.view.topAnchor.constraint(equalTo: view.topAnchor), hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)])
hostingController.didMove(toParent: self)
self.hostingController = hostingController
}
override func didResignActive(with conversation: MSConversation) {}
override func didReceive(_ message: MSMessage, conversation: MSConversation) {}
override func didStartSending(_ message: MSMessage, conversation: MSConversation) {}
override func didCancelSending(_ message: MSMessage, conversation: MSConversation) {}
override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {}
override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {}
}
I'm working on a NavigationStack based app. Somewhere I'm using:
@Environment(\.dismiss) private var dismiss
and when trying to navigate to that view it gets stuck.
I used Self._printChanges() and discovered the environment variable dismiss is changing repeatedly. Obviously I am not changing that variable explicitly. I wasn't able to reproduce this in a small project so far, but does anybody have any idea what kind of thing I could be doing that might be causing this issue?
iOS 17.0.3
Problem: When clicking on an item, it will be (un-)completed. When it's completed then ChildView should show GroupsView. However, that's not the case.
The logs are like this:
init, group Fruits - items not completed false - showItems false
body, group Fruits - items not completed false - showItems true
init, group Fruits - items not completed false - showItems false
init, group Fruits - items not completed false - showItems false
import SwiftUI
import SwiftData
@main
struct MainApp: App {
var body: some Scene {
WindowGroup {
SomeView()
}
.modelContainer(appContainer)
}
}
struct SomeView: View {
@Query private var items: [AItem]
var body: some View {
ParentView(items: items)
}
}
struct ParentView: View {
private var groupedItems: [GroupedAItems] = []
init(items: [AItem]) {
Dictionary(grouping: items) { $0.categoryName }
.forEach {
let groupedItems = GroupedAItems(categoryName: $0.key, items: $0.value)
self.groupedItems.append(groupedItems)
}
}
var body: some View {
ScrollView {
VStack(spacing: 15) {
ForEach(groupedItems, id: \.self.categoryName) { groupedItems in
ChildView(groupedItems)
}
}
}
}
}
struct ChildView: View {
public var groupedItems: GroupedAItems
@State private var showItems: Bool
init(_ groupedItems: GroupedAItems) {
self.groupedItems = groupedItems
self._showItems = State(initialValue: !groupedItems.completed)
print("init, group \(groupedItems.categoryName) - items not completed \(!groupedItems.completed) - showItems \(showItems)")
}
var body: some View {
print("body, group \(groupedItems.categoryName) - items not completed \(!groupedItems.completed) - showItems \(showItems)")
if showItems {
return AnyView(ItemsSampleView(items: groupedItems.items, onClick: { showItems = false }))
} else {
return AnyView(GroupsView(groupedItems: groupedItems, onClick: { showItems = true }))
}
}
}
struct ItemsSampleView: View {
public var items: [AItem]
public var onClick: () -> Void
private let gridColumns = [GridItem(.adaptive(minimum: CGFloat(70)))]
var body: some View {
VStack {
Button {
onClick()
} label: {
Image(systemName: "chevron.down")
}
Spacer()
LazyVGrid(columns: gridColumns) {
ForEach(items.sorted(by: {$0.name < $1.name})) { item in
Button {
item.completed.toggle()
} label: {
Text(item.name)
}
}
}
}
}
}
struct GroupsView: View {
public var groupedItems: GroupedAItems
public var onClick: () -> Void
var body: some View {
VStack {
Button {
onClick()
} label: {
Image(systemName: "chevron.down")
}
Spacer()
Text(groupedItems.categoryName)
}
}
}
@Model
final class AItem: Identifiable {
@Attribute(.unique) public var id: String
public var name: String
public var categoryName: String
public var completed = false
internal init(name: String, categoryName: String) {
self.id = UUID().uuidString
self.name = name
self.categoryName = categoryName
}
}
struct GroupedAItems {
var categoryName: String
var items: [AItem]
var completed: Bool {
items.filter { !$0.completed }.isEmpty
}
}
@MainActor
let appContainer: ModelContainer = {
do {
let container = try ModelContainer(for: AItem.self)
// Make sure the persistent store is empty. If it's not, return the non-empty container.
var itemFetchDescriptor = FetchDescriptor<AItem>()
itemFetchDescriptor.fetchLimit = 1
guard try container.mainContext.fetch(itemFetchDescriptor).count == 0 else { return container }
container.mainContext.insert(AItem(name: "Apple", categoryName: "Fruits"))
return container
} catch {
fatalError("Failed to create container")
}
}()
I have a problem in dealing with RTL language (Arabic) in SwiftUI with List and Searchable flow, also when long pressed on the search bar to prompt the options menu it is also flipped.
I added the environment parameter to support right to left layout direction for the list, but when I clicks on the search bar to do the search flow the list is flipped again, Thanks in advance.
var body: some View {
NavigationStack {
List {
Section {
Text("مرحبا")
}
}
.environment(\.layoutDirection, .rightToLeft)
.flipsForRightToLeftLayoutDirection(true)
.navigationTitle(" جديد")
.toolbar(content: {
Button("اغلاق") {
self.dismiss()
}
})
}
.tint(Color.blue)
.searchable(text: self.$searchText, placement: .navigationBarDrawer(displayMode: .always))
.interactiveDismissDisabled()
}
I've defined a custom layout container by having a struct conform to Layout and implementing the appropriate methods, and it works as expected.
The problem comes when trying to display Image, as they are shown squished when just using the .resizable() view modifier, not filling the container when using .scaledToFit() or extending outside of the expected bounds when using .scaledToFill().
I understand that this is the intended behaviour of these modifiers, but I would like to replicate UIImageView's scaledAspectFill.
I know that this can usually be achieved by doing:
Image("adriana-wide")
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipped()
But hardcoding the frame like that defeats the purpose of using the Layout, plus I wouldn't have direct access to the correct sizes, either.
The only way I've managed to make it work is by having a GeometryReader per image, so that the expected frame size is known and can bet set, but this is cumbersome and not really reusable.
GalleryGridLayout() {
GeometryReader { geometry in
Image("adriana-wide")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
[...]
}
Is there a more elegant, and presumably efficient as well as reusable, way of achieving the desired behaviour?
Here's the code of the Layout.
== PREVIEW UPDATE ERROR:
JITError
==================================
| NoBuiltTargetDescriptionCouldBeFound
|
| translationUnit: PreviewTranslationUnit(moduleNamePrefix: "Previews_EmptyFeedRow", sourceIdentifier: file:///Users/bryananderson/Developer/JournalApp/JournalApp/Interface/Feed/EmptyFeedRow.swift -> EmptyFeedRow.swift, parseTree: ParseTree(version: 727, statements: 3, providers: 1), update: nil, changesContextMemoizer: PreviewsPipeline.PreviewTranslationUnit.(unknown context at $34b4b9c4c).ChangesContextMemoizer(parseTree: ParseTree(version: 727, statements: 3, providers: 1), sourceIdentifier: file:///Users/bryananderson/Developer/JournalApp/JournalApp/Interface/Feed/EmptyFeedRow.swift -> EmptyFeedRow.swift, cachedValue: os.OSAllocatedUnfairLock<Swift.Optional<PreviewsModel.ParseTree.PreviewChangesContext>>(__lock: Swift.ManagedBuffer<Swift.Optional<PreviewsModel.ParseTree.PreviewChangesContext>, __C.os_unfair_lock_s>)), registryDeclarationMemoizer: PreviewsPipeline.PreviewTranslationUnit.(unknown context at $34b4b9bec).RegistryDeclarationMemoizer)
|
| builtTargetDescriptions:
|
== VERSION INFO:
Tools: 16A5171c
OS: 24A5264n
PID: 906
Model: MacBook Pro
Arch: arm64e
== ENVIRONMENT:
openFiles = [
/Users/bryananderson/Developer/JournalApp/JournalApp/Interface/Feed/EmptyFeedRow.swift
]
wantsNewBuildSystem = true
newBuildSystemAvailable = true
activeScheme = JournalApp
activeRunDestination = iPhone 15 Pro variant iphonesimulator arm64
workspaceArena = [x]
buildArena = [x]
buildableEntries = [
Remember.app
]
runMode = JIT Executor
== SELECTED RUN DESTINATION:
name = iPhone 15 Pro
eligible = true
sdk = Optional(<DVTSDK:0x13870da30:'iphonesimulator18.0':Simulator - iOS 18.0:<DVTFilePath:0x600001e8c700:'/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.0.sdk'>>)
variant = Optional("iphonesimulator")
device = Optional(<DVTiPhoneSimulator: 0x32f00d290> {
SimDevice: iPhone 15 Pro (CF3C85BC-F559-4437-9072-7F30153B399B, iOS 18.0, Booted)
PairedSim: <DVTiPhoneSimulator: 0x33733d150> {
SimDevice: Apple Watch Series 9 (45mm) (627CE93E-EB02-4200-BE40-3DCB5C91DB44, watchOS 11.0, Shutdown)
}
})
== SELECTED RUN DESTINATION:
Simulator - iOS 18.0 | iphonesimulator | arm64 | iPhone 15 Pro | Apple Watch Series 9 (45mm)
jit enabled: true
fallback to dynamic replacement: false
I am developing an iOS app using SwiftUI and have encountered an Auto Layout constraint conflict issue that appears when tapping on a TextField within a LoginView. I've tried several troubleshooting steps but haven't been able to resolve it.
Error Message:
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x6000021298b0 'accessoryView.bottom' _UIRemoteKeyboardPlaceholderView:0x10460dd10.bottom == _UIKBCompatInputView:0x1059220e0.top (active)>",
"<NSLayoutConstraint:0x60000217a620 'assistantHeight' SystemInputAssistantView.height == 45 (active, names: SystemInputAssistantView:0x10591ce60 )>",
"<NSLayoutConstraint:0x60000217d090 'assistantView.bottom' SystemInputAssistantView.bottom == _UIKBCompatInputView:0x1059220e0.top (active, names: SystemInputAssistantView:0x10591ce60 )>",
"<NSLayoutConstraint:0x60000217d040 'assistantView.top' V:[_UIRemoteKeyboardPlaceholderView:0x10460dd10]-(0)-[SystemInputAssistantView] (active, names: SystemInputAssistantView:0x10591ce60 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60000217d040 'assistantView.top' V:[_UIRemoteKeyboardPlaceholderView:0x10460dd10]-(0)-[SystemInputAssistantView] (active, names: SystemInputAssistantView:0x10591ce60 )>
This error appears in the console when I click on the TextField in my LoginView while running the code on a simulation. The app doesn't crash, but the console indicates there is a constraint conflict related to the keyboard. Here's my LoginView:
struct LoginView: View {
@StateObject var viewModel = LoginViewModel()
var body: some View {
NavigationStack {
VStack {
Spacer()
Image("logo")
.resizable()
.scaledToFit()
.frame(width: 150, height: 100)
VStack {
TextField("Enter your email", text: $viewModel.email)
.autocapitalization(/*@START_MENU_TOKEN@*/.none/*@END_MENU_TOKEN@*/)
.modifier(TextFieldModifier())
SecureField("Enter your password", text: $viewModel.password)
.modifier(TextFieldModifier())
}
Button {
print("Show forgot password")
} label: {
Text("Forgot Password")
.font(.footnote)
.fontWeight(.semibold)
.padding(.top)
.padding(.trailing, 20)
}
.frame(maxWidth: .infinity, alignment: .trailing)
Button {
Task { try await viewModel.signIn() }
} label: {
Text("Login")
.font(.subheadline)
.fontWeight(.semibold)
.foregroundColor(.white)
.frame(width: 360, height: 44)
.background(Color(.black))
.cornerRadius(8)
}
.padding(.vertical)
HStack {
Rectangle()
.frame(width: (UIScreen.main.bounds.width / 2) - 40, height: 0.5)
Text("OR")
.font(.footnote)
.fontWeight(.semibold)
.foregroundColor(.gray)
Rectangle()
.frame(width: (UIScreen.main.bounds.width / 2) - 40, height: 0.5)
}
.foregroundColor(.gray)
HStack {
Image("facebook_logo")
.resizable()
.frame(width: 20, height: 20)
Text("Continue with Facebook")
.font(.footnote)
.fontWeight(.semibold)
.foregroundColor(Color(.systemBlue))
}
.padding(.top, 8)
Spacer()
Divider()
NavigationLink {
AddEmailView()
.navigationBarBackButtonHidden(true)
} label: {
HStack (spacing: 3) {
Text("Don't have an account?")
Text("Sign Up")
.fontWeight(.semibold)
}
.font(.footnote)
}
.padding(.vertical, 16)
}
}
}
}
#Preview {
LoginView()
}
And my TextFieldModifier:
struct TextFieldModifier: ViewModifier {
func body(content: Content) ->some View {
content
.font(.subheadline)
.padding(12)
.background(Color(.systemGray6))
.cornerRadius(10)
.padding(.horizontal, 24)
.padding(.top)
}
}
Attempts to Resolve:
I've checked the TextFieldModifier for any potential issues but it seems standard.
I've tried simplifying the view by removing other elements, but the issue persists.
The issue seems to occur regardless of the simulator device or iOS version I use.
Questions:
What could be causing this Auto Layout constraint conflict in a SwiftUI app?
Are there any known issues with SwiftUI's TextField and keyboard interactions that might lead to such constraints issues?
Any suggestions on how to debug or resolve this constraint conflict?
I have an app with fairly typical requirements - I need to insert some data (in my case from the network but could be anything) and I want to do it in the background to keep the UI responsive.
I'm using SwiftData.
I've created a ModelActor that does the importing and using the debugger I can confirm that the data is indeed being inserted.
On the UI side, I'm using @Query and a SwiftUI List to display the data but what I am seeing is that @Query is not updating as the data is being inserted. I have to quit and re-launch the app in order for the data to appear, almost like the context running the UI isn't communicating with the context in the ModelActor.
I've included a barebones sample project. To reproduce the issue, tap the 'Background Insert' button. You'll see logs that show items being inserted but the UI is not showing any data.
I've tested on the just released iOS 18b3 seed (22A5307f).
The sample project is here:
https://hanchor.s3.amazonaws.com/misc/SwiftDataBackgroundV2.zip
I'm trying to add a ControlWidget to my WidgetBundle like this:
struct MyWidgets: WidgetBundle {
var body: some Widget {
if #available(iOSApplicationExtension 18.0, *) {
LauncherControl()
}
MyLiveActivityWidget()
HomeScreenWidget()
LockScreenWidget()
}
This works exactly as expected on iOS 18. However on iOS 17 my app seems to have no widgets at all.
The workaround described here (https://www.avanderlee.com/swiftui/variable-widgetbundle-configuration/) does not work either since WidgetBundleBuilder.buildBlock does not accept ControlWidget as an argument.
What is the correct way to include a Control widget conditionally on iOS 18?
First of all, I tried MobileVLCKit but there is too much delay
Then I wrote a UDPManager class and I am writing my codes below. I would be very happy if anyone has information and wants to direct me.
Broadcast code
ffmpeg -f avfoundation -video_size 1280x720 -framerate 30 -i "0" -c:v libx264 -preset medium -tune zerolatency -f mpegts "udp://127.0.0.1:6000?pkt_size=1316"
Live View Code (almost 0 delay)
ffplay -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 1 -strict experimental -framedrop -f mpegts -vf setpts=0 udp://127.0.0.1:6000
OR
mpv udp://127.0.0.1:6000 --no-cache --untimed --no-demuxer-thread --vd-lavc-threads=1
UDPManager
import Foundation
import AVFoundation
import CoreMedia
import VideoDecoder
import SwiftUI
import Network
import Combine
import CocoaAsyncSocket
import VideoToolbox
class UDPManager: NSObject, ObservableObject, GCDAsyncUdpSocketDelegate {
private let host: String
private let port: UInt16
private var socket: GCDAsyncUdpSocket?
@Published var videoOutput: CMSampleBuffer?
init(host: String, port: UInt16) {
self.host = host
self.port = port
}
func connectUDP() {
do {
socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: .global())
//try socket?.connect(toHost: host, onPort: port)
try socket?.bind(toPort: port)
try socket?.enableBroadcast(true)
try socket?.enableReusePort(true)
try socket?.beginReceiving()
} catch {
print("UDP soketi oluşturma hatası: \(error)")
}
}
func closeUDP() {
socket?.close()
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didConnectToAddress address: Data) {
print("UDP Bağlandı.")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didNotConnect error: Error?) {
print("UDP soketi bağlantı hatası: \(error?.localizedDescription ?? "Bilinmeyen hata")")
}
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
if !data.isEmpty {
DispatchQueue.main.async {
self.videoOutput = self.createSampleBuffer(from: data)
}
}
}
func createSampleBuffer(from data: Data) -> CMSampleBuffer? {
var blockBuffer: CMBlockBuffer?
var status = CMBlockBufferCreateWithMemoryBlock(
allocator: kCFAllocatorDefault,
memoryBlock: UnsafeMutableRawPointer(mutating: (data as NSData).bytes),
blockLength: data.count,
blockAllocator: kCFAllocatorNull,
customBlockSource: nil,
offsetToData: 0,
dataLength: data.count,
flags: 0,
blockBufferOut: &blockBuffer)
if status != noErr {
return nil
}
var sampleBuffer: CMSampleBuffer?
let sampleSizeArray = [data.count]
status = CMSampleBufferCreateReady(
allocator: kCFAllocatorDefault,
dataBuffer: blockBuffer,
formatDescription: nil,
sampleCount: 1,
sampleTimingEntryCount: 0,
sampleTimingArray: nil,
sampleSizeEntryCount: 1,
sampleSizeArray: sampleSizeArray,
sampleBufferOut: &sampleBuffer)
if status != noErr {
return nil
}
return sampleBuffer
}
}
I didn't know how to convert the data object to video, so I searched and found this code and wanted to try it
func createSampleBuffer(from data: Data) -> CMSampleBuffer? {
var blockBuffer: CMBlockBuffer?
var status = CMBlockBufferCreateWithMemoryBlock(
allocator: kCFAllocatorDefault,
memoryBlock: UnsafeMutableRawPointer(mutating: (data as NSData).bytes),
blockLength: data.count,
blockAllocator: kCFAllocatorNull,
customBlockSource: nil,
offsetToData: 0,
dataLength: data.count,
flags: 0,
blockBufferOut: &blockBuffer)
if status != noErr {
return nil
}
var sampleBuffer: CMSampleBuffer?
let sampleSizeArray = [data.count]
status = CMSampleBufferCreateReady(
allocator: kCFAllocatorDefault,
dataBuffer: blockBuffer,
formatDescription: nil,
sampleCount: 1,
sampleTimingEntryCount: 0,
sampleTimingArray: nil,
sampleSizeEntryCount: 1,
sampleSizeArray: sampleSizeArray,
sampleBufferOut: &sampleBuffer)
if status != noErr {
return nil
}
return sampleBuffer
}
And I tried to make CMSampleBuffer a player but it just shows a white screen and doesn't work
struct SampleBufferPlayerView: UIViewRepresentable {
typealias UIViewType = UIView
var sampleBuffer: CMSampleBuffer
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: .zero)
let displayLayer = AVSampleBufferDisplayLayer()
displayLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(displayLayer)
context.coordinator.displayLayer = displayLayer
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
context.coordinator.sampleBuffer = sampleBuffer
context.coordinator.updateSampleBuffer()
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var displayLayer: AVSampleBufferDisplayLayer?
var sampleBuffer: CMSampleBuffer?
func updateSampleBuffer() {
guard let displayLayer = displayLayer, let sampleBuffer = sampleBuffer else { return }
if displayLayer.isReadyForMoreMediaData {
displayLayer.enqueue(sampleBuffer)
} else {
displayLayer.requestMediaDataWhenReady(on: .main) {
if displayLayer.isReadyForMoreMediaData {
displayLayer.enqueue(sampleBuffer)
print("isReadyForMoreMediaData")
}
}
}
}
}
}
And I tried to use it but I couldn't figure it out, can anyone help me?
struct ContentView: View {
// udp://@127.0.0.1:6000
@ObservedObject var udpManager = UDPManager(host: "127.0.0.1", port: 6000)
var body: some View {
VStack {
if let buffer = udpManager.videoOutput{
SampleBufferDisplayLayerView(sampleBuffer: buffer)
.frame(width: 300, height: 200)
}
}
.onAppear(perform: {
udpManager.connectUDP()
})
}
}
I'm trying to develop an iOS app with SwiftUI supporting iOS15 and above and then I encounter with this issue.
I have a SwiftUI view and call this view from multiple different UI flows. So I want to provide different environment objects depending which flow it is in. I want them optional because depending which environment object I am able to retrieve, I want to modify properties of those environment objects to trigger UI updates. (expect to use "if let" check for optional binding)
Inside that view, I want to retrieve those environment objects as optionals but I can't use @EnvironmentObject because is expects conforming ObservableObject protocol. I also tried to use EnvironmentKey protocol to define custom optional types but this time Xcode gives error as:
"Failed to produce diagnostic for expression; please submit a bug report (https://swift.org/contributing/#reporting-bugs)"
I really wonder If I am able to reach an optional environment object for iOS15.
Note: I know that with Observation framework I may be able to get optional environment object but I have to update my supported iOS level beginning from iOS17 for the app which I can't do right now.
I want to smootlhy blend two or more UIImages without pulsating/pumping effect but cannot achieve this.
I have created a simple example code to visualize my issue.
Two UIImages with exactly the same content ("gear") are initialized. The images are then manipulated via "func resizeImage()" with:
UIGraphicsBeginImageContext()
defer { UIGraphicsEndImageContext() }
draw(in: CGRect())
This custom draw: (in:) is important for me as in my app there is a lot of custom drawing logic.
In the body I use a PhaseAnimator to animate through the different stages of my custom animation.
The result is always a pulsating/pumping effect which is unwanted. If the shape of two blended UIImages is exactly the same, there should not be any noticeable difference, especially no intensity change.
How to get a smooth blend without pulsating/pumping effect?
Any help appreciated.
import SwiftUI
struct ContentView: View {
@State var widgetSize: CGFloat = 128
let img1 = UIImage(systemName: "gear")!
let img2 = UIImage(systemName: "gear")!
func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
image.draw(in: CGRectMake(0, 0, newWidth, newHeight))
guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else { return UIImage(systemName: "questionmark")! }
UIGraphicsEndImageContext()
return newImage
}
var body: some View {
PhaseAnimator([1, 2]) { phase in
// This is just for demonstration purposes
// I have two or more UIImages that I want to smootlhy blend
// The UIImages are created with image.draw
// the result is a pulsating animation but I would expect
// a smooth blend over with no noticable change when there are two
// UIImages with identical content
let i1 = self.resizeImage(image: img1, newWidth: widgetSize)
let i2 = self.resizeImage(image: img2, newWidth: widgetSize)
VStack {
Image(uiImage: phase == 1 ? i1 : i2)
.renderingMode(.template)
.foregroundStyle(.white)
.background(.black)
Spacer()
}
}
}
}
#Preview {
ContentView()
}