Web socket Swift crash link - swift

I have link for web soket. I checked it on https://www.websocket.org and it connected. However when I start to create URL object
if let url = URL(string: "wss://ios-devchallenge-11.tk/write?id={id}") {
socket = WebSocket(url: url, protocols: ["chat", "superchat"])
socket?.delegate = self
socket?.connect()
}
I got error. What do I wrong?

I turn out I set wrong url. I change code as below (removed {})
if let url = URL(string: "wss://ios-devchallenge-11.tk/write?id=id") {
socket = WebSocket(url: url, protocols: ["chat", "superchat"])
socket?.delegate = self
socket?.connect()
}

Related

Swift URL returns nil when the url contains an internationalized domain name (IDN)

I was wondering why this piece of code always exit with 1:
import Foundation
// an idn domain:
let uLabel = "համընդհանուր-ընկալում-թեստ.հայ"
let urlStr = "https://" + uLabel
guard let url = URL(string: urlStr) else { exit(1) }
exit(0)
Since Apple's browser Safari does support well IDN domains, I was surprised their URL library does not... I tried to urlencode the string beforehand, but it is not helping.
======EDIT======
After fixing the piece above upon Matt's suggestion, I faced another problem during fetching the website data:
import Foundation
let uLabel = "համընդհանուր-ընկալում-թեստ.հայ"
let scheme = "https"
var comps = URLComponents()
comps.scheme = scheme
comps.host = uLabel
guard let url = comps.url else { exit(1) }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let rawContent = data else { exit(1) }
guard let content = String(data: rawContent, encoding: String.Encoding.utf8) else { exit(1) }
if content.contains("UASG Testbed Landing Page") {
// successfully fetch content of the page
exit(0)
} else {
// error during fetching
exit(1)
}
}
task.resume()
RunLoop.main.run()
The program still exits with 1. It seems the domain is not converted to an A-LABEL as it is on Safari, as the error suggests (the certificate is valid, the error is misleading):
NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “համընդհանուր-ընկալում-թեստ.հայ” which could put your confidential information at risk., NSErrorFailingURLKey=https://%d5%b0%d5%a1%d5%b4%d5%a8%d5%b6%d5%a4%d5%b0%d5%a1%d5%b6%d5%b8%d6%82%d6%80-%d5%a8%d5%b6%d5%af%d5%a1%d5%ac%d5%b8%d6%82%d5%b4-%d5%a9%d5%a5%d5%bd%d5%bf.%d5%b0%d5%a1%d5%b5/,
I don't know why you're having trouble, but rule number one is never never never call URL(string). Use URLComponents. That's what it's for.
let uLabel = "համընդհանուր-ընկալում-թեստ.հայ"
let scheme = "https"
var comps = URLComponents()
comps.scheme = scheme
comps.host = uLabel
let url = comps.url // works for me
Until, someone can find a way to tell the URL framework to correctly represent the URL "https://համընդհանուր-ընկալում-թեստ.հայ", it is possible to translate the domain part to an A-LABEL before passing it to the URL constructor and elude its wrong internal representation:
import Foundation
import IDNA
// an idn domain:
let uLabel = "համընդհանուր-ընկալում-թեստ.հայ"
guard let aLabel = uLabel.idnaEncoded else { exit(1) }
let supportedUrl = "https://" + aLabel
guard let url = URL(string: supportedUrl) else { exit(1) }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let rawContent = data else { exit(1) }
guard let content = String(data: rawContent, encoding: String.Encoding.utf8) else { exit(1) }
if content.contains("UASG Testbed Landing Page") {
// successfully fetch content of the page
exit(0)
} else {
// error during fetching
exit(1)
}
}
task.resume()
RunLoop.main.run()
This piece of code does exit 0. The IDNA library is there (ensure you take the master branch, because released versions are still on IDNA2003):
https://github.com/Wevah/IDNA-Cocoa

Alamofire error sessionDeinitialized ssl certificate

I'm testing Alamofire with ssl certificate.
using swift and swiftUI I wrote this 2 functions to load the ssl from a bundle and make the request using Alamofire.
func getCertificate() -> [SecCertificate] {
let url = Bundle.main.url(forResource: "ssl", withExtension: "cer")
let localCer = try! Data(contentsOf: url!) as CFData
guard let certificate = SecCertificateCreateWithData(nil, localCer) else {
return []
}
return [certificate]
}
func loginUserIcrew(userName: String, password: String){
let evaluators: [String: ServerTrustEvaluating] = [
linkIcrew: PinnedCertificatesTrustEvaluator(certificates:getCertificate())
]
let manager = ServerTrustManager(evaluators: evaluators)
let session = Session(serverTrustManager: manager)
session.request (linkIcrew,method: .get, encoding: URLEncoding.default)
.response { response in
print(response)
}
}
and I using it in a simple button like this
struct SalaryStart: View {
#ObservedObject var ss = SalaryManager()
var body: some View {
Button {
ss.loginUserIcrew(userName: "user", password: "pass")
} label: {
Text("test")
}
}
}
I'm getting the error : Alamofire.AFError.sessionDeinitialized
any help how to solve tis issue? reading online looks like the session need to keep alive, but I don't understand what does it mean??
thanks for the help
sessionDeinitialized means what it says: your Session was deinitialized while the request was in progress and so it was cancelled. You need to keep the Session alive at least long enough to complete the request. Usually you want to use a single Session for all of your requests, so I suggest keeping it as a singleton.

Does WKWebView require a URL?

I am pulling in HTML content via an API that loads JSON and would like to use WKWebView in order to display it. Is it possible to use WKWebView without a URL?
This controller is built programmatically, so the webView is added as Subview. In the long run I will have the webView display below other content that is also pulled from the API.
This is the code I have:
var webView = WKWebView()
webView = WKWebView(frame: scrollView.bounds, configuration: WKWebViewConfiguration())
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
scrollView.addSubview(webView)
webView.navigationDelegate = self as? WKNavigationDelegate
webView.loadHTMLString("<html><body>\(self.articleBody)</body></html>", baseURL: nil)
I get this error when I load my app:
Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
In testing with a random URL and no HTML it works just fine.
I've looked at this question, but it doesn't have an answer that makes sense for me: com.apple.WebKit.WebContent drops 113 error: Could not find specified service
I'm still getting the same error, but I am at least seeing my content now ...
The issue had to do with where I was calling the webView.loadHTMLString. I had to move it inside of my URLSession code instead of keeping it outside.
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
if err == nil {
do {
let decoder = JSONDecoder()
let devo = try decoder.decode(Devotion.self, from: data)
DispatchQueue.main.async {
self.articleBody = devo.body
self.webView.loadHTMLString("<html><body>\(self.articleBody)</body></html>", baseURL: nil)
}
} catch let err {
print("Err", err)
}
}
}.resume()

Master Detail app in Swift - how to convert string into URL

I'm new here, so please bear with me. I have a Master-Detail app, and in the DetailViewController.swift file, here's the configureView func where it calls a web view to open a web page.
It's complaining on the let request = URLRequest(url:url) line because url variable is defined as a string. I've tried everything but it won't work.
By the way, MasterViewController.MyVariables.urlString is an array of strings.
func configureView() {
// Update the user interface for the detail item.
if let detail: AnyObject = detailItem {
if let myWebview = webView {
let url = MasterViewController.MyVariables.urlString
let request = URLRequest(url: url)
myWebview.scalesPageToFit = true
myWebview.loadRequest(request)
}
}
}
You can either pass an URL object or create an URL object from the string that you´re passing. Anyhow you need to convert your string into an URL.
if let url = URL(string: MasterViewController.MyVariables.urlString) {
// use url in here
}
Update:
Use this for your example:
if let url = URL(string: MasterViewController.MyVariables.urlString) {
// use url in here
let request = URLRequest(url: url)
}
Update 2:
You have your Struct which is an array of strings. Then you need to do this to get the value you want:
struct MyVariables {
static var urlString: [String]? = ["something"]
}
if let str = MyVariables.urlString?.first, let url = URL(string: str) {
// use url in here
let request = URLRequest(url: url)
print(url)
}
Right now I´m using MyVariables.urlString?.first, in the future if you want another index then you need to get that instead.
This is what I did to make it work:
let stringRepresentation = MasterViewController.MyVariables.urlString?.joined(separator:"")
print ("urlString", MasterViewController.MyVariables.urlString)
print ("sR",stringRepresentation)
let url = NSURL(string: stringRepresentation as! String)
let request = URLRequest(url: url! as URL)
myWebview.scalesPageToFit = true
myWebview.loadRequest(request)

Swift UIWebView LoadRequest

In order to load urls, I tried to connect .loadRequest with webview, but there is not such loadRequest. Is there anyone who knows why this is occurring to me?
func configurationView(){
if let webData: Web = self.detailItem {
if let webView = self.WebView {
let url = NSURL(string: webData.url)
let urlRequest = NSURLRequest(URL: url!)
(here I am trying to dp WebView.loadRequest(urlRequest), but I cannot!)
}
}
}