Create elegant and intuitive apps that integrate seamlessly with Apple platforms.

Design Documentation

Posts under Design tag

65 Posts
Sort by:
Post not yet marked as solved
1 Replies
281 Views
Hello! This is my first time posting a question on a form. So sorry ahead of time if I am not doing something right and please let me know how I can fix it! I am new to swift and I have been following a video by AppStuff. https://youtu.be/QJHmhLGv-_0?si=OwLGXKNTc3m-UH7r&t=5914 . The link is time stamped to the part of the video I need help with. My question is: Where do I put the AuthenticationFormProtocol var formIsValid so that way I can call on formIsValid to use the .disabled and .opacity in the ButtonView File depending on if formIsValid is true or not? I deviated from the video by making a new file called ButtonView so that way I didn't have to copy and paste code that I would be using in two different places. ButtonView File import SwiftUI struct ButtonView: View { let printTitle: String let title: String let systemIcon: String //@Binding var disabledPlaceHolder: String let taskAction: () -> Void var body: some View { Button(action: { taskAction() }) { HStack { Text(title) .fontWeight(.semibold) Image(systemName: systemIcon) } .foregroundStyle(Color(.white)) .frame(width: UIScreen.main.bounds.width - 32, height: 48) } .background(Color(.systemBlue)) //.disabled(disabledPlaceHolder) //.opacity(disabledPlaceHolder ? 1.0 : 0.5) .clipShape(RoundedRectangle(cornerRadius: 10)) .padding(.bottom, 50) } } #Preview { ButtonView(printTitle: "Sign user up...", title: "Sign Up", systemIcon: "arrow.right", //disabledPlaceHolder: .constant(""), taskAction: {}) } LoginView File import SwiftUI struct LoginView: View { @State private var email = "" @State private var password = "" @EnvironmentObject var viewModel: AuthViewModel var body: some View { NavigationStack { VStack { //image Image("TestLogo") .resizable() .scaledToFill() .frame(width: 100, height: 120) .clipShape(RoundedRectangle(cornerRadius: 20)) .padding(.vertical, 32) //form fields VStack(spacing: 24) { InputView(text: $email, title: "Email", placeholder: "name@example.com") .textInputAutocapitalization(.none) InputView(text: $password, title: "Password", placeholder: "Enter your password", isSecureField: true) } .padding(.horizontal) .padding(.top, 12) //sign in button ButtonView(printTitle: "Login In", title: "SIGN IN", systemIcon: "arrow.right") { Task { try await viewModel.signIn(withEmail: email, password: password) } } // .disabled(formIsValid) // .opacity(formIsValid ? 1.0 : 0.5) Spacer() //signup button NavigationLink { RegistrationView() .navigationBarBackButtonHidden(true) } label: { HStack(spacing: 3) { Text("Don't have an account?") Text("Sign Up") .fontWeight(.bold) } .font(.system(size: 14)) } } } } } extension LoginView: AuthenticationFormProtocol { var formIsValid: Bool { return !email.isEmpty && email.contains("@") && !password.isEmpty && password.count > 5 } } RegistationView File struct RegistrationView: View { @State private var email = "" @State private var fullName = "" @State private var password = "" @State private var confirmPassword = "" @EnvironmentObject var viewModel: AuthViewModel @Environment(\.dismiss) var dismiss var body: some View { VStack { //image Image("TestLogo") .resizable() .scaledToFill() .frame(width: 100, height: 120) .clipShape(RoundedRectangle(cornerRadius: 20)) .padding(.vertical, 32) //form fields VStack(spacing: 24) { InputView(text: $email, title: "Email", placeholder: "name@example.com") .textInputAutocapitalization(.none) InputView(text: $fullName, title: "Full name", placeholder: "Enter your name") InputView(text: $password, title: "Password", placeholder: "Enter your password", isSecureField: true) InputView(text: $confirmPassword, title: "Confirm Password", placeholder: "Confirm your password", isSecureField: true) } .padding(.horizontal) .padding(.top, 12) //sign up button ButtonView(printTitle: "Create User", title: "CREATE USER", systemIcon: "arrow.right") { Task { try await viewModel.createUser(withEmail: email, password: password, fullname: fullName) } } // .disabled(formIsValid) // .opacity(formIsValid ? 1.0 : 0.5) Spacer() Button { dismiss() } label: { HStack(spacing: 3) { Text("Already have an account?") Text("Sign In") .fontWeight(.bold) } .font(.system(size: 14)) } } } } extension RegistrationView: AuthenticationFormProtocol { var formIsValid: Bool { return !email.isEmpty && email.contains("@") && !password.isEmpty && password.count > 5 && confirmPassword == password && !fullName.isEmpty } }
Posted Last updated
.
Post not yet marked as solved
2 Replies
398 Views
I've seen videos on how people on Youtube are using the Apple Vision pro as a Camera Monitor. I found this very neat, but I was wondering if there is a way to make a live stream panoramic view of live CCTV footage, with the Apple Vision Pro. SO my question is, can you make a panoramic view of something that is live, in real time?
Posted Last updated
.
Post not yet marked as solved
0 Replies
237 Views
Looking for help identifying the following ui element or 'widget' in this app, the window is a sort of 'drop zone', you drag and drop files to it, it then displays the DnD'd files as a 'file stack' which is a ui element commonly seen in the Dock. Unable to find the api to create this. Surely it exists? (A screenshot is attached)
Posted Last updated
.
Post marked as solved
2 Replies
2.7k Views
I try to change picker text color but, it does not work. As you see, "City" and "District"'s color are blue but, I'd like to make them white. I have tried below codes but, they do not work. Do you know any methods for that ? Picker("İl", selection: $selectedCity) { ForEach(turkishCities, id: \.self) { city in Text(city) .foregroundColor(.white) } } Picker("İlçe", selection: $selectedDistrict) { ForEach(cityDistricts[selectedCity] ?? [], id: \.self) { district in Text(district) .foregroundColor(Color.white) } } .onAppear { UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .normal) } Thank you in advance.
Posted Last updated
.
Post not yet marked as solved
0 Replies
228 Views
I'm looking to use a variable for the padding parameters but always seem to get an error reading "No exact matches in call to instance method 'padding'" ForEach(allGames) { theGame in var the_pad: [Edge.Set] = [.horizontal] if theGame.name == "Game1" { var the_pad: [Edge.Set] = [.horizontal,.top] } HStack{ ... } .padding(the_pad) } This is the code without all the stuff in HStack (which has no problems), to keep it simple This is for a menu and the top item gets cut off at the top hence it needs padding but the other menu items have better spacing without it. Yes, I got it to work using an if-else statement and 2 different HStacks, but I'm trying to learn and I'm wondering what I'm doing wrong.
Posted
by Justus_G.
Last updated
.
Post not yet marked as solved
1 Replies
467 Views
Hi, I uploaded my app to the app store but Apple rejected it and gave me the following reason for rejection. I don't know how to fix it because url for policy of privacy is working and show information. Please guide me for this how can I resolve it and re upload my app. Thank You Guideline 1.5 - Safety - Developer Information The support URL specified in your app’s metadata, https://www.doclinkapp.net/privacypolicy, does not properly navigate to the intended destination. Next Steps To resolve this issue, please revise your app’s support URL to ensure it directs users to a webpage with support information.
Posted
by Doclink.
Last updated
.
Post not yet marked as solved
0 Replies
511 Views
In theory, sending signals from iPhone apps to and from the brain with non-invasive technology could be achieved through a combination of brain-computer interface (BCI) technologies, machine learning algorithms, and mobile app development. Brain-Computer Interface (BCI): BCI technology can be used to record brain signals and translate them into commands that can be understood by a computer or a mobile device. Non-invasive BCIs, such as electroencephalography (EEG), can track brain activity using sensors placed on or near the head[6]. For instance, a portable, non-invasive, mind-reading AI developed by UTS uses an AI model called DeWave to translate EEG signals into words and sentences[3]. Machine Learning Algorithms: Machine learning algorithms can be used to analyze and interpret the brain signals recorded by the BCI. These algorithms can learn from large quantities of EEG data to translate brain signals into specific commands[3]. Mobile App Development: A mobile app can be developed to receive these commands and perform specific actions on the iPhone. The app could also potentially send signals back to the brain using technologies like transcranial magnetic stimulation (TMS), which can deliver information to the brain[5]. However, it's important to note that while this technology is theoretically possible, it's still in the early stages of development and faces significant technical and ethical challenges. Current non-invasive BCIs do not have the same level of fidelity as invasive devices, and the practical application of these systems is still limited[1][3]. Furthermore, ethical considerations around privacy, consent, and the potential for misuse of this technology must also be addressed[13]. Sources [1] You can now use your iPhone with your brain after a major breakthrough | Semafor https://www.semafor.com/article/11/01/2022/you-can-now-use-your-iphone-with-your-brain [2] ! Are You A Robot? https://www.sciencedirect.com/science/article/pii/S1110866515000237 [3] Portable, non-invasive, mind-reading AI turns thoughts into text https://techxplore.com/news/2023-12-portable-non-invasive-mind-reading-ai-thoughts.html [4] Elon Musk's Neuralink implants brain chip in first human https://www.reuters.com/technology/neuralink-implants-brain-chip-first-human-musk-says-2024-01-29/ [5] BrainNet: A Multi-Person Brain-to-Brain Interface for Direct Collaboration Between Brains - Scientific Reports https://www.nature.com/articles/s41598-019-41895-7 [6] Brain-computer interfaces and the future of user engagement https://www.fastcompany.com/90802262/brain-computer-interfaces-and-the-future-of-user-engagement [7] Mobile App + Wearable For Neurostimulation - Accion Labs https://www.accionlabs.com/mobile-app-wearable-for-neurostimulation [8] Signal Generation, Acquisition, and Processing in Brain Machine Interfaces: A Unified Review https://www.frontiersin.org/articles/10.3389/fnins.2021.728178/full [9] Mind-reading technology has arrived https://www.vox.com/future-perfect/2023/5/4/23708162/neurotechnology-mind-reading-brain-neuralink-brain-computer-interface [10] Synchron Brain Implant - Breakthrough Allows You to Control Your iPhone With Your Mind - Grit Daily News https://gritdaily.com/synchron-brain-implant-controls-tech-with-the-mind/ [11] Mind uploading - Wikipedia https://en.wikipedia.org/wiki/Mind_uploading [12] BirgerMind - Express your thoughts loudly https://birgermind.com [13] Elon Musk wants to merge humans with AI. How many brains will be damaged along the way? https://www.vox.com/future-perfect/23899981/elon-musk-ai-neuralink-brain-computer-interface [14] Models of communication and control for brain networks: distinctions, convergence, and future outlook https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7655113/ [15] Mind Control for the Masses—No Implant Needed https://www.wired.com/story/nextmind-noninvasive-brain-computer-interface/ [16] Elon Musk unveils Neuralink’s plans for brain-reading ‘threads’ and a robot to insert them https://www.theverge.com/2019/7/16/20697123/elon-musk-neuralink-brain-reading-thread-robot [17] Essa and Kotte https://arxiv.org/pdf/2201.04229.pdf [18] Synchron's Brain Implant Breakthrough Lets Users Control iPhones And iPads With Their Mind https://hothardware.com/news/brain-implant-breakthrough-lets-you-control-ipad-with-your-mind [19] An Apple Watch for Your Brain https://www.thedeload.com/p/an-apple-watch-for-your-brain [20] Toward an information theoretical description of communication in brain networks https://direct.mit.edu/netn/article/5/3/646/97541/Toward-an-information-theoretical-description-of [21] A soft, wearable brain–machine interface https://news.ycombinator.com/item?id=28447778 [22] Portable neurofeedback App https://www.psychosomatik.com/en/portable-neurofeedback-app/ [23] Intro to Brain Computer Interface http://learn.neurotechedu.com/introtobci/
Posted
by ztick.
Last updated
.
Post not yet marked as solved
0 Replies
384 Views
This image is drawn entirely using Bezier curves and animated only in Swift code. 500 lines of code. The code is in the attachment. Animation video here https://youtu.be/JNPv4qnsPA8 How it works on a real device here https://apps.apple.com/us/app/limoonik/id1629631880 This code is also here https://limooonik.store/ ContentView.swift
Posted
by Nick Limo.
Last updated
.
Post not yet marked as solved
0 Replies
390 Views
Hi! I am working on an app for Vision Pro. I would like to create a SideBar in a view that shows different topics, that you can click on. Firstly, I need help understanding how to create a SideBar. Also, I have already made the different topics that will be displayed on the SideBar but I don't know how to link the SideBar up to the topics view. For example, if a user clicks on Maple Trees as a topic in the SideBar, it would take them to a new window that talks about Maple Trees. If you can help, that would be great!
Posted Last updated
.
Post not yet marked as solved
4 Replies
1k Views
Hey Everyone, I've been remaking an app using SwiftUI, and I am running into a weird animation bug/hitch using .sheet(isPresented:). I have a GIF illustrating the issue, but can't seem to attach it to this forum post. Let me know if there's anyway to share this. Link to gif detailing issue(self hosted) Regardless, my issue: To describe the issue: I'm using two Detents for the sheet, [.medium, .large]. I have a TextField that's displayed in the sheet, and when opening it, the keyboard moves my content upward (expected, working fine). My issue comes when I programmatically resign the TextField (using .focused($isFocused). The content on the sheet jumps up, beyond the upper bound of the sheet. My hypothesis is that the sheet's content is immediately redrawn, using the medium detent frame, but before the animation has finished going from large to medium. It's possible this is not a SwiftUI bug, but something wrong with my implementation. I'll provide the relevant code below. Any help is greatly appreciated! Onboarding.swift (presents the sheet) @ViewBuilder var content: some View { VStack { headline .foregroundStyle(.white.opacity(0.95)) subHeadline .foregroundStyle(.white) Spacer() messages .foregroundStyle(.white) Spacer() callToAction } .ignoresSafeArea(.keyboard) .sheet(isPresented: $showJoin) { join } } var join: some View { Join() .ignoresSafeArea() .presentationCornerRadius(40) .presentationDragIndicator(.hidden) .presentationBackground { Rectangle() .fill(.ultraThinMaterial) .padding(.bottom, -1000) } .presentationDetents([.medium, .large]) } Join.swift (holds the sheet's content, and displays the heading) struct Join: View { @State private var didSignUp = false var body: some View { VStack { heading Divider() contentView } .animation(.easeInOut, value: didSignUp) .transition(.opacity) .interactiveDismissDisabled(didSignUp) } var heading: some View { VStack(spacing: 8) { Text(didSignUp ? "Verify" : "Start here") .frame(maxWidth : .infinity, alignment: .leading) .font(.largeTitle.bold()) .foregroundColor(.primary) .blendMode(.overlay) Text(didSignUp ? "Enter code" : "Create an account") .frame(maxWidth : .infinity, alignment: .leading) .font(.callout) .foregroundColor(.primary) .blendMode(.overlay) } .padding(.top, 20) .padding(.horizontal) } var contentView: some View { Group { if didSignUp { Verification() .transition(.move(edge: .trailing).combined(with: .opacity)) } else { SignUp(didSignUp: $didSignUp) .transition(.move(edge: .leading).combined(with: .opacity)) } } .padding(.horizontal) } } SignUp.swift (the sheet content) struct SignUp: View { @Binding var didSignUp: Bool @State private var phoneNumber: String = "" @State private var sendingTextMessage = false @FocusState private var isFocused: Bool private let notice = """ By creating an account, you agree to our **[Terms of Service](https://cordia.app/tos)** and **[Privacy Policy](https://cordia.app/privacy)** """ var body: some View { VStack { VStack { phoneNumberLabel phoneNumberInput } .padding() if sendingTextMessage { LoadingIndicator(isVisible: $sendingTextMessage) .padding() } else { continueButton .padding() } Spacer() termsAndConditions .padding(.bottom) } } var phoneNumberLabel: some View { Text("Enter your phone number") .font(.title3) .foregroundColor(.primary) .blendMode(.overlay) .frame(maxWidth: .infinity, alignment: .leading) } var phoneNumberInput: some View { iPhoneNumberField("(***) 867-5309", text: $phoneNumber) .maximumDigits(10) .formatted() .clearsOnEditingBegan(true) .clearButtonMode(.always) .font(.system(size: 25, weight: .semibold)) .padding() .glass(cornerRadius: 10) .focused($isFocused) } var termsAndConditions: some View { Text(addPolicyLinks() ?? AttributedString(notice)) .multilineTextAlignment(.center) .fixedSize(horizontal: false, vertical: true) .font(.body) .blendMode(.overlay) .padding() } var continueButton: some View { Button(action: { guard !sendingTextMessage else { return } sendingTextMessage = true isFocused = false UIImpactFeedbackGenerator(style: .rigid).impactOccurred() Auth.signUp(with: phoneNumber) { user, error in didSignUp = true } }) { Text("Join Cordia") .font(.system(size: 25, weight: .semibold)) .foregroundColor(.primary.opacity(0.8)) .frame(width: 200, height: 60) .tintedGlass( cornerRadius: 20, strokeColor: .cordiaGoldDark, strokeSize: 1.0, tint: .cordiaGold ) } } private func addPolicyLinks() -> AttributedString? { var string = try? AttributedString(markdown: notice) if let range = string?.range(of: "Terms of Service") { string?[range].foregroundColor = .cordiaGold } if let range = string?.range(of: "Privacy Policy") { string?[range].foregroundColor = .cordiaGold } return string } }
Posted
by jckwind.
Last updated
.
Post not yet marked as solved
1 Replies
502 Views
The hardest part of SwiftUI programming is to correctly define the layers of references that you need as your app grows features. When you add Swift data to the mix, it hard to get much of anything correct. I have an application that interacts with the outside world via BLE and LocationManager. I need to preserve used BLE devices and then store their current state in a static Monitor type class structure. This monitor though, needs to have access to some SwiftData elements, and it is not clear from the documentation whether it's preferred to create multiple ModelContainer instances, when they might share a particular types management. This doesn't feel very safe, so it would then make more sense to have a ModelContainer stuck inside of some other static Monitor object that everyone would use to get the single ModelContainer that should be used. All of the context specific stacking of references in SwiftUI creates huge dependency chains, and it make the build of my application, currently to take 10s of minutes sometimes, when I have changes in flux and the compiler cannot make heads or tails out of broken references. We really need to find a way to get the compiler fixed so that as a Recursive Decent parser, it has an easier time finding a terminal state instead of crawling up and down the stack of references looking for a place that it can reach a terminal state. Not using ';' on every statement is a big part of the problem I feel...
Posted
by greggwon.
Last updated
.
Post not yet marked as solved
0 Replies
359 Views
Hello! I need advice. According to Apple's guidelines, is it permissible to ask users during the initial app launch, through an OnBoarding screen (example in the screenshot), if they are older than 16 when the Age Rating on the App Store is set to 9+? I want to determine if the user from Europe and the UK has reached the age of consent in order to display or not display the GDPR consent form to them. Thanks!
Posted
by zeil.
Last updated
.
Post not yet marked as solved
5 Replies
345 Views
Hi there! I recently got into a discussion with my Java professor. In her style guide she specifically mentions to never use the break or continue keywords in loops as they are, according to her, outdated and unviable. I have tried to prove by counter example when they are more useful than alternatives, without success. This has gotten me wondering if these keywords are actually outdated, I am still a student after all. So I wanted to know from someone at Apple if using break or continue is forbidden, discouraged or fine to use (specifically in java but general guidelines are also fine) and why? Any answer from a current or former Apple employee would help me greatly to have an insight into how the industry handles these keywords and I thank you in advance for your response. If there is a better place to ask this please direct me towards that.
Posted Last updated
.
Post not yet marked as solved
0 Replies
356 Views
Só tenho aparelho Android, não tenho nenhum aparelho com o sistema iOS para publicar o meu aplicativo na App Store, alguém pode fazer isso por mim? Só falta o upload para o XCode, o app está todo configurado, aberto a negociação.
Posted
by Anerson.
Last updated
.
Post not yet marked as solved
1 Replies
1k Views
Hello, Our app rejected by following reason: Guideline 4.3 - Design We noticed your app shares a similar binary, metadata, and/or concept as apps previously submitted by a terminated Apple Developer Program account. Submitting similar or repackaged apps is a form of spam that creates clutter and makes it difficult for users to discover new apps. Next Steps Since we do not accept spam apps on the App Store, we encourage you to review your app concept and submit a unique app with distinct content and functionality. Resources Some factors that contribute to a spam rejection may include: Submitting an app with the same source code or assets as other apps already submitted to the App Store Creating and submitting multiple similar apps using a repackaged app template Purchasing an app template with problematic code from a third party Submitting several similar apps across multiple accounts Learn more about our requirements to prevent spam in App Store Review Guideline 4.3. iOS App 1.0App Version Rejection Reasons: 4.3.0 Design: Spam The application is 100% developed by our team and I am 100% sure of it. How can we do it ? Please help.
Posted
by NEURALABZ.
Last updated
.
Post not yet marked as solved
0 Replies
540 Views
I’m trying to create a layout with a group of labels / tags. The labels have a flexible width and height. If a label exceeds the width of the container it should grow in height. I’m using a UICollectionView with a compositional layout to create this layout. At first I used estimated for the width and height dimension of the layout items within a horizontal group layout that had an fractionalWidth and an estimated height. This worked but only if the cells with the labels were smaller than the group width. If they are larger, the app crashes. Somewhere on StackOverflow I read that this is a known issue. To fix the issue above I made the main group a vertical layout and created a different group for every row of labels. If the labels width exceeds the width of the group I give if a fractional width and if it’s smaller I give it an estimated width. This approach prevents the crashed above and gives me my desired layout. But… as soon as I rotate the device of call invalidate on the collection view layout; the layout is messed up. It looks like very cell gets the width of the value I proved in the estimated width dimension. Can someone help me to fix this issue? My app needs to run on iOS 14 and above. I've uploaded a small demo app to my GitHub that contains my current setup: https://github.com/JeroenVanRijn/compositional-layout This is the code I use for the UICollectionViewCompositionalLayout: func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection in var groups = [NSCollectionLayoutGroup]() let contentSize = layoutEnvironment.container.effectiveContentSize var rows = [[CGFloat]]() var currentRow = [CGFloat]() var currentRowWidth: CGFloat = 0 let spacing: CGFloat = 10 let maxRowWidth = contentSize.width - (2 * spacing) // Loop through the labels and add them to rows. for label in self.dataSource.snapshot(for: .main).items { let textWidth = self.width(for: label.text) let cellWidth = textWidth + 16 if currentRowWidth > 0 { currentRowWidth += spacing // spacing } currentRowWidth += cellWidth currentRow.append(cellWidth) if currentRowWidth > maxRowWidth { let last = currentRow.last! let withoutLast = Array(currentRow.dropLast()) addRow(items: withoutLast) currentRow = [last] currentRowWidth = last } } // Remaining rows if !currentRow.isEmpty { addRow(items: currentRow) } func addRow(items: [CGFloat]) { rows.append(items) // If a row contains only item that is larger that the group with we give it the width of the group. if items.count == 1 && items[0] >= maxRowWidth { print("Add row: \(items.count) - FULL WIDTH") let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(44)) let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(44)) let innerGroup = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [layoutItem]) innerGroup.interItemSpacing = .fixed(spacing) groups.append(innerGroup) } else { print("Add row: \(items.count)") let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .estimated(44)) let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(44)) let innerGroup = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [layoutItem]) innerGroup.interItemSpacing = .fixed(spacing) groups.append(innerGroup) } } print("Number of groups: \(groups.count)") let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(44)) let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: groups) group.interItemSpacing = .fixed(spacing) let section = NSCollectionLayoutSection(group: group) section.interGroupSpacing = spacing section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10) return section } return layout } func width(for text: String) -> CGFloat { text.size(withAttributes:[.font: UIFont.systemFont(ofSize: 16)]).width }
Posted Last updated
.
Post not yet marked as solved
0 Replies
498 Views
Currently, there seems to be an all or nothing approach to supporting rotation on iPhone. Either every screen in your UI supports rotation, or none of them do. For a some apps however, that approach won't work. They have a number of screens that don't adapt well to a super letterboxed screen size, and a number of others that would benefit from the additional screen space. Previous discussion on this issue recommends the use of size classes, but this advice fails to recognise that some use cases simply aren't suited to being super letterboxed. Apple's own UI design is tacit acknowledgement of this: For example, the main UI of the Camera app stays fixed in the portrait orientation in the shooting mode, but presents a rotatable modal to review photos and videos. Even Springboard, the home screen of the iPhone, remains locked in the portrait orientation whilst allowing an app to be presented in landscape. Social media and news apps are another example: generally anchored around a portrait newsfeed that doesn't adapt well to extreme letterboxing, but surfacing rich media such as images, videos, charts and other interactive elements that could use the flexibility of landscape presentation. (News app, looking at you.) Is it time to re-visit the rotation characteristics of the phone vs. tablet idioms? Is this all-or-nothing approach to rotation serving the platform well? Regardless, app designers at Apple and elsewhere are creating apps that use this hybrid approach to rotation. And as things stand today, SwiftUI makes it very difficult. A rough equivalent can be made using a ZStack and observing the device orientation, but this requires hiding the status bar and provides no way to honor a user's portrait lock settings. The only other option, as far as I can tell, is building the app using UIKit view controllers, to thread through supportedInterfaceOrientations hooks. Personally, what I'd love to see is a new presentationInterfaceOrientations(_:) hook on View, that allows a fullScreenCover presentation to be specified as supporting an alternative orientation set. This could be iPhone only, and should serve the majority of use cases. However, in the meantime, it would be great to know if there's a technique that can get the UIKit behavior in a SwiftUI app that doesn't require rewriting the entire container view hierachy in UIKit.
Posted
by tcldr.
Last updated
.