Posts

Post marked as solved
1 Replies
1.7k Views
Hi I have a custom UIView contained xib which is in an xcframework. The view has a timeout property which removes itself from the super view if it expiries. If the view does expiry, it fires a delegate which the function can observe using the KVC approach. What I'm experiencing is my function adds the view to the view controller ok, but doesn't display it until the function completes or throws an error. Here is a snippet of what I have described: // MARK: Contained in custom xcframework class MyView: UIView { var delegate: VerificationHandler? required init?(coder aDecoder: NSCoder) {         super.init(coder: aDecoder)         initialize()     }     override init(frame: CGRect) {         super.init(frame: frame)         initialize()     } func initialize() { let bundle = Bundle(for: type(of: self))      let uvNib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)      let uvView = uvNib.instantiate(withOwner: self, options: nil).first as! UIView addSubview(uvView) Timer.scheduledTimer(withTimeInterval: TimeInterval(10), repeats: false) { [self] timer in             timer.invalidate()             delegate?.verification(didContinue: false)             removeFromSuperview()       } } } protocol VerificationHandler { func verification(didContinue: Bool) } class VerificationResult: NSObject {     @objc dynamic var value: Bool     init(_ value: Bool) {         self.value = value     } } public enum MyEnum { } public extension MyEnum { private static var verificationResult: VerificationResult = VerificationResult(false) public static func myFunction(_ viewController: UIViewController) throws -> MyObject { if let viewController = viewController { let view = MyView(frame: viewController.view.frame) view.delegate = self as? VerificationHandler viewController.view.addSubview(view)  let semaphore = DispatchSemaphore.init(value: 0) // observe the change occurring in the view which creates the verificationResult. var result: Bool let kvc = verificationResult.observe(\.value, options: .new) { _, change in result = change.newValue! // didContinue semaphore.signal() } semaphore.wait() if !result { throw MyError.timeout } return MyObject(...) } } extension MyEnum: VerificationHandler {     func verification(didContinue: Bool) {         MyEnum.verificationResult = VerificationResult(didContinue)     } } // MARK: View controller app code class ViewController: UIViewController { override func viewDidLoad() {     super.viewDidLoad() } @IBAction func onClick(_ sender: UIButton) { do { // this call is where the custom view from the xcframework should appear       let result = try MyEnum.myFunction(self)       }       catch let error {       print(error.localizedDescription)       } } } I'm using the semaphore to wait for the timer in MyView to fire which would cause the KVC to invoke. Not sure if this is the best way, but I'm blocked and can't figure out why the view only appears after an Error is thrown from myFunc. Any guidance appreciated.
Posted
by craigaps.
Last updated
.
Post marked as solved
1 Replies
1k Views
Hi I want to prompt for FaceID or TouchID before creating the private key in the Secure Enclave. And again when the key is recreated. I might be misinterpreting the documentation wrong, but I thought passing in LAContext instance to the authenticationContext parameter does this for you in both create and recreate use cases. For example: swift let authContext = LAContext() let accessControl = SecAccessControlCreateWithFlags( nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, [.privateKeyUsage, .biometryCurrentSet], nil)! let key0 = try! SecureEnclave.P256.Signing.PrivateKey( accessControl: accessControl, authenticationContext: authContext) let key1 = try! SecureEnclave.P256.Signing.PrivateKey( dataRepresentation: key0.dataRepresentation, authenticationContext: authContext) I was expecting a biometry prompt to appear twice, on create and on recreate CryptoKit operations - no authentication prompt appears on an iPhoneX 14.3 with FaceID enrolled and enabled. Same result in the simulator. Read a few articles all suggesting the above code snippet is what you need to do, but I'm not seeing the desired result. Appreciate any help with this 🙏
Posted
by craigaps.
Last updated
.
Post marked as solved
7 Replies
10k Views
HiUsing the newer methods in the SDK for iOS 10, I can generate private and public keys, with the private key residing in the Keychain. The public key is exported.Here's my code thus far: func createKeyPair(_ keyName: String, authenticationRequired: SecAccessControlCreateFlags? = nil, completion: (_ success: Bool, _ publicKeyData: Data?) -> Void) { guard !keyName.isEmpty else { NSLog("\tNo keyname provided.") return completion(false, nil) } var error: Unmanaged<CFError>? // Private key parameters var privateKeyParams: [String: Any] = [ kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: keyName ] // If we are using a biometric sensor to access the key, we need to create an SecAccessControl instance. if authenticationRequired != nil { guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, authenticationRequired!, &error) else { NSLog("\tError: %@", error!.takeRetainedValue().localizedDescription) completion(false, nil) return } privateKeyParams[kSecAttrAccessControl as String] = accessControl } / let parameters: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: 2048, kSecPrivateKeyAttrs as String: privateKeyParams ] // Global parameters for our key generation guard let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error) else { NSLog("\tError generating keypair. %@", "\(error!.takeRetainedValue().localizedDescription)") return completion(false, nil) } // Generate the keys. guard let publicKey = SecKeyCopyPublicKey(privateKey) else { NSLog("\tError obtaining public key.") return completion(false, nil) } // Get the public key. guard let privateKeyData = SecKeyCopyExternalRepresentation(privateKey, nil) else { NSLog("\tError obtaining export of private key.") return completion(false, nil) } print("\nPrivate key: \(String(describing: exportPublicKey(privateKeyData as Data)))") // Extract the public key for export. guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) else { NSLog("\tError obtaining export of public key.") return completion(false, nil) } completion(true, publicKeyData as Data) } public func exportPublicKey(_ rawPublicKeyBytes: Data, base64EncodingOptions: Data.Base64EncodingOptions = []) -> String? { return rawPublicKeyBytes.base64EncodedString(options: base64EncodingOptions) } // Call the function like so. _ = createKeyPair(keyName) { (status, data) in if status { print("exporting public key: \(String(describing: exportPublicKey(data!)))") } }If I've understood the documentation, SecKeyCopyExternalRepresentation says that the method returns data in the PCKS #1 format for an RSA key. From the various forums, I'm lead to beleive that simply base64 encoding to a string the output of SecKeyCopyExternalRepresentation is all that is required to export the public key in PEM format (without BEGIN RSA PUBLIC KEY and END RSA PUBLIC KEY)When the public key is used to validate some signed data in a Java app, the public key fails to load with invalid key errors... Anyone provide some guidance on this?Thanks
Posted
by craigaps.
Last updated
.
Post not yet marked as solved
4 Replies
744 Views
HiI have a protocol as follows:protocol Profile: Codable, Identifiable { var id: String { get } var name: String { get } }With 2 implemenations as follows:struct Customer: Profile { let id: String let name: String let country: String } struct Contractor: Profile { let id: String let name: String let trade: String let companyName: String }I have a struct that encapsulates either the customer or contractor, but I don't what type of profile it will be at initialization time. So something like:final class UserData: ObservableObject, Codable { var account: Profile? }But the code doesn't compile with the error:Protocol 'Profile' can only be used as a generic constraint because it has Self or associated type requirements.How I'd like to use UserData is by:var user = UserData() user.account = getAccount() func getAccount() -> Profile? { // decode JSON from file, returning a Custoemr or Contractor return Customer(id: "123", name: "Bill", country: "USA") }I'm struggling to assign account to an optional protocol. Appreciate any help and guidence.Thanks
Posted
by craigaps.
Last updated
.
Post marked as solved
3 Replies
1.2k Views
HiI'm trying to display a sheet when the app first launches, similiar to when you upraded iOS to 13 and tapped say reminders.But I'm struggling to get with working with SwiftUI, here is a snippet of the code. It essentially crashes the app.import SwiftUI struct ContentView: View { @State private var showingSheet = false var body: some View { return self.sheet(isPresented: $showingSheet) { RegisterHome() } } } struct RegisterHome: View { var body: some View { NavigationView { Text("Register") .navigationBarTitle("Register") } } }Any thoughts would be very much appreciated.Thanks, Craig
Posted
by craigaps.
Last updated
.
Post marked as solved
6 Replies
1.4k Views
HiI'm using enum and wanted to write an extension to expose additional case values. Just confirming that this is not possible in Swift 5.1. I was thinking something like:import CryptoKit extension CryptoKitError { enum `Self` : Error { /// The data used to deserialized a key with `SecKeyCreateWithData` was incorrect. case incorrectKeyData /// The generation of the failed. case keyFailure } }The closest usage I example is:throw CryptoKitError.Self.keyFailureWhat I'd really want is:throw CryptoKitError.keyFailureThanks
Posted
by craigaps.
Last updated
.
Post marked as solved
1 Replies
7.2k Views
I have a framework project built in Xcode 10, Swift 5 and targeting iOS 11. I've opened the project up in Xcode 11 BETA 4 and executed a build via the command line. I set the Xcode Location setting to Command Line Tools: Xcode 11.0 (11M374r). Here is my xcodebuild arguments:xcodebuild -configuration Release -target MySDKKit -sdk iphoneos -scheme "My SDK Build" -derivedDataPath ./build clean buildIn the project itself, I have the following:User-Defined BITCODE_GENERATION_MODE Debug marker Release bitcodeThe rest of the project build settings are pretty much out of the box. The Valid Architectures arm64 arm64e armv7 armv7sSo here is the error:ld: symbol(s) not found for architecture arm64clang: error: linker command failed with exit code 1 (use -v to see invocation)** BUILD FAILED **The following build commands failed: Ld /Users/craig/Documents/Xcode/sdk-ios/MySDKKit/build/Build/Products/Release-iphoneos/MySDKKit.framework/MySDKKit normal arm64If I remove the Bitcode setting the project builds fine, but I can;t make an archive in an app project. If I enable Bitcode and target iOS 13, the build will also build without issue.Any ideas?Many thanksCraig
Posted
by craigaps.
Last updated
.
Post marked as solved
2 Replies
2.5k Views
HiI'm trying to figure out why the compiler is throwing this error at me:Cannot convert value of type '((Bool) -> Void) -> ()' to expected argument type '(Bool) -> Void'Here is my struct and initialization:struct Item { var title = String() var didFail = Bool() var execute: ((Bool) -> Void) } func doSomething(completion: @escaping (Bool) -> Void) { completion(true) } var item = Item(title: "Fred", didFail: false, execute: doSomething) item.execute { result in print("Result: \(result)") }Any ideas as to why this error might be happening. I refactored the execute to take an argument and no closure and it worked fine; but I'd really like to use the callback approach.Many thanksCraig
Posted
by craigaps.
Last updated
.