iOS 16 Lock-screen Widget: can we add a deep link to the widget - ios16

I want the user to be able to tap on a lock-screen widget created by my app and deep link to my main app (eg, so that my main app can take some action)
I have been able to do this with Home Widgets, but the same method does not work with the Lock Screen widgets in iOS 16.
Is this possible?
Here is a code that works for Home Widgets:
Link(destination: myActionURL) {
Image("my_image").resizable(capInsets: EdgeInsets(), resizingMode: .stretch)

I was able to do this using widgetURL. In the app delegate catch the url using func applicationHandle(url: URL) and do the action based on the url.
VStack(spacing: 0) {
Text("\(String(carName))").font(.system(size: 10)).fontWeight(.bold).minimumScaleFactor(0.4)
Image("action").resizable(capInsets: EdgeInsets(), resizingMode: .stretch)
.aspectRatio(contentMode: .fit).foregroundColor(entry.widgetTextColor)
}
.widgetURL(url)

It is my understanding that lock screen widgets are not interactive. They’re meant to show glanceable content from your app, not have tappable elements.
If you find out anything that contradicts this, I would love to hear it as I also wish to have them be tappable.

Related

SDWebImageSwiftUI - Image Loading and Caching

I'm working on developing an image heavy iOS app:
Users upload images to the app, all of which are then added to a cloud storage bucket. A database entry is also created, which contains the url to the image's location in the cloud storage bucket.
The SDWebImageSwiftUI framework is used to load the user's images (that are in the cloud storage bucket) into the app and display them.
When a user signs into their account or when a user launches the app and they are already authenticated, a "loading" screen appears while the rest of their account information is retrieved from a database. Part of the information that is collected from the database includes a url to each of the user's uploaded images. Once the app receives these urls (and while the "loading" screen is still on display), I load in the images. Once all the information has been received from the database and once all the images are preloaded, the "loading" screen disappears, taking the user into the app, where the images are displayed right away. I set it up this way so that when the user is taken into the "normal" app screens, they don't have to wait again for the images to load and populate into the view. Below you will find the code that I use to preload these images.
import Foundation
import SDWebImageSwiftUI
// used to retrieve and collect all information relating to a user and their account
class SessionStore: ObservableObject {
#Published var user: User?
#Published var collections: [Collection]?
// ...
// called after a user's collections have been retrieved from the database
func preloadImages() {
guard let collections = self.collections else { return }
// each collection object / item has an image associated with it, so iterate through all of the user's collections
for collection in collections {
// load the collection's image
let imageManager = ImageManager(url: URL(string: collection.imageUrl))
imageManager.load()
}
}
}
The SDWebImageSwiftUI framework has caching capabilities, but I am not currently taking advantage of them as I don't feel confident in my understanding of the subject and cannot find much information online. I am hoping that someone will be able to please explain this more in depth to me and potentially give me some recommendations? Some of my questions are detailed below:
Should I use a cache in my app since it so heavily relies on images?
How can I set up and use SDWebImageSwiftUI's cache systems? What are some good guidelines / principles for configuring a cache system (i.e., memory and disk size)?
When does a SDWebImageSwiftUI cache system reset, if ever?
If I add a cache system, would that help images load faster? Would I be able to remove the image "preloading" functionality I detailed above?
Additionally, I've noticed that if the app moves to the background and then later reenters the foreground, the images are being reloaded. So any images that were being displayed on the user's last screen, temporarily disappear when the app first opens back up. In this case, the "preloading" functionality that I detailed above is not triggered to run. Rather, the images are loaded in due to their presence in the view (see below code), meaning that only the images on the one screen are loaded back in. If I then navigate to another app screen, the images again won't be preloaded and will load as / if they are presented in the view.
import SwiftUI
import SDWebImageSwiftUI
struct ExampleView: View {
#EnvironmentObject var session: SessionStore
let threeColumnGrid = [GridItem(.fixed(UIScreen.main.bounds.width * 0.28)), GridItem(.fixed(UIScreen.main.bounds.width * 0.28)), GridItem(.fixed(UIScreen.main.bounds.width * 0.28))]
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
LazyVGrid(columns: threeColumnGrid, alignment: .center, spacing: 10) {
ForEach(session.collections ?? [], id: \.collectionId) { (collectionItem) in
// when the app enters the foreground after being in the background, the images are no longer preloaded into the app
// so instead of seeing an image displayed within a rounded rectangle (as expected), the user will see an empty rounded rectangle as the image reloads
// the following line is what seems to be triggering the image to be loaded again
WebImage(url: URL(string: collectionItem.imageUrl))
.resizable()
.scaledToFit()
.padding(.vertical, 5)
.padding(.horizontal, 10)
.frame(width: UIScreen.main.bounds.width * 0.28, height: UIScreen.main.bounds.height * 0.22)
.background(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.black.opacity(0.5), lineWidth: 1)
)
} // ForEach
} // LazyVGrid
.padding(.top, 2)
} // ScrollView
}
}
I am also wondering if a cache would help resolve these image "loading lags" when the app renters the foreground? As I believe the cache would have a loaded version of the image, which can be accessed and displayed quicker?
Any knowledge on SDWebImageSwiftUI's caching capabilities, would be greatly appreciated!

Disable autocorrect on an iOS 15 SwiftUI searchable search bar

I have a SwiftUI and Core Data app and have implemented the new iOS 15 search bar API.
.searchable(text: $searchText) // This is a modifier under my List view
However, the search bar has autocorrect, which unexpectedly changes the search when the view disappears or the user commits (it even happens if navigating to a detail view and back). Overall it is a poor user experience.
I cannot find anything in the Apple documentation for disabling autocorrect on this search bar (although it is easily done for a standard TextField with the .disableAutocorrect(true) modifier).
I used a Swift Package for iOS14 that provided a search bar (via UIViewRepresentable), but I would rather use first party APIs if possible, so my question relates specifically to the iOS 15 SwiftUI .searchable API.
The auto correction of the search bar get disabled if you set disableAutocorrection(true) after .searchable(text: $searchText)
List {
//
}
.searchable(text: $searchText)
.disableAutocorrection(true)
disableAutocorrect will be deprecated in a future iOS update (current version: iOS 16.3). Use autocorrectionDisabled instead:
List {
//
}
.searchable(text: $searchText)
.autocorrectionDisabled(true)

How to add Today Widget Chevron

I am working on an app with a Today Widget extension. I've seen some widgets, including a sample app from Apple, that display a chevron in the top right to take the user to the app. I've looked through the documentation and sample code and can't figure out how this is added.
The sample app that's downloaded from here has it, but there isn't any information about how to enable it. https://developer.apple.com/documentation/notificationcenter/building_a_simple_widget_for_the_today_view
Does anyone know how to enable this?
You can add the chevron button to your widget by setting the widgetLargestAvailableDisplayMode of your extension context to .expanded:
extensionContext?.widgetLargestAvailableDisplayMode = .expanded
(Note that the chevron button does not take you to the app, but rather it toggles between expanded/compact sizes of your widget.)

WebView qml doesn't work correctly on iOS 11

I've a problem, i need to open url inside app, and I used a WebView, but doesn't work correctly.
imported this:
import QtWebView 1.0
my code:
Rectangle{
width: Screen.width
height: Screen.height
color: "Orange"
anchors.fill: parent
z:9999999
WebView {
id: webviewer
anchors.fill: parent
url: "http://www.google.com"
onLoadProgressChanged: {
console.log(webviewer.loadProgress)
}
}
}
and in the .pro file i've put:
QT += webview
And my main.cpp
QtWebView::initialize();
my console.log is printing correctly the load status, but on the screen I don't see nothing.
Why?
Works on iOS, the solution is:
Open project in Xcode from build folder, and set App Transport Security Settings, you must add Allow Arbitrary Loads and sets it on YES.
Now the WebView works.
initialize() creates opengl surface, in this case You must first open parent window(surface to display) , other solution is to comment initialize() - page will show. If you'll decide to show it on GL surface, try to se ALWAYSSTACKONTOP attribute to see, if other windows dont cover webview, opengl is rendered first,so any other background can make it not visible. You may also open webview class parented to other, visible window, but if you will show it fullscreen, it will be flicker a while

How to detect SmartBanner

A smartbanner is apple's direct link to the app store. https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
I am trying to have the smart banner show on the top of the page, content below it, and the nav bar on the bottom. The issue I run into is the smart banner is not counted as part of screen height. If you were to do either:
height: 100%;
screen.innerHeight;
height: 100vh;
or any other typical request for screen height, it ignores the presence of the smart banner and pushes content offscreen by the delta of the smart banner's height.
I am trying to detect if the smart banner is showing on an iOS device to ensure the page fits the window screen regardless of its presence and updates height accordingly. What I've found is that the smart banner shows after the document is ready, and doesn't affect window height. Is there a simple way to detect if the user is being shown the smart banner?
$(document).ready(function() {
heightResize($(".container"));
$(window).resize(function() {
heightResize($(".container"));
$(".container").append("<div class='banner'>this is your dynamically created banner</div>");
$(".container").height($(".container").height()+$(".banner").height());
});
});
function heightResize(element) {
element.height($(window).height()-20);
$("p").text(element.height());
}
Code like this will be pushed off the screen by the smart banner after the page finishes loading.

Resources