Post not yet marked as solved
I'm trying to display one embedded content by using the WKWebView and I can not click some of these links. Is there anything I did wrong?Here is the Link which I get the embedded content from:https://publish.twitter.com Here is the embedded content:<a class="twitter-timeline" href="https://twitter.com/Google?ref_src=twsrc%5Etfw">Tweets by Google</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>Here is my code:import UIKit
import WebKit
class ViewController: UIViewController {
private var mWebView: WKWebView!
let embeddedTwittContent = "<a class='twitter-timeline' href='https://twitter.com/Google?ref_src=twsrc%5Etfw'>Tweets by Google</a>" // let embeddedTwittContent = "<a class=\"twitter-timeline\" href=\"https://twitter.com/Smaforetagarna?ref_src=twsrc%5Etfw\">Tweets by Smaforetagarna</a>"
let scriptValue = "<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>"
let redirectLink = "https://twitter.com/Smaforetagarna/status/"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
configuration.preferences = preferences
self.mWebView = WKWebView(frame: CGRect.zero, configuration: configuration)
self.mWebView.translatesAutoresizingMaskIntoConstraints = false
self.mWebView.allowsLinkPreview = true
self.mWebView.allowsBackForwardNavigationGestures = true
self.mWebView.navigationDelegate = self
self.view.addSubview(self.mWebView)
// Add Constraints
self.mWebView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive = true
self.mWebView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
self.mWebView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0).isActive = true
self.mWebView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0).isActive = true
loadTweetNews()
}
func loadTweetNews(){
let htmlHeader = "<!DOCTYPE html> <html><meta name=\'viewport\' content=\'initial-scale=1.0\'/> <head> \(scriptValue) </head> <body>"
let htmlFooter = "</body> </html>"
let orderHtml = htmlHeader + embeddedTwittContent + htmlFooter
let url: URL = URL(string: "https:")!
self.mWebView.loadHTMLString(orderHtml, baseURL: url)
}
}
extension ViewController: WKNavigationDelegate{
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("page finished load")
}
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
print("didReceiveServerRedirectForProvisionalNavigation: \(navigation.debugDescription)")
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("didStartProvisionalNavigation")
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.navigationType == .linkActivated {
if let url = navigationAction.request.url,
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
print(url)
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
} else {
decisionHandler(.allow)
}
}
Post not yet marked as solved
Hello, I'm new to SwiftUI and right now I'm trying to create one simple Application by using @State, @ObservedObject, and @Environment. For some reason, I got error "Cannot preview in this file" after I tried to add Environment object. The canvas is not working, but I can actually run the application in a simulator and actual device without any problem. Here is how I added my environment object. SceneDelegate:func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let channelData = ChannelData()
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView().environmentObject(channelData)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible(
}
}ChannelData class:import Combine
final class ChannelData: ObservableObject{
@Published var channelName = "YouTube Channel"
}ContentView:import SwiftUI
struct ContentView: View {
@State private var showingSecondVC = false
@ObservedObject var videoIdea = VideoIdea()
@EnvironmentObject var channelData: ChannelData
var body: some View {
NavigationView{
VStack(alignment: .leading){
Text(videoIdea.title)
.font(.title)
Text(videoIdea.contentIdea)
.font(.subheadline)
Divider()
NavigationLink(destination: ChannelView()){
Text("Add Channel")
}
Button(action: {
self.showingSecondVC.toggle()
}){
Text("Add New Idea")
}.sheet(isPresented: $showingSecondVC){
SecondView(videoTitle: self.$videoIdea.title, videoContent: self.$videoIdea.contentIdea).environmentObject(self.channelData)
}
Spacer()
}.padding()
.navigationBarTitle(channelData.channelName)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}SecondView:import SwiftUI
struct SecondView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@Binding var videoTitle: String
@Binding var videoContent: String
@EnvironmentObject var channelData:ChannelData
var body: some View {
NavigationView {
VStack(alignment: .leading){
TextField("Video title", text: $videoTitle)
TextField("Video Content", text: $videoContent)
Divider()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}){
Text("Dismiss this VC")
}
Spacer()
}.padding()
.navigationBarTitle(channelData.channelName)
}
}
}ChannelView:import SwiftUI
struct ChannelView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State private var channelName = "My Channel"
@EnvironmentObject var channelData: ChannelData
var body: some View {
NavigationView{
VStack(alignment: .leading){
TextField("Channel Name", text: $channelName)
Divider()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}){
Text("Dismiss this VS")
}
Spacer()
}.padding()
.navigationBarTitle(channelData.channelName)
}
}
}
Post not yet marked as solved
Hello guys, like the title says. I'm tying to implment code so I can report the the call before I receive the remote VoIP notification call in methodfunc pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion pushProcessingCompletion: @escaping () -> Void)But under my research time I did get banned from the system and I was not aware for the change which apple announced before:https://developer.apple.com/documentation/pushkit/pkpushregistrydelegate/2875784-pushregistry?language=objcOn iOS 13.0 and later, if you fail to report a call to CallKit, the system will terminate your app. Repeatedly failing to report calls may cause the system to stop delivering any more VoIP push notifications to your app.So my question is is there any chance I can get myself "unban" from the system so I can at least debug my code to verify if my code is working or not
Post not yet marked as solved
Hellow, I was using one iPhone with version 12.4 to run application for development. Suddely when I updated from version 12.4 to 13.1, one of my http rest api just stopped working and it returns me error:"019-09-25 16:56:56.578750+0200 SmaforetagarnasAPP[487:44045] task challenge NSURLAuthenticationMethodServerTrustFAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://appapi2.bankid.com/rp/v5/auth, NSErrorFailingURLKey=https://appapi2.bankid.com/rp/v5/auth, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <1FDB0948-469A-4333-BA23-9CAB3452F59B>.<1>"), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <1FDB0948-469A-4333-BA23-9CAB3452F59B>.<1>, NSLocalizedDescription=cancelled}2019-09-25 16:56:56.590973+0200 SmaforetagarnasAPP[487:44045] Task <1FDB0948-469A-4333-BA23-9CAB3452F59B>.<1> HTTP load failed, 0/0 bytes (error code: -999 [1:89])2019-09-25 16:56:56.592230+0200 SmaforetagarnasAPP[487:44045] Connection 3: unable to determine interface type without an established connection2019-09-25 16:56:56.592313+0200 SmaforetagarnasAPP[487:44045] Connection 3: unable to determine fallback status without a connection"Im using Alamofire SessionManager to make the http callThe http call requires certificate and here is my code:Calling function:func authenticate(completion: @escaping ModelCompletion<Bool>) {
let configuration = URLSessionConfiguration.default
// configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
let sessionManager = Alamofire.SessionManager(
configuration: configuration)
let endUserIp: String = self.getIPAddress() ?? "192.168.8.103"
let parameters: Parameters = ["endUserIp": endUserIp]
//set condition
// certificatePolicies to “1.2.752.78.1.5” to restrict the order to Mobile BankID only.
var header = HTTPHeaders()
header["Content-Type"] = "application/json"
sessionManager.request("https://appapi2.bankid.com/rp/v5/auth", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: header)
.validate()
.responseJSON { [weak self] data in
print(data)
guard let strongSelf = self else { return }
switch data.result {
case .success(let value):
let bankIDJson = JSON(value)
strongSelf.autoStartToken = bankIDJson[RequestJsonTag.autoStartToken.rawValue].string
strongSelf.orderRef = bankIDJson[RequestJsonTag.orderRef.rawValue].string
SessionManager.sharedInstance.orderRef = strongSelf.orderRef!
completion(ModelResult.success(true))
case .failure(let error):
completion(ModelResult.failure(error: error.localizedDescription))
}
}.session.finishTasksAndInvalidate()
// Seeion delegate
let delegate = sessionManager.delegate
self.didReceiveSessionManagerChallenge(delegate: delegate)
}Once I receive Challenge this function will get called:private func didReceiveSessionManagerChallenge(delegate: SessionDelegate) {
// Did Receive Challenge
delegate.sessionDidReceiveChallenge = { urlSession, challenge in
let protectionSpace = challenge.protectionSpace
NSLog("task challenge %@", protectionSpace.authenticationMethod)
switch (protectionSpace.authenticationMethod, protectionSpace.host) {
case (NSURLAuthenticationMethodServerTrust, "appapi2.bankid.com"):
if self.shouldTrustBankID(protectionSpace: protectionSpace) {
let credential = URLCredential(trust: protectionSpace.serverTrust!)
return (.useCredential, credential)
} else {
return (.cancelAuthenticationChallenge, nil)
}
case (NSURLAuthenticationMethodClientCertificate, "appapi2.bankid.com"):
let identity = Bundle.main.identityForBankIDPayment(named: "smaforetagarnasrpca", password: "Helsingborg#1977")
let credential = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
return (.useCredential, credential)
default:
return (.performDefaultHandling, nil)
}
}
}Here is extension once it requires the certificate:extension Bundle {
func certificateForBankIDPayment(named: String) -> SecCertificate {
let cerURL = self.url(forResource: named, withExtension: "der")!
let cerData = try! Data(contentsOf: cerURL)
return SecCertificateCreateWithData(nil, cerData as NSData)!
}
func identityForBankIDPayment(named: String, password: String) -> SecIdentity {
let p12URL = Bundle.main.url(forResource: named, withExtension: "p12")!
let p12Data = try! Data(contentsOf: p12URL)
var importResult: CFArray? = nil
let err = SecPKCS12Import(
p12Data as NSData,
[kSecImportExportPassphrase: password] as NSDictionary,
&importResult)
assert(err == errSecSuccess)
let identityDicts = importResult! as! [[String:Any]]
return identityDicts.first![kSecImportItemIdentity as String]! as! SecIdentity
}
}My Info.plist:<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Småföretagarnas</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.curamet.SmaforetagarnasAPP</string>
<key>CFBundleURLSchemes</key>
<array>
<string>sfrapp</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>appapi2.bankid.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>MainTapBarView</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>P.s. I updated my Xcode till support the latest iOS 13.1 version as well.
Post not yet marked as solved
I want to know if it's possible to disable full-screen mode when WKWebView open local video file by using the file's local url.Because I always receive error "Plug-in handled load" when WKWebView is loading(but the video is still playing in full screen mode).I checked some solutions from StackOverFlow:https://stackoverflow.com/a/10194888/11055217https://stackoverflow.com/questions/2143763/does-uiwebview-send-the-same-user-agent-in-the-request-headers-as-mobile-safari/5916330#5916330But these link still cannot solve my problem.Here is my WKWebView code setup://
// WebViewController.swift
// HelpieMeApp
//
// Created by Guests on 11/9/18.
// Copyright © 2018 Menjie Mao. All rights reserved.
//
import WebKit
class WebViewController: UIViewController {
private var webView: WKWebView!
@IBOutlet var viewTitle: UILabel!
@IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
var urlString: String = ""
var url: URL? = nil
var webViewTitle: String = ""
override func viewDidLoad() {
super.viewDidLoad()
self.viewTitle.text = self.webViewTitle
self.initWebView()
self.loadingIndicator.stopAnimating()
self.loadingIndicator.isHidden = true
// Load file url else use load link url to support both ways
if let fileURL = self.url {
self.webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
self.webView.customUserAgent = UIWebView().stringByEvaluatingJavaScript(from: "navigator.userAgent")
} else {
self.webView.load(URLRequest(url: URL(string: self.urlString)!))
}
}
@IBAction func cancelAction(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
private func initWebView() {
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
// Setup Web View
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
configuration.preferences = preferences
self.webView = WKWebView(frame: CGRect.zero, configuration: configuration)
self.webView.translatesAutoresizingMaskIntoConstraints = false
self.webView.allowsLinkPreview = true
self.webView.allowsBackForwardNavigationGestures = true
self.webView.navigationDelegate = self
self.view.addSubview(self.webView)
self.view.bringSubviewToFront(self.loadingIndicator)
// Add Constraints
self.webView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 80).isActive = true
self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
self.webView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0).isActive = true
self.webView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0).isActive = true
if #available(iOS 11.0, *) {
self.webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
} else {
self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
}
}
}
// MARK: - WKNavigationDelegate
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
self.loadingIndicator.startAnimating()
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Swift.Void) {
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.loadingIndicator.stopAnimating()
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
self.loadingIndicator.stopAnimating()
self.loadingIndicator.isHidden = true
AlertUtil.showErrorMessage(vc: self, title: error.localizedDescription)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
self.loadingIndicator.stopAnimating()
self.loadingIndicator.isHidden = true
AlertUtil.showErrorMessage(vc: self, title: error.localizedDescription)
}
}And the error triggered atfunc webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error)
Hello, Im trying to make a API call to a server by using a https certificate, but I already get stuck at the server trust stage. I'm using a server certificate with extension .cer and here is my code:private func shouldTrust(protectionSpace: URLProtectionSpace) -> Bool {
guard let trust = protectionSpace.serverTrust else { return false }
// First try evaluating trust with any custom anchor. If that succeeds, we're good to go.
var trustResult = SecTrustResultType.invalid
var err = SecTrustEvaluate(trust, &trustResult)
guard err == errSecSuccess else { return false }
if [.proceed, .unspecified].contains(trustResult) { return true }
// If it fails, apply our custom anchor and try again.
let root = Bundle.main.certificateForBankIDPayment(named: "sebtekniskbankinfoserverca")
err = SecTrustSetAnchorCertificates(trust, [root] as NSArray)
guard err == errSecSuccess else { return false }
err = SecTrustEvaluate(trust, &trustResult)
guard err == errSecSuccess else { return false }
return [.proceed, .unspecified].contains(trustResult)
}extension Bundle {
func certificateForBankIDPayment(named: String) -> SecCertificate {
let cerURL = self.url(forResource: named, withExtension: "cer")!
let cerData = try! Data(contentsOf: cerURL)
return SecCertificateCreateWithData(nil, cerData as NSData)!
}
}Here is the server certificate in txt form:-----BEGIN CERTIFICATE-----MIIFvjCCA6agAwIBAgIITyTh/u1bExowDQYJKoZIhvcNAQENBQAwYjEkMCIGA1UECgwbRmluYW5zaWVsbCBJRC1UZWtuaWsgQklEIEFCMRowGAYDVQQLDBFJbmZyYXN0cnVjdHVyZSBDQTEeMBwGA1UEAwwVQmFua0lEIFNTTCBSb290IENBIHYxMB4XDTExMTIwNzEyMzQwN1oXDTM0MTIzMTEyMzQwN1owYjEkMCIGA1UECgwbRmluYW5zaWVsbCBJRC1UZWtuaWsgQklEIEFCMRowGAYDVQQLDBFJbmZyYXN0cnVjdHVyZSBDQTEeMBwGA1UEAwwVQmFua0lEIFNTTCBSb290IENBIHYxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwVA4snZiSFI3r64LvYu4mOsI42A9aLKEQGq4IZo257iqvPH82SMvgBJgE52kCx7gQMmZ7iSm39CEA19hlILh8JEJNTyJNxMxVDN6cfJP1jMHJeTES1TmVbWUqGyLpyT8LCJhC9Vq4W3t/O1svGJNOUQIQL4eAHSvWTVoalxzomJhOn97ENjXAt4BLb6sHfVBvmB5ReK0UfwpNACFM1RN8btEaDdWC4PfA72yzV3wK/cY5h2k1RM1s19PjoxnpJqrmn4qZmP4tN/nk2d7c4FErJAP0pnNsll1+JfkdMfiPD35+qcclpspzP2LpauQVyPbO21Nh+EPtr7+Iic2tkgz0g1kK0IL/foFrJ0Ievyr3Drm2uRnA0esZ45GOmZhE22mycEX9l7w9jrdsKtqs7N/T46hil4xBiGblXkqKNG6TvARk6XqOp3RtUvGGaKZnGllsgTvP38/nrSMlszNojrlbDnm16GGoRTQnwr8l+Yvbz/ev/e6wVFDjb52ZB0Z/KTfjXOl5cAJ7OCbODMWf8Na56OTlIkrk5NyU/uGzJFUQSvGdLHUipJ/sTZCbqNSZUwboI0oQNO/Ygez2J6zgWXGpDWiN4LGLDmBhB3T8CMQu9J/BcFvgjnUyhyim35kDpjVPC8nrSir5OkaYgGdYWdDuv1456lFNPNNQcdZdt5fcmMCAwEAAaN4MHYwHQYDVR0OBBYEFPgqsux5RtcrIhAVeuLBSgBuRDFVMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+Cqy7HlG1ysiEBV64sFKAG5EMVUwEwYDVR0gBAwwCjAIBgYqhXBOAQQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDQUAA4ICAQAJOjUOS2GJPNrrrqf539aN1/EbUj5ZVRjG4wzVtX5yVqPGcRZjUQlNTcfOpwPoczKBnNX2OMF+Qm94bb+xXc/08AERqJJ3FPKu8oDNeK+Rv1X4nh95J4RHZcvl4AGhECmGMyhyCea0qZBFBsBqQR7oC9afYOxsSovaPqX31QMLULWUYoBKWWHLVVIoHjAmGtAzMkLwe0/lrVyApr9iyXWhVr+qYGmFGw1+rwmvDmmSLWNWawYgH4NYxTf8z5hBiDOdAgilvyiAF8Yl0kCKUB2fAPhRNYlEcN+UP/KL24h/pB+hZ9mvR0tM6nW3HVZaDrvRz4VihZ8vRi3fYnOAkNE6kZdrrdO7LdBc9yYkfQdTcy0N+Aw7q4TkQ8npomrVmTKaPhtGhA7VICyRNBVcvyoxr+CY7aRQyHn/C7n/jRsQYxs7uc+msq6jRS4HPK8olnF9usWZX6KY+8mweJiTE4uN4ZUUBUtt8WcXXDiK/bxEG2amjPcZ/b4LXwGCJb+aNWP4+iY6kBKrMANs01pLvtVjUS9RtRrY3cNEOhmKhO0qJSDXhsTcVtpbDr37UTSqQVw83dReiARPwGdURmmkaheH6z4k6qEUSXuFch0w53UAc+1aBXR1bgyFqMdy7Yxib2AYu7wnrHioDWqP6DTkUSUeMB/zqWPM/qx6QNNOcaOcjA==-----END CERTIFICATE-----Im pretty sure about the server root certificate is valid because I can add it to the keychain access.With debug mode, I can pass code line:let cerURL = self.url(forResource: named, withExtension: "cer")!
let cerData = try! Data(contentsOf: cerURL)But I will receive the error message "error: Unexpectedly found nil while unwrapping an Optional value" when I trying to pass code line: return SecCertificateCreateWithData(nil, cerData as NSData)!Is there anything I was missing?
Post not yet marked as solved
Right now I'm looking for a good tool which can help me track down user activity when they are using application. I know there is App Analytics, but I need some more information which is a little more specific. Information which I would like to know is:How many user clicked on one specific button, image, text or link.How many times user has viewd on one specific UI page.
I was trying to create a UIButton by code, and I want to add the UIButton as a subview into a UITextView. Here is the code:private func initTermsTextView() { let filePath = Bundle.main.path(forResource: "terms", ofType: "html", inDirectory: nil, forLocalization: nil) ?? "" let htmlString = try! String(contentsOfFile: filePath) let htmlData = NSString(string: htmlString).data(using: String.Encoding.unicode.rawValue) let options = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html] let attributedString = try! NSMutableAttributedString(data: htmlData!, options: options, documentAttributes: nil) let font = UIFont(name: "BrandonGrotesque-Regular", size: 20) ?? UIFont.systemFont(ofSize: 20) attributedString.setFontFace(font: font, color: UIColor.grayMetalic()) let btn: UIButton = UIButton(frame: CGRect(x: 8, y: termsTextView.contentSize.height*11-135, width: 48, height: 48)) btn.setTitle("asdasdasdasda", for: .normal) btn.addTarget(self, action: #selector(buttonAction), for: .touchUpInside) btn.clipsToBounds = true btn.setImage(UIImage(named: "uncheckedBox"), for: .normal) let path = UIBezierPath(rect: CGRect(x: 8, y: termsTextView.contentSize.height*11-135, width: btn.frame.width, height: btn.frame.height)) self.termsTextView.textContainer.exclusionPaths = [path] self.termsTextView.attributedText = attributedString self.termsTextView.text.append(TermConditionSingleton.getInstance.setTCGetString()) self.termsTextView.addSubview(btn) }Since I have no idea how to add UIButton at the bottom of a UITextView, I did hardcore and count out the UITextView length(text length*11-135) and added the button under the UITextView.After I was running my code with devices which is above the iPhone 6 (include 6s and plus) and the UIButton has displayed in the UITextView. But when I tried with iPhone 6 plus and iPhone 6s plus, the UIButton sub view did not show in the UITextView and I have no idea why.Is there any way I can fix this type of problem?