The following sample checks whether the device has a set passcode.
MastgTest.swift
1 2 3 4 5 6 7 8 910111213141516171819202122
importSwiftUIimportLocalAuthenticationstructMastgTest{staticfuncmastgTest(completion:@escaping(String)->Void){ifdevicePasscodeSet(){completion("This device is protected with a passcode ✅")}else{completion("This device doesn't have a passcode ⚠️")}}staticfuncdevicePasscodeSet()->Bool{//UseLAPolicy.deviceOwnerAuthenticationtoverifyifthedevicehasapasscode.//Accordingtodocs:"In iOS, policy evaluation fails with the error passcodeNotSet if the device passcode isn’t enabled"//Ref:https://developer.apple.com/documentation/localauthentication/lapolicy/deviceownerauthenticationreturnLAContext().canEvaluatePolicy(.deviceOwnerAuthentication,error:nil)}}
Interceptor.attach(ObjC.classes.LAContext["- canEvaluatePolicy:error:"].implementation,{onEnter(args){constLAPolicy={1:".deviceOwnerAuthenticationWithBiometrics",2:".deviceOwnerAuthentication"};constpolicy=args[2].toInt32();constpolicyDescription=LAPolicy[policy]||"Unknown Policy";console.log(`\nLAContext.canEvaluatePolicy(${args[2]}) called with ${policyDescription} (${args[2]})\n`);// Use an arrow function so that `this` remains the same as in onEnterconstprintBacktrace=(maxLines=8)=>{console.log("\nBacktrace:");letbacktrace=Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress);for(leti=0;i<Math.min(maxLines,backtrace.length);i++){console.log(backtrace[i]);}}printBacktrace();}});
LAContext.canEvaluatePolicy(0x2)calledwith.deviceOwnerAuthentication(0x2)Backtrace:0x100f58110MASTestApp.debug.dylib!staticMastgTest.devicePasscodeSet()0x100f5802cMASTestApp.debug.dylib!staticMastgTest.mastgTest(completion:)0x100f599d4MASTestApp.debug.dylib!$s10MASTestApp11ContentViewV4bodyQrvg7SwiftUI05TupleD0VyAE0D0PAEE7paddingyQrAE4EdgeO3SetV_12CoreGraphics7CGFloatVSgtFQOyAE6HStackVyAGyAE4TextV_AE6SpacerVAiEEAJyQrAN_ARtFQOyAiEE12cornerRadius_11antialiasedQrAQ_SbtFQOyAiEE10background_9alignmentQrqd___AE9AlignmentVtAeHRd__lFQOyAE6ButtonVyAiEE4fontyQrAE4FontVSgFQOyAiEEAJyQrAN_ARtFQOyAiEEAJyQrAN_ARtFQOyAV_Qo__Qo__Qo_G_AE14LinearGradientVQo__Qo__Qo_tGG_Qo__AiEEAJyQrAN_ARtFQOyAiEEAY_AZQrAQ_SbtFQOyAiEEA__A0_Qrqd___A2_tAeHRd__lFQOyAiEE5frame8minWidth10idealWidth8maxWidth9minHeight11idealHeight9maxHeightA0_QrAR_A5RA2_tFQOyAE06ScrollD0VyAiEEAJyQrAN_ARtFQOyAiEEA21_A22_A23_A24_A25_A26_A27_A0_QrAR_A5RA2_tFQOyAV_Qo__Qo_G_Qo__AE5ColorVQo__Qo__Qo_tGyXEfU_A18_yXEfU_yyScMYccfU_0x19afc6e30SwiftUI!partialapplyforimplicitclosure#2 in implicit closure #1 in WrappedButtonStyle.Body.body.getter0x19b2ddf28SwiftUI!closure#1 in PressableGestureCallbacks.dispatch(phase:state:)0x19b047b98SwiftUI!thunkfor@escaping@callee_guaranteed()->()0x19b047bc0SwiftUI!thunkfor@escaping@callee_guaranteed()->(@out())0x19b047b98SwiftUI!thunkfor@escaping@callee_guaranteed()->()
The output reveals the use of LAcontext.canEvaluatePolicy(0x2) in the app. Policy 0x2 is .deviceOwnerAuthentication.
The test passes because the output shows the runtime use of LAcontext.canEvaluatePolicy(.deviceOwnerAuthentication) which verifies whether the device has passcode set.