Failing to make request to server using alamofire and DisabledTrustEvaluator - swift

I am trying to get some data off a server that created I using asp.net core, however; when trying to get the data in my Swift iOS code it keeps on failing without any error showing. I have done all the TSL checks in my info.plist.
model.swift
import Foundation
struct User: Decodable {
let name:String
let userEmail: String
let firebaseId: String
let userMode: Int
let profileImg: String
let loginType: Int?
}
userController.swift
import UIKit
import ProgressHUD
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
removeNavBar()
// UserApiService.shared.makeGetAPICall(user:{users, error in
// // ProgressHUD.dismiss()
// guard let users = users else {return}
// print(users)
// guard let errors = error else {return}
// print(errors)
// })
}
#IBAction func googleLogin(_ sender: Any) {
ProgressHUD.animationType = .circleSpinFade
ProgressHUD.show()
UserApiService.init().makeGetAPICall(user: {users, error in
ProgressHUD.dismiss()
guard let users = users else {return}
print(users)
guard let errors = error else {return}
print(errors)
})
}
private func removeNavBar(){
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
apiService.swift
import Foundation
import Alamofire
class UserApiService{
static let shared = UserApiService.init()
let session: Session = {
let manager = ServerTrustManager(allHostsMustBeEvaluated: false,evaluators: ["localhost:5001": DisabledTrustEvaluator()])
let configuration = URLSessionConfiguration.af.default
return Session(configuration: configuration, serverTrustManager: manager)
}()
//MARK:- GET
func makeGetAPICall(user completionHandler: #escaping ([User]?,Error?) -> Void) {
var urlComponent = URLComponents()
urlComponent.scheme = "https"
urlComponent.host = "localhost"
urlComponent.port = 5001
urlComponent.path = "/api/user"
print(urlComponent.url!)
guard let url = urlComponent.url else {
return
}
session.request(url, method: .get).validate().responseDecodable(of: [User].self) {(response) in
switch response.result{
case .success:
guard let users = response.value else {
return
}
print(users)
completionHandler(users, nil)
case .failure(let error):
completionHandler(nil, error)
}
}
}
}
info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
I debugged it with breakpoints, and I am getting <unavailable; try printing with "VO" or "PO">. I'm having trouble understanding what that means and how I should resolve this.
Also, I have changed my info.plist and it looks like this, however; I am still getting the same issue
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

So I managed to fix my issue, Hooray!!!
What I did was, I changed evaluators: ["localhost:5001": DisabledTrustEvaluator() to evaluators: ["localhost": DisabledTrustEvaluator()
Also, when calling my method, I was referencing normally from a class but then after, I had to call it as a singleton, and then, HEY PRESTO, IT WORKED!
#IBAction func googleLogin(_ sender: Any) {
ProgressHUD.animationType = .circleSpinFade
ProgressHUD.show()
UserApiService.shared.makeGetAPICall(user: {users, error in
ProgressHUD.dismiss()
guard let users = users else {return}
print(users)
guard let errors = error else {return}
print(errors)
})
}
This link helped me figure out part of the reason for my issues https://github.com/Alamofire/Alamofire/issues/3336

Related

In iOS, how can I get the contact shared from "Recent" calls list to my app in Flutter?

Please excuse me if I sound stupid, I'm new to flutter.
I have started learning flutter recently and wanted to create an app where anyone can share a contact from the "Recent" calls list to my app. I'm following this blog post which allows text share from any other app to my app.
What I have done so far:
This is my plist file, added the public.vcard to allow my app to appear on the tap of "Share Contact".
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<string>
SUBQUERY (
extensionItems, $extensionItem,
SUBQUERY (
$extensionItem.attachments, $attachment,
ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.vcard"
).#count >= 1
).#count > 0
</string>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>
Here's my ShareViewController.swift
import Social
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
override func isContentValid() -> Bool {
// Do validation of contentText and/or NSExtensionContext attachments here
print("Something is not right")
return true
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
let sharedSuiteName: String = "group.com.thelogicalbeing.whatsappshare"
let sharedDataKey: String = "SharedData"
let extensionItem = extensionContext?.inputItems[0] as! NSExtensionItem
let contentTypeText = kUTTypeText as String // Note, you need to import 'MobileCoreServices' for this
for attachment in extensionItem.attachments! {
print(attachment)
if attachment.hasItemConformingToTypeIdentifier(contentTypeText) {
attachment.loadItem(forTypeIdentifier: contentTypeText, options: nil, completionHandler: {(results, error) in
if let sharedText = results as! String? {
if let userDefaults = UserDefaults(suiteName: sharedSuiteName) {
userDefaults.set(sharedText, forKey: sharedDataKey)
}
}
})
}
}
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
}
Here's my AppDelegate.swift
import UIKit
import Flutter
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let sharedSuiteName: String = "group.com.thelogicalbeing.whatsappshare"
let sharedDataKey: String = "SharedData"
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: "com.thelogicalbeing.whatsappshare", binaryMessenger: controller.binaryMessenger)
methodChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: #escaping FlutterResult) -> Void in
if call.method == "getSharedData" {
if let prefs = UserDefaults(suiteName: sharedSuiteName) {
if let sharedText = prefs.string(forKey: sharedDataKey) {
result(sharedText);
}
// clear out the cached data
prefs.set("", forKey: sharedDataKey);
}
}
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
What I'm trying to achieve is that I need to receive the phone number and display it in my app.
Don't know how to proceed. Any help will be appreciated.
1- Apple does not allow fetching call logs on iOS!
You can fetch all contacts with all their information. But not the calls log.
2- On Android you can use the pub.dev dependency plugin call_log to do that.
Have a look at this package called receive_sharing_intent, it allows you to to receive sharing photos, videos, text, urls or any other file types from another app. And it also supports iOS Share extension and launching the host app automatically.

Files backed up to icloud in swift are changed when the app is deleted

Added backup and restore functions to the app
And it works fine until I delete the app
But if you delete the app and reinstall it, the file name you backed up is changed
The backup.db file is changed to .backupp.db.icloud when you reinstall the app after deleting it
And after the backup file, which was normal before deleting the app, is changed to .icloud, it seems that the file is not normal.
Below is the Info.plist and the source code
What's the problem?
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.sinwho.CheckDay</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>CheckDay</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>
func copyiCloudToLocal() throws -> Bool {
var result:Bool = false
let dbFileURL = CloudDataManager.DocumentsDirectory.dbFileURL.appendingPathComponent(Define.DB_NAME)
guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents") else
{
return result
}
let iCloudFileURL = containerURL.appendingPathComponent(Define.DB_NAME)
if !FileManager.default.fileExists(atPath: iCloudFileURL.path)
{
return false
}
if FileManager.default.fileExists(atPath: dbFileURL.path) {
try FileManager.default.removeItem(at: dbFileURL)
try FileManager.default.copyItem(at: iCloudFileURL, to: dbFileURL)
result = true
} else {
try FileManager.default.copyItem(at: iCloudFileURL, to: dbFileURL)
result = true
}
return result
}

How to read the string in an attached file, not sharing the string directly, using Share Extension from other APP to my APP in Swift?

In the following code I can read text in this way and print the text in the code.
But I do not know how to share txt file as an attachment and read it out in the following code.
import UIKit
import Social
import CoreServices
class ShareViewController: SLComposeServiceViewController {
private var textString: String?
override func isContentValid() -> Bool {
// Do validation of contentText and/or NSExtensionContext attachments here
if textString != nil {
if !contentText.isEmpty {
return true
}
}
return true
}
override func viewDidLoad() {
super.viewDidLoad()
let extensionItem = extensionContext?.inputItems[0] as! NSExtensionItem
let contentTypeText = kUTTypeText as String
for attachment in extensionItem.attachments! {
if attachment.isText {
attachment.loadItem(forTypeIdentifier: contentTypeText, options: nil, completionHandler: { (results, error) in
let text = results as! String
self.textString = text
_ = self.isContentValid()
})
}
}
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
print(String(textString!)) // <-- I cannot read txt file and print it
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
}
//MARK: NSItemProvider check
extension NSItemProvider {
var isText: Bool {
return hasItemConformingToTypeIdentifier(kUTTypeText as String)
}
}
Is there any method to share the txt file as an attachment in Share Extension?
Thanks for any help.
First of all, in info.plist of your share extension you have to set what type of attachments and how many your extension can get
Example:
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>10</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
</dict>
All keys you can find here
When your extension recives attachment first you need to check it for type(is it what you are expecting to recive).
And then, in didSelectPost() you can get that attachment and do something with it (maybe store it in your app if that's what you want).
Here is nice article about shere extension for photos

Cannot read the NFC chip of the ePassport using iOS13

import UIKit
import CoreNFC
class ViewController: UIViewController, NFCTagReaderSessionDelegate {
var nfcTagReaderSession: NFCTagReaderSession?
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("Tag reader did become active")
print("isReady: \(nfcTagReaderSession?.isReady)")
}
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
print("\(error)")
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
// this part is never called!
print("got a Tag!")
print("\(tags)")
}
#IBAction func clickedNFC(_ sender: Any) {
nfcTagReaderSession = NFCTagReaderSession(pollingOption: [.iso14443], delegate: self)
nfcTagReaderSession?.alertMessage = "Place the device on the innercover of the passport"
nfcTagReaderSession?.begin()
print("isReady: \(nfcTagReaderSession?.isReady)")
}
}
I also have in my entitlements file
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>NDEF</string>
<string>TAG</string>
</array>
and in my Info.plist
<key>NFCReaderUsageDescription</key>
<string>Read the NFC chip of ePassports</string>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
</array>
My problem is that tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) is never being called. What am I missing?
I found the solution I added 00000000000000 to the com.apple.developer.nfc.readersession.iso7816.select-identifiers entry in the Info.plist
Now it looks like this:
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
<string>00000000000000</string>
</array>

How to share a Note including Markup with Share Extensions Swift

I've already figured out how to share the general content of a Note (text and pictures). But the way I currently approach the problem the markup of the note is not kept (Titles, Lists, etc.). I just receive the pure text of the note. When you share a note with Mail for instance, you can see that the markup is transferred. Is there a way to do that for your own apps?
My current solution where I only receive the pure text:
class ShareViewController: UIViewController{
override func viewDidLoad() {
if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
// Verify the provider is valid
if let contents = content.attachments as? [NSItemProvider] {
// look for images
for attachment in contents {
print(attachment.registeredTypeIdentifiers)
if attachment.hasItemConformingToTypeIdentifier("public.plain-text"){
attachment.loadItem(forTypeIdentifier: "public.plain-text", options: nil) { data, error in
let string = data as! String
print(string)
}
}
}
}
}
}
}
EDIT:
My current NSExtensionActivationRules:
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationDictionaryVersion</key>
<integer>2</integer>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>100</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
</dict>
</dict>
Use the attributedContentText property of your NSExtensionItem (content):
override func viewDidLoad() {
if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
// move your content validation to `func isContentValid() -> Bool`
let attributedString = content.attributedContentText // yay NSAttributedString!
}
}