Replaced UIWebView with WKWebView, but still same error from Apple - uiwebview

I have removed the UIWebView from my app. But when I uploaded the iOS app on iTunes I still got the same message "Re: ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs"
I have searched for UIWebView globally in the project and there are no search results. That simply means UIWebView is removed.
I have updated the pods too.
I have verified the presence of UIWebView in the app archive using below code:
grep -r "UIWebView" .
The response is
./BCSymbolMaps/F4DBB519-4BC9-3C29-B017-4C0BD603D250.bcsymbolmap:l_OBJC_PROTOCOL_$_UIWebViewDelegate
./BCSymbolMaps/F4DBB519-4BC9-3C29-B017-4C0BD603D250.bcsymbolmap:l_OBJC_LABEL_PROTOCOL_$_UIWebViewDelegate
./BCSymbolMaps/F4DBB519-4BC9-3C29-B017-4C0BD603D250.bcsymbolmap:-[Crashlytics monitorErrorsForUIWebView:]
./BCSymbolMaps/F4DBB519-4BC9-3C29-B017-4C0BD603D250.bcsymbolmap:CLSWebViewIsUIWebViewAlreadyMonitored
./BCSymbolMaps/63FADF77-FD8F-31A1-9B4E-2799F044786E.bcsymbolmap:l_OBJC_PROTOCOL_$_UIWebViewDelegate
./BCSymbolMaps/63FADF77-FD8F-31A1-9B4E-2799F044786E.bcsymbolmap:l_OBJC_LABEL_PROTOCOL_$_UIWebViewDelegate
./BCSymbolMaps/63FADF77-FD8F-31A1-9B4E-2799F044786E.bcsymbolmap:-[Crashlytics monitorErrorsForUIWebView:]
./BCSymbolMaps/63FADF77-FD8F-31A1-9B4E-2799F044786E.bcsymbolmap:CLSWebViewIsUIWebViewAlreadyMonitored
Binary file ./dSYMs/Eureka.framework.dSYM/Contents/Resources/DWARF/Eureka matches
How can I check the code that is still causing the error of UIWebView?

How can I check if the UIWebView is completely removed from the project or not?
Solution is:
Open terminal. Open your project root folder in terminal.
Run Command: grep -r "UIWebView" .
This command will list all the pods that contains “UIWebView”. No either update these pods or remove these pods and ren the step 2 command again. Repeat till all “UIWebView” matches are not removed.
Below are some steps that will guide you to update existing UIWebView to WKWebView.
Import the “WebKit” class to the Controller.
Suppose you are using a UIWebView named “webViewMain”. Then go to your storyboard and simply replace the UIWebView with UIView. Make sure that you have added the same constraints to UIView that were added to UIWebView. Draw #IBOutlet from the new UIView to existing #IBOutlet of UIWebView.
Here you need to change the class of #IBOutlet from UIWebView to UIView because you have replaced the UIWebView with UIView.
Older Code: #IBOutlet weak var webViewMain: UIWebView!
New Code: #IBOutlet weak var webViewMain: UIView!
Then create a new variable to create a new WKWebView.
CODE: var webView : WKWebView!
Add below code where you load request/html in the UIWebView:
// WKWebView
// init and load request in webview.
webView = WKWebView(frame: self.webViewMain.frame)
webView.navigationDelegate = self
self.webView.load(request)
self.webViewMain.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
// Adding constraints from webView(WKWebView) to webViewMain (UIView)
webView.leadingAnchor.constraint(equalTo: webViewMain.leadingAnchor, constant: 0).isActive = true
webView.trailingAnchor.constraint(equalTo: webViewMain.trailingAnchor, constant: 0).isActive = true
webView.topAnchor.constraint(equalTo: webViewMain.topAnchor, constant: 0).isActive = true
webView.bottomAnchor.constraint(equalTo: webViewMain.bottomAnchor, constant: 0).isActive = true
// WKWebView
Till now you have replaced UIWebView with WKWebView .
Now comes the delegate methods.
UIWebView has delegate class: UIWebViewDelegate
WKWebView has delegate class: WKNavigationDelegate
Replace UIWebViewDelegate with WKNavigationDelegate.
Now comes delegate method comparison for UIWebView vs WKWebView:
UIWebView: func webViewDidFinishLoad(_ webView: UIWebView)
WKWebView: func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
UIWebView: func webViewDidStartLoad(_ webView: UIWebView)
WKWebView: func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)
UIWebView: func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool
Here we return true/false to load/cancel the navigation.
WKWebView: func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void)
Here we returndecisionHandler(.allow)/decisionHandler(.cancel) to load/cancel the navigation.
To Scale aspect fit content of the webView (WKWebView).
var scriptContent = "var meta = document.createElement('meta');"
scriptContent += "meta.name='viewport';"
scriptContent += "meta.content='width=device-width';"
scriptContent += "document.getElementsByTagName('head')[0].appendChild(meta);"
webView.evaluateJavaScript(scriptContent, completionHandler: nil)
To set the height of the webView:
webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
if complete != nil {
self.webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
self.constraintWebViewProductDescriptionHeight.constant = height as! CGFloat
})
}
})

Related

Display PDF in Vaadin version 14+

What is the best way to display PDF file in Vaadin 14? i want to display a pdf file in a dialog, but i'm not sure how to render the pdf files. I saw some post about embedded pdf view,pdf browser and EmbeddedPdfDocument, but i can't tell if they are compatible with 14 or not.Is there a new method to do this?
There is a third party addon to render a PDF in Vaadin 14.
Your can find it here: https://vaadin.com/directory/component/pdf-browser/
That gives you the possibility to render a pdf with this code:
StreamResource streamResource = new StreamResource(
"report.pdf", () -> getClass().getResourceAsStream("/report.pdf")); // file in src/main/resources/
PdfBrowserViewer viewer = new PdfBrowserViewer(streamResource);
viewer.setHeight("100%");
layout.add(viewer);
Alternatively you can do it in same way as it was commonly done in previous Vaadin framework versions, embedding in IFrame (see Show PDF in a Vaadin View ), which could look something like this
StreamResource streamResource = new StreamResource(
getPresenter().createPdfStreamSource(), report.getName() + ".pdf");
StreamRegistration registration = VaadinSession.getCurrent().getResourceRegistry().registerResource(resource);
IFrame iframe = new IFrame(registration.getResourceUri().toString());
iframe.setHEight("100%");
layout.add(iframe);
To do it in Vaadin Flow (without an addon) and in a dialog as requested, I'd like to present the following code for your dialog which can be called like any other class. I had to tweak Jean-Christophe his answer a bit.
public class ManualDialog extends Dialog {
private IFrame iFrame;
private final String fileName = "fileNameAsFoundUnderYourResourceMap";
public ManualDialog() {
this.setHeight("calc(100vh - (2*var(--lumo-space-m)))");
this.setWidth("calc(100vw - (4*var(--lumo-space-m)))");
buildLayout();
}
private void buildLayout() {
// HEADER
HorizontalLayout header = new HorizontalLayout();
header.setMaxHeight("1em");
header.setAlignItems(FlexComponent.Alignment.CENTER);
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
header.getStyle().set("margin-top", "-1em");
Span caption = new Span(getTranslation("main.download.manual"));
caption.getStyle().set("color", "black");
caption.getStyle().set("font-weight", "bold");
Icon closeIcon = new Icon(VaadinIcon.CLOSE);
closeIcon.setColor(GENERIC_BUTTON_COLOR.getDescription());
Button closeButton = new Button();
closeButton.setIcon(closeIcon);
closeButton.getStyle().set("border", "none");
closeButton.getStyle().set("background", "transparent");
closeButton.addClickListener(click -> this.close());
header.add(caption, closeButton);
this.add(header);
// PDF-VIEW
iFrame = new IFrame();
iFrame.setSizeFull();
StreamResource resource = new StreamResource(fileName, () -> new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(fileName)));
StreamRegistration registration = VaadinSession.getCurrent().getResourceRegistry().registerResource(resource);
iFrame.setSrc(registration.getResourceUri().toString());
this.add(iFrame);
this.open();
}
}

How to adjust webpage view using wkwebview

I am loading a url to wkwebview and i want to keep it from viewing a side of the webpage like this
https://drive.google.com/file/d/1qStJ1C_rrcjobSuorgPeLTkHZc82oUV4/view?usp=sharing
instead of
https://drive.google.com/file/d/1G05f6UVolmQCqdqKdJ0UFBBA6LVDI-BN/view?usp=sharing
Scrollview is already false and bounces are false too. Can someone help me
Thanks!
I have already tried using the scrollview and bounces parameters but the wkwebview still moves to the left exposing the blue part shown in the images. I want to display the webpage as shown in the first image so that its, for lack of a better word, view is locked as displayed. I'm not sure if I am explaining myself good, but let me know if I need to explain. I have added a video below showing what I want to know how to do.
https://drive.google.com/file/d/1uErGQlB1HKLU7px49UtGbsX9nOYqa3FN/view?usp=sharing
import Foundation
import UIKit
import WebKit
class ViewControllerWebKit: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
webView.scrollView.bounces = false
let myURL = URL(string:"https://www.swpc.noaa.gov/communities/space-weather-enthusiasts")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}}
As shown in the photos and video, I don't know how to keep it from moving so it doesn't show the blue side which is part of the webpage.
If you want to stop the page from being scrolled to the side, the width in the html that you are showing should be equal to device-width. you can do so by defining the viewport. The thing is that your page has the blue bar in the right so either way I think you have to show it.
This solution will stop the scrolling behavior, but the bar will still be showing as it is part of the page.
override func viewDidLoad() {
super.viewDidLoad()
let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jscript, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let wkUController = WKUserContentController()
wkUController.addUserScript(userScript)
let webConfiguration = WKWebViewConfiguration()
webConfiguration.userContentController = wkUController
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
webView.scrollView.bounces = false
let myURL = URL(string:"https://www.swpc.noaa.gov/communities/space-weather-enthusiasts")
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
Hope this could help.

MFSideMenu in UINavigationController not working when introduced with a modal Segue

I'm trying to integrate MFSideMenu in my project but I don't want to adopt the approach described in the GitHub depository as it defines the menu in the app delegate.
I have a login screen which will introduce a navigation controller with the main page as reported in this picture
I would like to add the support for MFSideMenu in the navigationcontroller root controller using this code:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// Custom initialization
self.sideMenuController = [[SideMenuViewController alloc] init];
UINavigationController *navigationController = self.navigationController;
MFSideMenuOptions options = MFSideMenuOptionMenuButtonEnabled|MFSideMenuOptionBackButtonEnabled
|MFSideMenuOptionShadowEnabled;
MFSideMenuPanMode panMode = MFSideMenuPanModeNavigationBar|MFSideMenuPanModeNavigationController;
MFSideMenu *sideMenu = [MFSideMenu menuWithNavigationController:navigationController
sideMenuController:sideMenuController
location:MFSideMenuLocationLeft
options:options
panMode:panMode];
sideMenuController.sideMenu = sideMenu;
}
return self;
}
When I run the app the menu button appears in my navigation bar and everything seems working fine but,if I introduce the navigation controller through a modal segue (i.e. a login screen which goes to the navigation controller in case of a correct login) the button disappears.
Any idea about how to fix it?

Can WatiN handle the CuteWebUI Uploader popup dialog?

My Background:
I am new to WatiN, but not new to writing automated Web UI tests. At my new job, we are trying to use WatiN for our Web UI tests (thanks to a few CUIT fails).
I've solved this problem in the past using ArtOfTest.WebAii, by using a Win32 mouse click with a magic number offset from the containing element, but I can't seem to find documentation on how to do that in WatiN and I can't figure it out myself :\
My problem:
This dialog appears and I can't seem to find a way for WatiN to click it.
The dialog has the following markup:
<OBJECT style="FILTER: alpha(opacity=1); WIDTH: 329px; HEIGHT: 100px; mozOpacity: 0.01; opacity: 0.01; mozopacity: 0.01" data="data:application/x-oleobject;base64, <a bunch of data>" width=329 height=100 type=application/x-silverlight-2></OBJECT>
<param name="source" value="/CuteWebUI_Uploader_Resource.axd?type=file&file=silverlight.xap&_ver=634334311861475176"/>
<param name="windowless" value="true" object="" <=""/>
my test code:
[TestMethod]
public void SomeTest()
{
Settings.MakeNewIeInstanceVisible = true;
Settings.AutoStartDialogWatcher = true;
Settings.AutoMoveMousePointerToTopLeft = false;
using (IE ie2 = new IE())
{
ie2.GoTo(URL);
ie2.Link(SomeButtonID).Click();
ie2.Image(AnotherButtonID).FireEvent("onclick");
// some debugging code wrapped around the next user action
// which is clicking on the attach file button
var helper = new DialogHandlerHelper();
using (new UseDialogOnce(ie2.DialogWatcher, helper))
{
Thread.Sleep(1 * 1000); // wait for attach button to be "ready"
// Click button that triggers the dialog that states:
// "file browsing dialog has been blocked"
// "please click here and try again"
//
ie2.Button(FileAttachButtonID).FireEvent("onclick");
}
foreach(string dialogHandler in helper.CandidateDialogHandlers)
{
// nothing prints out here :(
Console.Out.WriteLine(dialogHandler);
}
// debug print out all elements with tagname = object
foreach (Element objectElement in ie2.ElementsWithTag("object"))
{
StringBuilder elementInfo = new StringBuilder();
elementInfo.AppendLine("--------------------------------------------");
elementInfo.AppendLine("element.tagname = " + objectElement.TagName);
elementInfo.AppendLine("element.style = " + objectElement.Style);
elementInfo.AppendLine("element.type = " + objectElement.GetAttributeValue("type"));
elementInfo.AppendLine("element.data = " + objectElement.GetAttributeValue("data"));
elementInfo.AppendLine("--------------------------------------------");
Console.Out.WriteLine(elementInfo.ToString());
// none of these clicks make the dialog go away
objectElement.ClickNoWait();
objectElement.Click();
objectElement.DoubleClick();
objectElement.MouseEnter();
objectElement.MouseDown();
Thread.Sleep(500);
objectElement.MouseUp();
}
// wait to see if dialog disappears after click
Thread.Sleep(300 * 1000);
}
}
Any and all help will be very much appreciated.
Thanks!
Your control is a silverlight component which can't be automated with WatiN. Fortunately this you can combine WatiN and White to get the job done.
Following code is created and published by Leo Bartnik so ALL the credits go to him! Have a look at his blog post here. The following code in the comments:
He used the following versions.
watin-2.0.50.1179.zip from 2011-02-08 http://sourceforge.net/projects/watin/files/WatiN%202.x/2.0%20Final/
white 0.20 Binaries http://white.codeplex.com/releases/view/29694
public void WatiN_and_White_join_forces()
{
// Navigate to your webpage with WatiN
string url = "http://localhost[port#]/WatinWhiteTestLandingPage.aspx";
WatiN.Core.IE watin = new WatiN.Core.IE(url);
watin.Link(Find.ByText("click here)).Click();
// Attach the IE instance used by WatiN to White
InternetExplorerFactory.Plugin();
string title = "[browser title here]"; // will be something like "WatinWhiteHybrid - Internet Explorer provided by ..."
var ie = (InternetExplorerWindow)Application.Attach(watin.ProcessID).GetWindow(title);
White.WebBrowser.Silverlight.SilverlightDocument sl = ie.SilverlightDocument;
// Click the button in the silverlight control using White
sl.Get(SearchCriteria.ByAutomationId("ClickMeId")).Click();
}
btw don't know why the formating of this code is so way off....
So this was my hack solution:
Use Microsoft's Coded UI Test to click on the Silverlight dialog. However, CUIT is inferior to WatiN, so I run my test in WatiN and load CUIT for one, magical, click.
Additionally, I was not able to easily find the Silverlight object using CUIT, so I find the window behind it, find the window's center pixel and force a Microsoft.VisualStudio.TestTools.UITesting.Mouse.Click(). Yes, a hack inside of a hack, I am a very bad person, but I ran out of time and just needed something working.
If anyone has a more elegant solution, please share.
My solution code:
FileUploadDialogHandler helper = new FileUploadDialogHandler(attachmentPath);
using (new UseDialogOnce(ie.DialogWatcher, helper))
{
Thread.Sleep(1 * 1000); // wait for attach button to be "ready"
ie.Button(browseButtonID).FireEvent("onclick");
// When automating a file upload, there is a Silverlight popup in IE that forces an extra click
// before opening the file open dialog. WatiN does not support Silverlight automation
// and the popup element was acting quirky in Microsoft's Coded UI Test, so we find the
// dialog box UNDERNEATH the Silverlight popup and force one, lovely, mouse click.
//===== Entering Coded UI Test land, beware! =====================================
// initialize Coded UI Test
Playback.Initialize();
BrowserWindow.CurrentBrowser = "IE";
Process watinBrowserProcess = Process.GetProcessById(ie.ProcessID);
BrowserWindow cuitBrowser = BrowserWindow.FromProcess(watinBrowserProcess); // attach Coded UI Test to the IE browser WatiN initialized
// get the window underneath the Silverlight popup
UITestControl modalUnderSilverlightPopup = new UITestControl(cuitBrowser.CurrentDocumentWindow);
modalUnderSilverlightPopup.SearchProperties.Add("id", windowElementUnderPopupID);
// get the X and Y pixel center of the window
int centerX = modalUnderSilverlightPopup.BoundingRectangle.X + modalUnderSilverlightPopup.BoundingRectangle.Width / 2;
int centerY = modalUnderSilverlightPopup.BoundingRectangle.Y + modalUnderSilverlightPopup.BoundingRectangle.Height / 2;
// Click!
Mouse.Click(new Point(centerX, centerY));
// Shutdown Coded UI Test
Playback.Cleanup();
//===== End Coded UI Test land, you survived! yay! ============================
}

iPad - find the true height of a UIWebView

I work for a media company, and in our iPad application we're upgrading our content so it looks better. Previously, we used a UILabel to display the contents of our posts. I used this to get the actual height of my UILabel:
CGSize expectedSize = [label.text sizeWithFont:label.font
constrainedToSize:maximumLabelSize lineBreakMode:label.lineBreakMode];
However, we changed our posts' content to HTML, so I'm using a UIWebView. Is there a way to find the true height of the UIWebView, like I do with the UILabel?
Unlike with a plain string, you'll probably only be able to get the height once the web view finishes rendering. Here's how you can do it in a web view delegate method:
- (void)webViewDidFinishLoad:(UIWebView *)webview
{
NSString *heightString = [webview stringByEvaluatingJavaScriptFromString:
#"document.body.clientHeight"];
int height = [heightString intValue];
...
}

Resources