I'm working on an iPad app, and I am unable to hide the UIKeyboardAssistantBar, the bar shown above the soft keyboard, with text prediction etc. See picture below, which shows the full keyboard, just to give a reference - the bar I want to hide is above the keyboard (the one displaying "2")
The problem I have is when an external keyboard is used: the soft keyboard is not shown when a text view obtains the focus, but that assistant bar is always shown instead - the only way I've found so far is to let the user manually hide it, using the icon at the far right.
Ideally, the solution I'm looking for is a global call that enables or disables that, so that I don't have to handle that individually for each text view.
Any idea?
There is a trick that you can try. Here is the code:
let item = self.yourTextView.inputAssistantItem;
item.leadingBarButtonGroups = [];
item.trailingBarButtonGroups = [];
The accepted solution will hide the leading and trailing BarButtonGroups on the keyboard, however unfortunately it will not hide the suggestion/auto correct bar (the center buttons with the suggested "2".
My need was for an iPad native app that required an HTML login page using a WKWebView to render the HTML login page. To hide the suggestion buttons, I used some injected javascript because I had no control over the HTML login page. Swift 3 code below creates the WKWebView (replaces the view object and injects the userScript into the page):
var webView: WKWebView!
override func loadView() {
let autocorrectJavaScript = "var inputTextElement = document.getElementById('userName');"
+ " if (inputTextElement != null) {"
+ " var autocorrectAttribute = document.createAttribute('autocorrect');"
+ " autocorrectAttribute.value = 'off';"
+ " inputTextElement.setAttributeNode(autocorrectAttribute);"
+ " }"
let userScript = WKUserScript(source: autocorrectJavaScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
let webConfiguration = WKWebViewConfiguration()
webConfiguration.userContentController.addUserScript(userScript)
webView = WKWebView(frame: .zero, configuration: webConfiguration)
view = webView
}
Actually, here is a method that works, even with contenteditable enabled:
func findKeyboardAssistantView() -> UIView? {
let result: UIView? = nil
let windows = UIApplication.shared.windows
let prefixes = [
"<UIInputSetContainerView",
"<UIInputSetHostView",
"<_UIKBCompatInputView",
"<UIKeyboardAutomatic",
"<UIKeyboardImpl",
]
for window in windows {
if window.description.hasPrefix("<UIRemoteKeyboardWindow") {
var last = window.subviews
for p in prefixes {
for s in last {
if s.description.hasPrefix(p) {
last = s.subviews
}
}
}
for s in last {
if s.description.hasPrefix("<UIKeyboardAssistantBar") {
return s
}
}
break
}
}
return result
}
findKeyboardAssistantView()?.isHidden = true
Note that it has to be fired when UIResponder.keyboardWillShowNotification is sent
Related
I implemented live text on images with the following code
let config = ImageAnalyzer.Configuration([.text, .machineReadableCode])
Task {
do {
let analysis = try await analyzer.analyze(image, configuration: config)
interaction.analysis = analysis
interaction.preferredInteractionTypes = .automatic
} catch {
}
}
I am able to select text, but I'm not able to do much after that. I would like to be able to get the selected text along with the position of the selected text relative to the image. How would I do that?
I have an iOS app where I can display html and pdf-files. I try to implement a find-in-page functionality which is available since iOS14 (find(_:configuration:completionHandler:)).
Here is my implementation:
private func searchInPage(forward: Bool) {
ktWebView.select(nil)
searchIsAtTop = false
searchIsAtEnd = false
let searchConfig = WKFindConfiguration()
searchConfig.backwards = !forward
searchConfig.caseSensitive = false
searchConfig.wraps = false
ktWebView.find(searchString, configuration: searchConfig, completionHandler: { result in
// https://stackoverflow.com/questions/64193691/ios-wkwebview-findstring-not-selecting-and-scrolling
guard result.matchFound else {
if forward { searchIsAtEnd = true }
else { searchIsAtTop = true }
return
}
ktWebView.evaluateJavaScript("window.getSelection().getRangeAt(0).getBoundingClientRect().top") { offset, _ in
guard let offset = offset as? CGFloat else { return }
ktWebView.scrollView.scrollRectToVisible(
.init(x: 0, y: offset + ktWebView.scrollView.contentOffset.y,
width: 100, height: 100), animated: true)
}
})
}
With each invocation of this function the next occurrence of the searchString will be highlighted and scrolled to.
This works fine as long as the mime type of the WKWebView content is text/html. When it is application/pdf it doesn't work.
Can anyone help me with a solution to find a string in a pdf document displayed in a WKWebView?
Thanks, Clemens
I have no clue how to approach this problem. Any help is appreciated.
It working for text files, maybe need to copy text from PDF and render it as a text / string, found some example:
Can't copy text from PDF which created with iOS Swift
I've solved it now by using PDFView for pdf files instead of WKWebView.
A sample exemplary implementation you may find at https://github.com/cs-LA/FindInPDF.
Thanks for all your efforts to help me with this problem,
Clemens
Are you sure your PDF file has text,
maybe it was converted from text to vector!
Using swift 4 and IOS 12 ,i am using a webViewKit to load a website. One of the features of the web app is to scan qrcode, i have successfully loaded the website but i am still struggling how to access the device camera to scan qr code, in android everything works fine including this qr code scanner using webView onPermissionRequest method. I have already tried this
Key : Privacy - Camera Usage Description in info.plist
and also adding these lines of codes here AVCaptureDevice.authorizationStatus(for: .video) on url load before pressing the web button to scan qr code. According to our web developer this button press executes a javascript undefined function, but i don't know how to make webViewKit respond to this button click event and the hardest part is that there are no logs or NSLogs to evaluate. I am new to IOS development for about almost a month. Thank you
var WebCodeCamJS = function(element) {
'use strict';
this.Version = {
name: 'WebCodeCamJS',
version: '2.7.0',
author: 'Tóth András',
};
var mediaDevices = window.navigator.mediaDevices;
mediaDevices.getUserMedia = function(c) {
return new Promise(function(y, n) {
(window.navigator.getUserMedia || window.navigator.mozGetUserMedia || window.navigator.webkitGetUserMedia).call(navigator, c, y, n);
});
}
HTMLVideoElement.prototype.streamSrc = ('srcObject' in HTMLVideoElement.prototype) ? function(stream) {
this.srcObject = !!stream ? stream : null;
} : function(stream) {
if (!!stream) {
this.src = (window.URL || window.webkitURL).createObjectURL(stream);
} else {
this.removeAttribute('src');
}
};
Above code is a js function named webcodecamjs.js that is being executed from a button click event on the web page. I found similar problem with solution here , but i'm not quite sure how to implement it, it says
Now Add JS file (WebRTC.js) that defines various WebRTC classes, functions & passes the calls to the WKWebView.
In the WKWebView inject the script at the document start:
where do i put this WebRTC.js file? what i did was to create a new file in my ios project and named it WebRTC.js , i also tried renaming it to webcodecamjs.js like what we have in web js files, how i did it in func viewDidAppear
let contentController = WKUserContentController()
contentController.add(self, name: "callbackHandler")
let script = try! String(contentsOf: Bundle.main.url(forResource: "webcodecamjs", withExtension: "js")!, encoding: String.Encoding.utf8)
contentController.addUserScript(WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true))
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
configuration.userContentController = contentController
configuration.allowsPictureInPictureMediaPlayback = true
webView.navigationDelegate = self
webView.configuration.preferences = configuration.preferences
WKWebView.load(webView)(NSURLRequest(url: NSURL(string: encodedLoginUrl)! as URL) as URLRequest)
webView is a
#IBOutlet weak var webView: WKWebView
not declared as below
var webView: WKWebView
that's why i can't do something like below, cause it gives me 'weak' warning
webView = WKWebView(frame: CGRect.zero, configuration: config)
Could you add code snippet to check?
I am trying to show a website through a WKWebView.
My problem is that I don't want to show the navigationBar of the WebSite.
It looks like I have to use webview.evaluateJavaScript but is there an other way of doing it. If NO, can you provide an example with webview.evaluateJavaScript
Thanks
Looking a bit online, I found that on the particular website you can check for navigator.userAgent.
Then I could use the following that helped me remove the content that I want
webView.evaluateJavaScript("navigator.userAgent") { [weak webView] (result, error) in
if let webView = webView, let userAgent = result as? String {
webView.customUserAgent = userAgent + "/_app_"
}
}
I have a viewcontroller which has a webview attached to it. I wan't to mirror it to external screen connected to ipad. I am able to create new window and show images and all, but here i want the exact mirroring of UIWebview (all taps, links, textfield input in web page, video) on secondary display.
func initiateTheExternalDisplay() {
guard UIScreen.screens.count > 1 else {
return
}
let externalScreen = UIScreen.screens[1]
let externalWindow = UIWindow(frame: externalScreen.bounds)
self.externalSecondaryWindow = externalWindow
let roortVc = ExternalPresentationViewController() // this contains view to be shown
self.externalPresentationViewController = rootVc
externalWindow.rootViewController = rootVc
externalWindow.screen = externalScreen
externalWindow.isHidden = false
externalWindow.makeKeyAndVisible()
}
This is how i am instantiating the secondary display and is working fine. Suppose same class is showing the webview, can anyone suggest what info should i pass from here (or alternate way) to achieve mirroring.
I couldn't find any way to do so, so I used a work around. I taking screenshots of the web view controller and updating the secondary view at around 20fps, so it lags a bit but at least able to see the same interaction in almost rela time.