Post

Replies

Boosts

Views

Activity

scrollview layout
I am very confused about UIScrollview auto layout I want to make a very standard IOS Application with some textfields and textviews. When the keyboard appears, I want the current responder to be visible on screen. It seems to me very simple, There ara many posts on the subject, but I don't obtain the correct result, and I think it comes from the layout of my scrollview and it's contentView. For the layout, I do the following: The left, top, right and bottom of my UIscrollView is pinned on the view of the UIViewController. The left, top, right and bottom of the controlView is pinned on ContentLayoutGuide of the UIScrollview. And, as I want the scroll to be only vertical, I have the width of the Content View to be equal to the width of the FrameLayoutGuide of the UIScrollView. At this point, I have an error in interface Builder, which is: Scrollview needs constraint for Y position. After that, in IB, I position constraints of all the fields in the contentView. I still have the layout error in Interface Builder. Some posts say that the last subview in contentView as to be pinned to the bottom of the contentView. But I think it is not good, because it will give a height for the content view, or this height depends of the device to be used. So I click on the error in Interface Builder, then on "Add missing constraints", and the new constraint pin the bottom of contentView to bottom of FrameLayoutGuide of the UIScrollView. No error at this point, but if I run under simulator, I have the warning: "LayoutConstraints] Unable to simultaneously satisfy constraints." No Matters, I go on To eventually make the scroll when a UIControl becomes first responder, I write the following in my UIViewController: `class BaseViewController: UIViewController { // visibleRect is the part of the contentView which is visible on screen var visibleRect: CGRect! // scrollOrigin is the initial contentOffset of the scrollview var scrollOrigin: CGPoint! override func viewDidLoad() { super.viewDidLoad() registerKeyboardNotifications() Let kbdGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard(_:))) view.addGestureRecognizer(kbdGestureRecognizer) } func registerKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) } @objc func dismissKeyboard(_ sender: UITapGestureRecognizer) { view.endEditing(true) if let scrollview = scrollview, let scrollOrigin = scrollOrigin { scrollview.setContentOffset(scrollOrigin, animated: true) } } @objc func adjustForKeyboard(notification: Notification) { guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } let keyboardViewEndFrame = view.convert(keyboardValue.cgRectValue, from: view.window) if let scrollview = scrollview { visibleRect = scrollview.subviews[0].frame } else { visibleRect = view.frame } visibleRect.size.height -= keyboardViewEndFrame.size.height }` In adjustForKeyboard function, scrollview.subviews[0].frame as a negative y position. All UIControls are subclassed so that in becomeFirstResponder, it calls the following function of UIViewController: public func currentResponderChange(_ newResponder: UIResponder?) { currentResponder = newResponder if let scrollview = scrollview, let currentResponder = currentResponder as? UIView, currentResponder.isFirstResponder, let view = controllerView { if scrollOrigin == nil { scrollOrigin = scrollview.contentOffset } var frameConverted = view.convert(currentResponder.frame, from: view.window) // si le scroll est uniquement vertical, on met x à zéro frameConverted.origin.x = 0 if let scrollOffset = scrollOrigin { frameConverted.origin.y -= scrollOffset.y } if visibleRect.contains(frameConverted) { if let scrollOrigin = scrollOrigin { scrollview.setContentOffset(scrollOrigin, animated: true) } } else { var delta = (currentResponder.frame.origin.y+currentResponder.frame.size.height) - visibleRect.size.height //- scrollview.contentOffset.y if let scrollOrigin = scrollOrigin { delta -= scrollOrigin.y } scrollview.setContentOffset(CGPoint(x: 0, y: delta), animated: true) } } } It don't work, because of the visibleRect, which is not correct. And I think it comes from initial layout in Interface Builder. the view is effectively scrolled, but not for the correct amount Can someone helps?
2
0
1k
Aug ’22
focused modifier
I'm trying to make a custom TextField which eventually show errors when loosing focus in a normal form, foreach TextField, I write: TextField(label, text: $text) .focused($checkoutInFocus, equals: <some Value>) Text(textError) .foregroundColor(.red) .frame(height: textError == "" ? 0 : 20) (I want to precise it's not all: I have many modifiers for the TextField and it becomes very difficult to read when there are many TextFields) So I thought it would be a good idea to make a special view for each Textfield: struct TextFieldWithError: View { var label: String @Binding var text: String @Binding var textError: String @FocusState.Binding var isFocused: Bool init(label: String, text: Binding<String>, textError: Binding<String>, isFocused: FocusState<Bool>.Binding) { self.label = label self._text = text self._textError = textError self._isFocused = isFocused } var body: some View { TextField(label, text: $text) .modifier(TextFieldStyle()) .focused($isFocused) Text(textError) .foregroundColor(.red) .frame(height: textError == "" ? 0 : 20) } } My problem is that I don't find the way to act on the focusState. In the mainView I write: TextFieldWithError(label: "Email", text: $email, textError: $emailError, isFocused: checkoutInFocus == .<some Value>) in place of the modifier .focused($checkoutInFocus, equals: .email) but the syntax is obviously not good: I get the error: Cannot convert value of type 'Bool' to expected argument type 'FocusState.Binding' Do you think there is a way?
3
0
1.6k
Jun ’23
Xcode 15.2 and Developper App Certificate
I develop an App for Mac and iPhone, and till now, I had no issue to test it on my iPhone. but this morning, I have the following message, when I try to run it on my iPhone: Failed to verify code signature .... (A valid provisioning profile for this executable was not found.) Verify that the Developer App certificate for your account is trusted on your device. Open Settings on the device and navigate to General -&gt; VPN &amp; Device Management, then select your Developer App certificate to trust it. I must precise that it works on the simulator. the version of Xcode is 15.2 and the version of iPhone is 17.2.1 when I go on Settings/VPN -&gt; Device Management (on iPhone), I don't see any section for Developper App Certificate when I go to Devices and Simulators on Xcode, and list the Provisioning Profiles installed on my iPhone, I see the IOS Team Provisioning Profiled of my application but it still not work. What can I do?
3
0
1.5k
Jan ’24