SwiftUI: Is it possible to turn off predictive text for a TextField - textfield

I would like to turn off predictive text/autocorrect for a TextField in SwiftUI. Looks like this was possible in with UITextField:
Disable UITextField Predictive Text
I checked the Apple documentation for TextField and googled, but can't find anything about this.
Has anyone found a way to disable the predictive text/autocomplete for a TextField?
Thank you!

Seems like it is now possible using Xcode 11 Beta 5. There is a new modifier to disable the autocorrection on TextField
func disableAutocorrection(_ disable: Bool?) -> some View
https://developer.apple.com/documentation/swiftui/textfield/3367734-disableautocorrection?changes=latest_beta
Edit:
Modifier disableAutocorrection is deprecated in iOS 16.1. The new modifier is autocorrectionDisabled:
func autocorrectionDisabled(_ disable: Bool = true) -> some View
https://developer.apple.com/documentation/swiftui/presentedwindowcontent/autocorrectiondisabled(_:)?changes=latest_beta&language=_5

This should work:
.disableAutocorrection(true)

Turns out you need to set the keyboard type to .alphabet for .disableAutocorrection(true) to work.
here is the extension I use:
extension View {
func removePredictiveSuggestions() -> some View {
self.keyboardType(.alphabet)
.disableAutocorrection(true)
}
}

Xcode 12.3 Swift 5.3
If you need to disable autocorrection on multiple TextFields, or indeed add other modifiers, then create a custom TextField:
struct TextFieldCustom: View {
let title: String
let text: Binding<String>
init(_ title: String, text: Binding<String>) {
self.title = title
self.text = text
}
var body: some View {
TextField(title, text: text)
.disableAutocorrection(true)
// add any other modifiers that you want
}
}
Example Usage:
Form {
Section(header: Text("Details")) {
TextFieldCustom("Field1", text: $field1)
TextFieldCustom("Feild2", text: $field2)
TextFieldCustom("Field3", text: $field3)
}
}

For the iOS 16.2 SDK, I needed to do this:
.keyboardType(.alphabet)
.textContentType(.oneTimeCode)
.autocorrectionDisabled(true)
(oneTimePasscode is an old UIKit hack to achieve the same result. It feels dirty to me, and I wouldn't be surprised if this behaviour changes again in the future...)

Related

TTTAttributedLabel clickable link does not work in Swift 3

I just upgraded to Swift 3. I created a TTTAttributedLabel with a clickable URL, unfortunately the delegate function does not work anymore. Anyone has similar problems?
func attributedLabel(_ label: TTTAttributedLabel!, didSelectLinkWith url: URL!) {
}
Did you remember to connect the delegate?
label.delegate = self
It is working for me
extension YourViewController: TTTAttributedLabelDelegate {
func attributedLabel(_ label: TTTAttributedLabel!, didSelectLinkWith url: URL!) {
UIApplication.shared.openURL(url)
}
}

tvOS UICollectionView get currently focused item's index path

So this is kind of a noobish question but I just can't figure out a very simple way to detect currently focused item's indexPath.
I looked around hoping to see something very easy like collectionView.indexPathOfCurrentlyFocusedItem but didn't find anything remotely close.
So I digged around and tried to find something similar at UIFocusEnvironment, UIFocusUpdateContext trying to find the desired property but failed.
So, the only solution I can come up with is just iterating through all visible cells and finding a cell with focused property set to true.
So is there a more simple and elegant way to find the currently focused item's indexPath? (Except tracking it through delegate method and saving it in view controller's property)
You can use UIScreen property focusedView as followed for this:
if let focusedCell = UIScreen.main.focusedView as? UICollectionViewCell {
if let indexPath = collectionView.indexPath(for: focusedCell) {
print("IndexPath is \(indexPath)")
}
}
Use didUpdateFocusInContect - UICollectionViewDelegate
func collectionView(collectionView: UICollectionView, didUpdateFocusInContext context: UICollectionViewFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if collectionView == self.collectionView {
print(context.nextFocusedIndexPath)
}
}
This wil return the indexPath of the cell that is going to be focused, you could also try:
context.previouslyFocusedIndexPath
Depends what you're trying to do.
So, your target is to do something when you get and lose focus particularly on a cell under tvOS. The catch is you're moving around other UI elements, and therefore the context could be different. You have to change in this context only those UIs that you have to care of.
The right place to make your implementation is func didUpdateFocusInContext(), like this:
override func didUpdateFocusInContext(
context: UIFocusUpdateContext,
withAnimationCoordinator coordinator: UIFocusAnimationCoordinator
) {
coordinator.addCoordinatedAnimations({
if let cell = context.previouslyFocusedView as? UICollectionViewCell {
cell.layer.borderWidth = 2
}
if let cell = context.nextFocusedView as? UICollectionViewCell {
cell.layer.borderWidth = 5
}
},
completion: nil)
}
Now we're using the focus coordinator to apply our logic:
When the previously focused item is UICollectionViewCell then you have to release the focus to the next item. You shouldn't care what is the next item because it could be a collection cell or not. For fun, in this case, let's change the border to 2. This value could be set by default.
When the next focused item is UICollectionViewCell then you've to handle it is a similar way, or it will become a mess... So, let's change the border to 5.
As you can see, didUpdateFocusInContext() provides a generic approach for all views within your current visual context. You can apply the same approach for other UI elements.
Have a fun with tvOS...
Here's how I accomplished this in shouldUpdateFocusInContext
Solution
override func shouldUpdateFocusInContext(context: UIFocusUpdateContext) -> Bool {
// The magic is in the next two lines
let cell: UICollectionViewCell = context.nextFocusedView as! UICollectionViewCell
let indexPath: NSIndexPath? = self.collectionView.indexPathForCell(cell)
print(indexPath)
// <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}
return true
}

Dynamically set Label's "id" property

I'm developing an application for SailfishOS using the QML language.
I want to dynamically set the id property of a Label by using an if condition.
This is my code:
Label {
id: {
if(myBool == false) {
thisText()
} else {
notThatText()
}
}
width: parent.width
horizontalAlignment: Text.AlignRight
text: ""
font.pixelSize: Theme.fontSizeLarge
}
This code is placed into my CoverPage.qml file, the one that display things on the application's cover while in background.
By doing this, the cover is simply black, nothing is displayed.
Is it possible in QML to do this?
Thanks in advance!
The Qt doc says this.
While it may look like an ordinary property, the id attribute is not an ordinary property attribute, and special semantics apply to it;
You cannot set the id of a QML component at runtime.(Correct me if I am wrong). You might find objectName property useful. But I don't understand why you are trying to assign dynamic id.
I have a use case where use a dynamic/specific id could be useful. The id could be view with Gammaray, it can help for debugging.
GridLayout {
id: layout
Repeater {
model: foo
Bar {
id: bar_X_Y // bar_{model.row}_{model.column}
}
}
}
But as far as I know, it's not possible.

How to change PreferredStatusBarStyle programmatically

I'd like to change the color of status bar from white to black by press button, programmatically only in a single-ViewController
This is the code:
- (UIStatusBarStyle)preferredStatusBarStyle {
NSLog(#"PreferredStatusBarStyle");
if(nav_bar.alpha==1)
{
NSLog(#"->UIStatusBarStyleBlackOpaque");
return UIStatusBarStyleBlackOpaque;
}
else
{
NSLog(#"->UIStatusBarStyleLightContent");
return UIStatusBarStyleLightContent;
}}
then When I press a button action is:
[self setNeedsStatusBarAppearanceUpdate];
But this doesn't work!
When I press the button log write the correct status according to navbar.alpha, but statusbar text color remain UIStatusBarStyleBlackOpaque like when view appear.
setStatusBarStyle:animated: has been deprecated. In iOS9 you can achieve the same thing using preferredStatusBarStyle and setNeedsStatusBarAppearanceUpdate.
In your View Controller:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
if (condition) {
return .LightContent
}
return .Default
}
And then when your condition changes:
self.setNeedsStatusBarAppearanceUpdate()
On Swift 4:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Hope it helps anybody else to find this post.
what you need to do, is to call the -setStatusBarStyle:animated: method thru the shared application, like this
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
you can use it without the animated parameter as well. keep in mind that UIStatusBarStyleBlackOpaque is deprecated in iOS 7, documentation says you wanna use UIStatusBarStyleLightContent instead
edit:
sorry, if u wanna use preferredStatusBarStyle, take a look at this preferredStatusBarStyle isn't called

QML application launcher similar to iOS

I'm trying to write an application launcher using QtQuick\QML, and I'd like the user experience to be similar to iOS, in terms of having a grid of icons that can be rearranged with icons that "move out of the way" via animated transitions and a "snap to grid" effect if the icon is dropped in an intermediate position. I've tried using GridView and the drag properties, but I can't seem to get the layout do what I want. What would be the best way to implement this type of app using QML? I'm fairly new to QtQuick, and I feel like maybe I'm missing something fundamental that would make this fairly easy\obvious to write.
For putting icons in a grid, you can use the grid view:
http://developer.qt.nokia.com/doc/qt-4.8/qml-gridview.html
Go through the Qt Quick documentation, you will find out how to do this.
This is not directly relevant to implementing the grid of icons, but I recently came across the QML component Loader. This lets you load QML components on demand, and could be useful for the code that launches an app after the icon is selected.
http://doc-snapshot.qt-project.org/5.0/qml-qtquick2-loader.html
I have made Nokia N9 launched look and feel (Maemo 6, or also known as MeeGo).
It is similar, I just scroll from up to down with icons, while you change "pages" from left to right (and vice versa).
I don't know is it best way, but this is how I did icon manager (its shrinked, this is only to give you idea - in reality it is considerably larger):
Item
{
id: root
function getChildAt(x, y) {}
function getIndexOfChild(child) {}
function moveChild(child, x, y)
{
//moving around icons
}
function setIndexToChild(child)
{
//index of child in Grid element (where to drop)
}
Flickable
{
id: scroller
clip: true
//you most likely want HorizontalFlick ("paging" effect you can add on onBeginingXChanged)
flickableDirection: Flickable.VerticalFlick
contentHeight: iconTable.height
contentWidth: iconTable.width
Grid
{
id: iconTable
width: root.width
anchors.top: parent.top
flow: Grid.LeftToRight
spacing: 10
add: Transition
{
NumberAnimation
{
properties: "x,y"
//make desired transition
}
}
move: Transition
{
NumberAnimation
{
properties: "x,y"
//make desired transition
}
}
}
}
}
You could also write down your own implementation of manager in C++ and later on use it in QML.
This is how it looks like:
I created something distantly connected to this recently, the idea is: create a ListView with snapping. Its delegate should contain a GridView. Separate all of the apps into n-element chunks. Then (it's only the idea)
ListModel
{
ListElement { apps: [app1, app2, ..., appn] }
ListElement { apps: [app1, app2, ..., appn] }
....
ListElement { apps: [app1, app2, ..., appk] }
}
Then populate the ListView with this model and the GridView with the apps property.
I don't know whether you can provide drag and drop here, though