NSURL Error in XCode 8.2.1 - ios

BEGINNER ALERT! Please talk to me like I'm a 5-year-old because I am new to this platform and language. I will be grateful and unoffended.
I have the following code in my Xcode project to open a website in the native browser from a button on the app home page:
#IBAction func faceURL(_ sender: Any) {
NSURL *spotiURL = [NSURL URLWithString:#"https://www.facebook.com"];
[[UIApplication sharedApplication] openURL:faceURL options:#{} completionHandler:^(BOOL success) {
if (success){
NSLog(#"Opened url");
}
}];
}
On the line:
NSURL *spotiURL = [NSURL URLWithString:#"https://www.facebook.com"];
it's throwing the following error:
Expected "," separator Consecutive statements on a line must be separated by ";"
It recommends putting a ; between the colon and # symbol before the URL. I know some of this is deprecated with the new Xcode and Swift format, but I can't find a straightforward answer for this particular issue. Thank you in advance for your wisdom.
UPDATE
Thank you to the folks who helped with this. In case anyone else comes across this issue, here is the code that ended up working to touch the button and open a URL in the native browser:
#available(iOS 10.0, *)
#IBAction func openURL(_ sender: Any) {
let openURL = URL(string: "https://www.facebook.com")
UIApplication.shared.open(openURL!, options: [:], completionHandler: nil)
}
I also had to delete the original button and corresponding reference in the ViewController, replace the button, and do a fresh connection with ViewController to get it working. Many thanks!

It looks like you're trying to use Objective C code in a Swift method. If your project is written in Swift then this is (probably) the code you need:
#IBAction func faceURL(_ sender: Any) {
if let facebookURL = URL(string: "https://www.facebook.com")
{
UIApplication.shared.openURL(facebookURL) // the open method you were using doesn't exist in Swift
}
}
I'd suggest you work through a few tutorials to learn the basics of iOS development.

Well, you are mixing Swift (first line) and ObjC (all the other) syntax, so you have to choose one of them first of all. Your "mixed" code looks good btw.

First: you have faceURL in openURL when it should be spotiURL.
Second: you mean to convert the code you copied from SO from Obj-C to Swift which I will do for you :)
let spotiURL = URL(string: "https://www.facebook.com")
UIApplication.shared.openURL(spotiURL!)

Related

Synchronizing Apple Watch and iPhone using Swift 3 and Realm

I need to Display and modify my data structure from both Apple Watch and iPhone.
The Database:
I am currently using a simple Realm Structure where I have an Object A and an Object B which can hold lots of A's.
So on iPhone the user can create a B and add A's and view of course all A's and B's.
I want the Apple watch to show all A's of the current B and give the users the chance to add new A's to their current B.
The way I have tried to do it:
I wanted to move the hole Realm file from iPhone to the watch or the other way. (That was a tip from the Internet)
iPhone Code:
override func viewDidLoad() {
super.viewDidLoad()
if WCSession.isSupported() { //makes sure it's not an iPad or iPod
let watchSession = WCSession.default()
watchSession.delegate = self
watchSession.activate()
transferRealmFile()
if watchSession.isWatchAppInstalled {
do {
try watchSession.updateApplicationContext(["foo": "bar"])
} catch let error as NSError {
print(error.description)
}
}
}
}
func transferRealmFile(){
if let path = Realm.Configuration().fileURL {
WCSession.default().transferFile(path, metadata: nil)
}
}
WathcKit Extension:
func session(_ session: WCSession, didReceive file: WCSessionFile) {
//set the recieved file to default Realm file
var config = Realm.Configuration()
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
let realmURL = documentsDirectory.appendingPathComponent("data.realm")
if FileManager.default.fileExists(atPath: realmURL.path){
try! FileManager.default.removeItem(at: realmURL)
}
try! FileManager.default.copyItem(at: file.fileURL, to: realmURL)
config.fileURL = realmURL
Realm.Configuration.defaultConfiguration = config
}
Then I call transferRealmFile() every time I write to Realm. This works but I can't solve this Problems:
Problems:
It doesn't work if only watchKit App is started.
Apple Watch to iPhone doesn't work the same way. (I think I need to change the didRecived code, but I don't know what)
Question:
Do you know who to solve this 2 Problems or do you maybe know a better way to handle the situation or will the way we interact between iPhone an Watch change in WathcOS 3?
With watchOS1 it was possible to use AppGroups to share resources (even your Realm database) between an iOS app and its Watch extension. However, Apple removed this in watchOS 2, so now the only way to share data between your iOS and watchOS apps is via WatchConnectivity. Have a look at this answer.
Sadly the WatchConnectivity framework requires the WCSession to be active on both devices for transferring data, so you can't really get around problem 1.
In my opinion it is a better solution to only communicate the changes between the two apps and not send the whole Realm file, since your Realm file can get quite big and hence sending it forward and backward can take a lot of time and resources, while just sending the changes should be way faster.

URL, NSURL - compiler errors in code from the standard samples

m.b. I'm asking stupid question, but I'm really newbie in Swift and iPhone programming. Using XCode 8.0.
I want to create WebView application and have taken next code from here: https://sourcefreeze.com/uiwebview-example-using-swift-in-ios/
My Code :
import UIKit
import Foundation
class ViewController: UIViewController {
#IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL (string: "http://www.sourcefreeze.com");
let requestObj = NSURLRequest(URL: url!);
myWebView.loadRequest(requestObj);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Of course I've created UI object of UIWebView and connected it to controller:
#IBOutlet weak var myWebView: UIWebView!
During the build I receive next red alert:
'NSURL' is not implicitly convertible to 'URL'; did you mean to use 'as' to explicitly convert?
As I understand this code worked perfectly before 2 years. I guess that I'm missing something, but what?
Thanks for advance.
Try to use URL instead of NSURL as it is replaced with URL type in Swift 3
let url = URL(string: "http://www.sourcefreeze.com")
Here is the instruction from apple developer forum
The Swift overlay to the Foundation framework provides the URL
structure, which bridges to the NSURL class. The URL value type offers
the same functionality as the NSURL reference type, and the two can be
used interchangeably in Swift code that interacts with Objective-C
APIs. This behavior is similar to how Swift bridges standard string,
numeric, and collection types to their corresponding Foundation
classes.
For more information about value types, see Classes and Structures in
The Swift Programming Language (Swift 3) and Working with Cocoa
Frameworks in Using Swift with Cocoa and Objective-C (Swift 3).
It is the simplest way to solve issue:
let url = URL(string: "http://www.sourcefreeze.com")!
myWebView.load(URLRequest(url: url))
Xcode often tales you what is wrong. So from Xcode message it is possible to understand that NSURL should be converted to URL. Try to read relevant resources and bot use old tutorials. Swift is dynamically changes language always try to use up to date resources.
Try in this way
myWebView.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.sourcefreeze.com")))
myWebView.delegate = self;
self.view.addSubview(myWebView)
This code worked:
let myUrl = URL (string: "http://www.sourcefreeze.com")!
let request = URLRequest(url: myUrl);
myWebView.loadRequest(request);
Now the WebView is invisible, but I'll try firstly to search the solution in a forum.

Create a unique identifer in a webview

Go easy on me I am new to I OS and Swift :). I am trying to create a IOS app using swift. I have a web view display that is working correctly, displaying the website. YAY!!
What I need to do now is create a unique identifier that is stored locally and when the app is opened is sent to the remote server. I see i can use this...
UIDevice.currentDevice().identifierForVendor!.UUIDString
However i would like to store it locally for future use and send it to the remote server every time the app is opened. I have done research on this and have come upon answers for other objects just not a web view.
If someone knows of a tutorial or example code for this solution i would greatly appreciate it.
UPDATE
let uuid = UIDevice.currentDevice().identifierForVendor!.UUIDString
and for the url im using
let url= NSURL (string:"https://example.com");
Could i do something like this? Or like it?
let url= NSURL (string:"https://example.com");
let requestobj= NSURLRequest(URL:url! ADD VAR HERE? );
Where ADD VAR HERE is the uuid to pass to the server which i can catch with a php script?
Latest update..
Im having a hard time integrating that into my existing code. Where would be the best place to put it?
import UIKit
class ViewController: UIViewController {
let uuid = UIDevice.currentDevice().identifierForVendor!.UUIDString
#IBOutlet weak var WebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL (string: "https://example.com");
let requestObj = NSURLRequest(URL: url?)
WebView.loadRequest(requestObj);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is the answer i was looking for. Thanks for your help everyone!
let device_uuid = UIDevice.currentDevice().identifierForVendor!.UUIDString
let api_host = "https://example.com?uuid=" + device_uuid
let url = NSURL(string: api_host)
let req = NSURLRequest(URL: url!)
WebView.loadRequest(req);
Apparently what i needed to do was build my URL into a variable. Then i can structure it using the NSURL and use it from there. This guide helped me. Just ignore the ruby on rails part if that's not what your doing.
http://ericlondon.com/2015/12/09/sending-messages-between-a-swift-webview-and-a-rails-backend-using-javascript.html
You will need to check on the webserver side to confirm exactly what you need to pass in - but if you are developing that side as well, then you should have control :-)
Should be something like this - please not that you don't need ; in swift
let request= NSURLRequest(URL:url)
var bodyData = "myUUID=\(uuid)&otherData=value1"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
Keep in mind that this identifier will change if a user uninstalls the application. If you need to persist it then I'd recommend to store it on the keychain so the id is always the same for the same phone even if the app is uninstalled.
Check this other question: How to preserve identifierForVendor in ios after uninstalling ios app on device?

Using Facebook Messenger SDK in Swift

I've been trying to use Facebook Messenger SDK in my Swift Project.
And the problem is that Facebook only shows how to use in Objective-C.
I'm having trouble calling methods from the FBSDKMessengerShareKit.
I've made bridging header and added FBSDKMessengerShareKit for import.
The bridging header is like this
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
#import <FBSDKMessengerShareKit/FBSDKMessengerShareKit.h>
#ifndef myProject_Bridging_Header_h
#define myProject_Bridging_Header_h
#endif
This is how Facebook shows how to share an image in Messenger with Objective-C
if ([FBSDKMessengerSharer messengerPlatformCapabilities] & FBSDKMessengerPlatformCapabilityImage) {
UIImage *image = [UIImage imageNamed:#"myImage];
[FBSDKMessengerSharer shareImage:image withOptions:nil];
}
The way I'm changing it into Swift
if (FBSDKMessengerSharer.messengerPlatformCapabilities() & FBSDKMessengerPlatformCapability.Image) {
let myImage = UIImage(named: "myImage")
FBSDKMessengerSharer.shareImage(myImage, withOptions: nil)
}
My Swift code cannot be built and it always shows the error
"Could not find an overload for '&' that accepts the supplied arguments"
I don't know what's wrong with my Swift code, Do anyone know how to use MessengerSDK in Swift?
here is the code you need :
let result = FBSDKMessengerSharer.messengerPlatformCapabilities().rawValue & FBSDKMessengerPlatformCapability.Image.rawValue
if result != 0 {
// ok now share
if let sharingImage = sharingImage {
FBSDKMessengerSharer.shareImage(sharingImage, withOptions: nil)
}
} else {
// not installed then open link. Note simulator doesn't open iTunes store.
UIApplication.sharedApplication().openURL(NSURL(string: "itms://itunes.apple.com/us/app/facebook-messenger/id454638411?mt=8")!)
}
Check this for more reference : http://shoheik.hatenablog.com/entry/2015/03/28/120212
In Swift you can use this code:
if UIApplication.sharedApplication().canOpenURL(NSURL(string: "fb-messenger-api://")!) {
let content = FBSDKShareLinkContent()
content.contentURL = NSURL(string: url)
content.contentTitle = "your awesome title"
FBSDKMessageDialog.showWithContent(content, delegate: self)
} else {
UIApplication.sharedApplication().openURL(NSURL(string: "https://itunes.apple.com/pl/app/messenger/id454638411?mt=8")!)
}
It's show Messenger window with content.
Not an answer but as of Today 15 April 2021, MessageDialog or FBSDKMessageDialog is deprecated
Here is the FB Response
Share to Messenger SDK that allows people to share links and media from apps to Messenger will no longer be supported. Businesses and developers might need to make modifications to their app to trigger native OS sharing. People will be able to share content to Messenger using the native sharing features that is built into their devices.

'NSURLRequest?' does not have a member named 'URL' - Swift

Hi I am really new to coding in Swift, and am trying to follow the codes in this book: http://www.apress.com/9781484202098. Learn iOS 8 App Development 2nd Edition by James Bucanek
In particular, I am working through Chapter 3 - building a URL shortening app, but despite having copied the code exactly, I am getting an error on the code in Page 76:
if let toShorten = webView.request.URL.absoluteString {
which states 'NSURLRequest?' does not have a member named 'URL'.
I have tried googling an answer, but unfortunately have not come across anything. Any response I can find seems to suggest that my code ought to be working (e.g. How to get url which I hit on UIWebView?). This seems to have the closest answer SWIFT: Why I can't get the current URL loaded in UIWebView? but the solution does not appear to work for me. If I add a ? after the request, it will then at least build it, but I then have a nil variable returned.
I am using Xcode v6.1.1. Here is the piece of code that is coming up with the error in ViewController.swift:
let GoDaddyAccountKey = "0123456789abcdef0123456789abcdef" //this is replaced by my actual account key in my own code
var shortenURLConnection: NSURLConnection?
var shortURLData: NSMutableData?
#IBAction func shortenURL( AnyObject ) {
if let toShorten = webView.request?.URL.absoluteString { // ? now added
let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) //added if here and removed !
let request = NSURLRequest(URL:firstrequest)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
If you have any suggestions on how I can fix this, I would really appreciate it!
Update:
Following suggestions from Ashley below, I have amended my code so that it is no longer bringing up the error (see comments above). However, it is now no longer running. This appears to be because the urlString is being created as http://api.x.co/Squeeze.svc/text/d558979bb9b84eddb76d8c8dd9740ce3?url=Optional("http://www.apple.com/"). The problem is therefore the Optional() that is included and thus makes it an invalid URL. Does anyone have a suggestion on how to remove this please?
request is an optional property on UIWebView:
var request: NSURLRequest? { get }
also stringByAddingPercentEscapesUsingEncoding returns an optional:
func stringByAddingPercentEscapesUsingEncoding(_ encoding: UInt) -> String?
What you need is to make user of optional binding in a few places:
if let toShorten = webView.request?.URL.absoluteString {
if let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) { // If a method can return a nil, don't force unwrap it
let request = NSURLRequest(URL:first request)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
See Apple's docs on optional chaining for details
See Apple's docs for NSURL class

Resources