Xcode 9.2 - WebView doesn't work - webkit

I'm trying to build a simple webView application for MacOS, but it doesn't seem to work. I've linked the code to the storyboard, imported WebKit, but nothing seems to work. After I finish the build, and try to test it, the window keeps gray. There are no errors involved. Does anyone know what I did wrong?
CODE:
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet var webView: WebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.mainFrame.load(URLRequest(url: URL(string: "http://apple.com")!))
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}

You should be using a WKWebView instead of a WebView. WKWebView replaced WebView in macOS 10.10.
#IBOutlet var webView: WKWebView?
To load a webpage create a URL request with the webpage's URL. Call the web view's load() function to load the webpage with the URL request. The following code should load Apple's website in a WKWebView:
override func viewDidLoad() {
super.viewDidLoad()
loadWebContent()
}
func loadWebContent() {
if let myURL = URL(string: "https://www.apple.com") {
let myRequest = URLRequest(url: myURL)
webView?.load(myRequest)
}
}
One last thing you have to deal with is the app sandbox. Xcode projects initially have the app sandbox turned on. The app sandbox is set initially to disallow any incoming and outgoing network connections. Either allow incoming and outgoing network connections or turn off the sandbox.

Related

Android Webview (Kotlin), camera doesn't open with allowed permission

I have a PWA (a Webview) made with both WebViewClient and WebChromeClient in Kotlin.
The main code of the PWA is this one, where I set all the options for both webview clients:
binding.webView.settings.javaScriptEnabled=true
binding.webView.settings.javaScriptCanOpenWindowsAutomatically=true
binding.webView.settings.domStorageEnabled=true
binding.webView.settings.allowFileAccess=true
binding.webView.webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest) {
request.grant(request.resources)
}
}
binding.webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return false // then it is not handled by default action
}
}
The web page that opens this webview has an option to take pictures with camera.
Have been working for 5 years, and it used to work in an old PWA made with Java, but now in the new one with Kotlin I can't make work the camera.
I had problems with camera permissions but not anymore (I fix that), it ask for camera permissions correctly:
But when I tried to open the camera this is what I get:
But if I open directly on Chrome (on the mobile) it works ok:
so the problem is not on the webpage but in the PWA.
What could be? any hint please

Why my userNotificationCenter didReceive not run when fired

I use UserNotifications make a simple notification for test, I wrote the code in AppDelegate as below, when the notification fired in background, it will shows the message on the screen, but it doesn't run the code both print(...) and a.get()) :
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("run in didReceive")
let a = ViewController()
a.get()
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge, .carPlay], completionHandler: { (granted, error) in
if granted {
print("granted")
}else{
print("not granted")
}
})
UNUserNotificationCenter.current().delegate = self
return true
}
I just only want to run a "viewcontroller" function when the app when in background...
One problem is this line:
let a = ViewController()
You are creating a "loose" view controller and then throwing it away. What you probably want is a reference to some existing view controller that is already in the interface.
A broader problem might be a false assumption about what userNotificationCenter(_:didReceive:withCompletionHandler:) is for. It is not called to indicate that a notification alert appeared (i.e. the notification fired). It is called to indicate that the user interacted with the notification, such as tapping or (if so configured) dismissing the alert. A banner alert that just appears and goes away again, with no user interaction, will not cause userNotificationCenter(_:didReceive:withCompletionHandler:) to be called.

React Native app stuck on blank screen when running on device with remote debugging

I run my react native application on my device (iPhone 6) and it loads fine. But when I enable remote debugging, it seems to connect fine to debugger but gets stuck on a blank screen.
As soon as I turn off remote debugging, everything loads fine.
I am on react-native 0.40.0.
Please help!
There can be many reasons, in my case it was the cache that was creating problem.
Suggested Solutions:-
Clean gradlew
- To clean gradle go to android folder and open cmd in it, run 'gradlew clean' in the cmd
after cleaning gradle, re-build your app run command (run-android etc)
if the problem exist after rebuilding follow step 4 & 5
Go to App's setting and clear App's data
now clear react-native terminal's cache ( react-native start --reset-cache )
These steps will fix the problem!
I overcome this effect by doing the following:
go to the terminal and press "a" to reopen Android device or emulator
close application on mobile device and open it once again
if necessary, restart R to restart packager and clear cache in the terminal
I was facing this same issue when launching a react native module from iOS native module.
Replacing below mentioned code using BUNDLE URL
if let bundleUrl = (UIApplication.shared.delegate as? AppDelegate)?.bridge?.bundleURL {
let mockData:NSDictionary = ["names":
[
["name":"Name 1",],
["name":"Name 2"]
]
]
let rootView = RCTRootView(bundleURL: bundleUrl, moduleName: "modulename", initialProperties: mockData as [NSObject : AnyObject], launchOptions: nil)
let vc = UIViewController()
vc.view = rootView
self.present(vc, animated: true, completion: nil)
with this updated code using BRIDGE
if let bridge = (UIApplication.shared.delegate as? AppDelegate)?.bridge {
let mockData:NSDictionary = ["names":
[
["name":"Name 1",],
["name":"Name 2"]
]
]
let rootView = RCTRootView(bridge: bridge, moduleName: "modulename", initialProperties: mockData as [NSObject : AnyObject])
let vc = UIViewController()
vc.view = rootView
self.present(vc, animated: true, completion: nil)
}
resolve the issues!!

How to make application NOT redirect me when app is running and push notification comes and I am NOT tapping on it

I have an application and PUSHs work fine when the app is on background I tap on push notification and it redirects me - OK.
But here is the situation which i have to fix:
1 step: I open the app, working with it, it is active
2 step: notification comes but user is not seeing anything AND he gets redirected to another ViewController(according to push notification info) UNEXPECTEDLY.
I need the app NOT to redirect anywhere when it is active unless the push notification is actually tapped.
I found a solution!
in didReceiveRemoteNotification method add if statement:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if application.applicationState == .inactive || application.applicationState == .background {
//here add you actions
}
}

How to detect when a React Native app is opened?

My React Native app wants to synchronize its local data with an API when the user opens the app. This should happen whenever the user returns to the app, not just when it first starts. Essentially, what I would like is the equivalent of AppDelegate's applicationDidBecomeActive callback, so that I can run synchronization code there. Obviously, I would like to do this in React Native instead.
As far as I can tell, the componentWillMount / componentDidMount callbacks on the root component only run when the app is initially loaded, not after the user leaves the app and comes back later (without explicitly quitting the app).
I thought that the AppState API would provide this functionality, but its change listeners don't fire in this case, either.
This seems like obvious functionality to have, so I must be missing something glaringly obvious. Help!
I fixed this by using the AppStateIOS API instead of AppState. The later works as expected on iOS devices: when the app goes to the background the "change" event fires, and again when it comes back to the foreground. The AppState API doesn't seem to fire the "change" event at all on an iOS device, as of React Native v0.18, as far as I can tell. The project's conventions suggest that AppState should be a cross-platform wrapper around AppStateIOS, but that doesn't seem to be the case here.
The following example should demonstrate the issue:
React.createClass({
componentDidMount() {
AppStateIOS.addEventListener('change', state =>
console.log('AppStateIOS changed to', state)
)
AppState.addEventListener('change', state =>
console.log('AppState changed to', state)
)
},
render() {
return <View/>
}
})
When this component is mounted into a React Native app, you will see "AppStateIOS changed to ..." when closing and opening the app. You will never see "AppState changed to ..." as far as I'm aware.
Update
It appears that this was fixed in React Native recently (as of v26). You can now use AppState as advertised on iOS and Android.
I don't think that you're missing something. This functionality is just not provided by react-native out of the box. Maybe the idea was to simplify, since for most apps it's enough to perform data sync when the app returns to foreground.
You can either create your own native module which provides this functionality or you can go with a simple (sort of hacky?) solution:
In your AppDelegate save a reference to the react root view:
#interface AppDelegate()
#property (nonatomic, strong) RCTRootView *rootView;
#end
When initializing the view, set your property and use it:
self.rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:#"MyApp"
initialProperties:nil
launchOptions:launchOptions];
Now implement the AppDelegate methods for handling the active state like you would do in your iOS apps and pass the information as props:
-(void)onAppActiveStateChanged:(BOOL)appBecameActive
{
NSMutableDictionary *newProps = [NSMutableDictionary dictionary];
if (self.rootView.appProperties != nil) {
[newProps addEntriesFromDictionary:self.rootView.appProperties];
}
newProps[#"appDidBecomeActive"] = #(appBecameActive);
self.rootView.appProperties = newProps;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
[self onAppActiveStateChanged:NO];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self onAppActiveStateChanged:YES];
}
On the JavaScript side, do whatever you need when the props change:
componentWillReceiveProps(nextProps) {
if (nextProps.appDidBecomeActive) {
alert('app did become active');
}
}
I'm not sure if this is the best approach, but it's supposed to work...
I think you answered the question your self already. Why don't you use a combination of componentWillMount and AppState -> 'change'? That should cover all cases. I use this for syncing my app via CodePush.