Click “like” to see, wechat search [iOS growth refers to north] to guide the book. Welcome to share, please feel free to ask any questions

Apple Silicon

In this chapter, we look at crashes on Apple Silicon Macs, such as crashes caused by the use of Rosetta translation systems and crashes caused by unmodified iOS applications running on macOS. In addition, we’ll look at new types of crashes that can be caused by multi-architecture code that supports both ARM and Intel cpus.

What is the Apple Silicon Mac?

Apple Silicon says the chip design comes from Apple, not a third party. Apple’s A-series chips can be considered Apple chips. However, this chapter focuses on Apple Silicon Macs. These started with the Apple M1 chip. The reason these Macs are not called ARM-based Macs is probably because Apple has made significant contributions at the design level while still conforming to the ARM ABI. When switching from Intel-based Macs to Apple Silicon Macs, this gives customers better marketing benefits, such as longer battery life and higher performance.

What is the Rosetta?

Rosetta is an instruction translator for Apple Silicon Macs. When an application has Intel instructions as part of its binary code, it can convert them to ARM instructions and then run them. Think of it as an AOT compiler. The technology’s roots go back even further, when the MAC was transitioning from PowerPC chips to Intel chips. Apple in Transitive Technologies Ltd. The first version of Rosetta was developed with the help of technology from The Internet. In the second version of Rosetta, our system allows Intel instructions to be pre-translated into ARM instructions on a per-process basis and then run at native speed.

Rosetta binaries

On Apple Silicon Macs, Rosetta software resides

/Library/Apple/usr/libexec/oah
Copy the code

In this directory are the runtime engine runtime_t8027, the translator oahd-helper, the command line tool translate_tool, and other tools. Its operations are basically transparent to the end user, except for lower startup latency or slightly lower performance. From a crash analysis point of view, we can see it in terms of memory usage, exception helpers, and runtime helpers.

Limitations of Rosetta

Rosetta is a powerful system, but it has some limitations. These focus on high-performance multimedia applications and operating system virtualization solutions.

Rosetta does not include the following features:

  • Kernel extensions
  • x86_64Virtualization Support
  • Vector instructions, such as AVX, AVX2 and AVX512

Interestingly, Rosetta supports just-in-time compilation of applications. These applications are special because they generate and then execute the code themselves. Most applications have only fixed read-only code (program text) that is then executed, and their data is mutable (but not executable). This is probably because JIT is a common technique for JavaScript runtime.

Apple recommends checking optional hardware features before calling code that uses this feature. We can run sysctl hw | grep optional to determine what are the optional hardware platform support. In the code, we can call the sysctlByName method to do the same thing.

Enforce Rosetta

If we use standard Build options for our projects by default, we will Only see native binaries when we set Build Active Architecture Only to Yes for Debug and No for Release builds and then Debug. This is because when debugging, we don’t want to waste time building an architecture that isn’t relevant to the machine we’re testing.

If we do an Archive build, Product > Archive, and select Distribute App we end up with a distributable version. By default, this will be Fat Binary \index{file! Fat} (which we call Fat binary) files, x86 and ARM64 are available in multi-architecture binaries.

Once we have a Fat Binary File, we can use the Finder application to right click on File Info and set Rosetta to perform the translation of our Binary so that on an Apple Silicon Mac, The Intel instructions will be translated from the Fat Binary.

Sample translated application

The working example for this chapter is the icdab_thread program. You can find it online. The program tries to call thread_set_state, and then 60 seconds later calls Abort to actively crash. It doesn’t actually have a way to do that because of recent security enhancements to macOS to prevent the use of such apis, which are malware attack vectors. Still, the program is interesting because a closely related part of task_for_pid is called multiple times during the crash.

We have modified the command line executable, ICdab_thread, to an application that only calls the same underlying code. This application is icdab_rosetta_thread. This is because UNIX command-line executables are not suitable for running converted programs, whereas applications can.

icdab_rosetta_threadLipo information

The following command shows that our application supports both ARM and Intel instructions.

# lipo -archs
 icdab_rosetta_thread.app/Contents/MacOS/icdab_rosetta_thread
x86_64 arm64
Copy the code

The translated program crashes

If we run the icdab_rosetta_thread application and click Start Threads Test, after one minute the application crashes. Comparing crash analysis between native and translated cases, we can find differences in crash reports.

Code type

Code Type:             ARM-64 (Native)
Copy the code

When run locally, it becomes translated

Code Type:             X86-64 (Translated)
Copy the code

A thread dump

The crashed thread (and other threads) looks very similar, except that the pointer is based on a higher pointer in the translated case. For native crashes, we have:

Thread 1 Crashed:: Dispatch queue: com.apple.root.default-qos
0   libsystem_kernel.dylib              0x00000001de3015d8
 __pthread_kill + 8
1   libsystem_pthread.dylib             0x00000001de3accbc
 pthread_kill + 292
2   libsystem_c.dylib                   0x00000001de274904 abort
 + 104
3   perivalebluebell.com.icdab-rosetta-thread  
 0x00000001002cd478 start_threads + 244
4   perivalebluebell.com.icdab-rosetta-thread  
 0x00000001002cd858 thunk for @escaping @callee_guaranteed () ->
 () + 20
5   libdispatch.dylib                   0x00000001de139658
 _dispatch_call_block_and_release + 32
6   libdispatch.dylib                   0x00000001de13b150
 _dispatch_client_callout + 20
7   libdispatch.dylib                   0x00000001de13e090
 _dispatch_queue_override_invoke + 692
8   libdispatch.dylib                   0x00000001de14b774
 _dispatch_root_queue_drain + 356
9   libdispatch.dylib                   0x00000001de14bf6c
 _dispatch_worker_thread2 + 116
10  libsystem_pthread.dylib             0x00000001de3a9110
 _pthread_wqthread + 216
11  libsystem_pthread.dylib             0x00000001de3a7e80
 start_wqthread + 8
Copy the code

In the case of post-translation collapse, yes

Thread 1 Crashed:: Dispatch queue: com.apple.root.default-qos
0   ???                                 0x00007fff0144ff40 ???
1   libsystem_kernel.dylib              0x00007fff6bdc4812
 __pthread_kill + 10
2   libsystem_c.dylib                   0x00007fff6bd377f0 abort
 + 120
3   perivalebluebell.com.icdab-rosetta-thread  
 0x0000000100d1c5ab start_threads + 259
4   perivalebluebell.com.icdab-rosetta-thread  
 0x0000000100d1ca1e thunk for @escaping @callee_guaranteed () ->
 () + 14
5   libdispatch.dylib                   0x00007fff6bbf753d
 _dispatch_call_block_and_release + 12
6   libdispatch.dylib                   0x00007fff6bbf8727
 _dispatch_client_callout + 8
7   libdispatch.dylib                   0x00007fff6bbfad7c
 _dispatch_queue_override_invoke + 777
8   libdispatch.dylib                   0x00007fff6bc077a5
 _dispatch_root_queue_drain + 326
9   libdispatch.dylib                   0x00007fff6bc07f06
 _dispatch_worker_thread2 + 92
10  libsystem_pthread.dylib             0x00007fff6be8c4ac
 _pthread_wqthread + 244
11  libsystem_pthread.dylib             0x00007fff6be8b4c3
 start_wqthread + 15
Copy the code

Notice that in the translated case, the actual line of code in thread stack 0 is?? . Presumably this is the actual translation code synthesized by Rosetta.

In addition, in the translated case, we have two more threads, the exception server and the runtime environment:

Thread 3:: com.apple.rosetta.exceptionserver
0   runtime_t8027                       0x00007ffdfff76af8
 0x7ffdfff74000 + 11000
1   runtime_t8027                       0x00007ffdfff803cc
 0x7ffdfff74000 + 50124
2   runtime_t8027                       0x00007ffdfff82738
 0x7ffdfff74000 + 59192

Thread 4:
0   runtime_t8027                       0x00007ffdfffce8ac
 0x7ffdfff74000 + 370860
Copy the code

Crashed thread status register

In the native example, we get the thread status register:

Thread 1 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000000   x1: 0x0000000000000000   x2:
 0x0000000000000000   x3: 0x0000000000000000
    x4: 0x000000000000003c   x5: 0x0000000000000000   x6:
 0x0000000000000000   x7: 0x0000000000000000
    x8: 0x00000000000005b9   x9: 0xb91ed5337c66d7ee  x10:
 0x0000000000003ffe  x11: 0x0000000206c1fa22
   x12: 0x0000000206c1fa22  x13: 0x000000000000001e  x14:
 0x0000000000000881  x15: 0x000000008000001f
   x16: 0x0000000000000148  x17: 0x0000000200e28528  x18:
 0x0000000000000000  x19: 0x0000000000000006
   x20: 0x000000016fbbb000  x21: 0x0000000000001707  x22:
 0x000000016fbbb0e0  x23: 0x0000000000000114
   x24: 0x000000016fbbb0e0  x25: 0x000000020252d184  x26:
 0x00000000000005ff  x27: 0x000000020252d6c0
   x28: 0x0000000002ffffff   fp: 0x000000016fbbab70   lr:
 0x00000001de3accbc
    sp: 0x000000016fbbab50   pc: 0x00000001de3015d8 cpsr:
 0x40000000
   far: 0x0000000100ff8000  esr: 0x56000080
Copy the code

In the translated case, there is also a thread status register:

Thread 1 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x000000030600b000  rcx:
 0x0000000000000000  rdx: 0x0000000000000000
  rdi: 0x0000000000000000  rsi: 0x0000000000000003  rbp:
 0x0000000000000000  rsp: 0x000000000000003c
   r8: 0x000000030600ad40   r9: 0x0000000000000000  r10:
 0x000000030600b000  r11: 0x00007fff6bd37778
  r12: 0x0000000000003d03  r13: 0x0000000000000000  r14:
 0x0000000000000006  r15: 0x0000000000000016
  rip: <unavailable>  rfl: 0x0000000000000287
Copy the code

Translated code information

In the translated case, we’ll get more information that might be useful to engineers working on debugging Rosetta:

Translated Code Information:
  tmp0: 0xffffffffffffffff tmp1: 0x00007fff0144ff14 tmp2:
 0x00007fff6bdc4808
Copy the code

Summary of external modifications

In the native example, we see:

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 914636
    thread_create: 0
    thread_set_state: 804
Copy the code

Our code tried to call thread_set_state but failed (not under any platform configuration due to macOS restrictions).

Then let’s look at the translated example:

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 1
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 915091
    thread_create: 0
    thread_set_state: 804
Copy the code

We see almost the same statistics, but interestingly, we set task_for_PID to 1. Thus, the translation environment makes minimal observation/modification of the translation process.

Virtual memory area

The translated version of the program has higher RAM usage than the native version.

In the native case, we can see:

                                VIRTUAL   REGION
REGION TYPE                        SIZE    COUNT (non-coalesced)
===========                     =======  =======
TOTAL                              1.7G     2053
TOTAL, minus reserved VM space     1.3G     2053
Copy the code

And the translated situation is:

REGION TYPE SIZE COUNT (non - coalesced) = = = = = = = = = = = = = = = = = = = = = = = = = TOTAL 5.4 G 1512 TOTAL, Minus reserved VM space 5.1g 1512Copy the code

Note that in the post-translation case, we provide additional virtual memory areas for Rosetta:

Rosetta Arena                     2048K        1
Rosetta Generic                    864K       19
Rosetta IndirectBranch             512K        1
Rosetta JIT                      128.0M        1
Rosetta Return Stack               192K       12
Rosetta Thread Context             192K       12
Copy the code

Rosetta collapse

Rosetta is a powerful translation system. But it can’t translate all x86-64 instructions. For example, vector instructions cannot be translated and crash when encountered.

Before diagnosing specific problems, it is worthwhile to be familiar with Apple’s Porting Guide, as this can help us come up with reasonable assumptions about why the program might crash.

icdab_avxVector instruction crash

We crashed when we encountered Intel AVX vector instructions on an Apple Silicon Mac running an application using translation. We demonstrate this with a sample application, ICdab_avx.

The crash code type will be:

Code Type:             X86-64 (Translated)
Copy the code

The crash type will be EXC_BAD_INSTRUCTION as follows:

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [26823]
Copy the code

In our case, the thread state at crash is:

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000001  rbx: 0x0000600001fcf5c0  rcx:
 0x00007f87d143f8c0  rdx: 0x00007f87d143f8c0
  rdi: 0x00000001047d6fa0  rsi: 0x00000001047d770a  rbp:
 0x000000030d132ab0  rsp: 0x000000030d132ab0
   r8: 0x0000000000000003   r9: 0x0000000104b0e000  r10:
 0x00000001047dc702  r11: 0x00000001047d57d0
  r12: 0x00006000012d5100  r13: 0x00007fff6a9d4000  r14:
 0x00007f87d143f8c0  r15: 0x00000001047d770a
  rip: 0x00000001047d56cb  rfl: 0x0000000000000206
Copy the code

The application binaries (program text) are loaded as follows:

Binary Images: 0 x1047d4000 x1047d7fff 0 + perivalebluebell.com.icdab-avx (1.0 1) < 3 d9e0ded - 2 c66-30 ee - AC6C - 7 c426246332e > /Users/USER/Desktop/*/icdab_avx.app/Contents/MacOS/icdab_avxCopy the code

If we find that Apple Silicon Macs crash our apps in this way, we can quickly search for any vector instruction if we have such suspicions.

# objdump -d icdab_avx.app/Contents/MacOS/icdab_avx | grep vmov |
 head
100004527: c5 fa 10 84 24 a4 00 00 00      vmovss    164(%rsp),
 %xmm0
100004530: c5 fa 10 8c 24 a0 00 00 00      vmovss    160(%rsp),
 %xmm1
10000453f: c5 fa 10 8c 24 a8 00 00 00      vmovss    168(%rsp),
 %xmm1
10000454e: c5 fa 10 8c 24 ac 00 00 00      vmovss    172(%rsp),
 %xmm1
10000455d: c5 fa 10 8c 24 b4 00 00 00      vmovss    180(%rsp),
 %xmm1
100004566: c5 fa 10 94 24 b0 00 00 00      vmovss    176(%rsp),
 %xmm2
100004575: c5 fa 10 94 24 b8 00 00 00      vmovss    184(%rsp),
 %xmm2
100004584: c5 fa 10 94 24 bc 00 00 00      vmovss    188(%rsp),
 %xmm2
100004593: c5 f8 29 8c 24 90 00 00 00      vmovaps    %xmm1,
 144(%rsp)
10000459c: c5 f8 29 84 24 80 00 00 00      vmovaps    %xmm0,
 128(%rsp)
Copy the code

But, to be more precise, we can use instruction Pointers at crash time. As we see from the state of the crashed thread, we have:

  rip: 0x00000001047d56cb  rfl: 0x0000000000000206
Copy the code

We can see from Binary Images that the program is loaded at address 0x1047d4000.

Using the technique we discussed in the Symbolification section, we can load the ICdab_avx binary in Hopper, changing the base address of the binary to 0x1047d4000, Then go to the instruction pointer RIP and address 0x00000001047D56CB.

Then, we see the assembly dump:

_compute_delta:
push       rbp          ; CODE
 XREF=_$s9icdab_avx14ViewControllerC31runVectorOperationsButtonAc
tionyySo12NSButtonCellCF+32
mov        rbp, rsp
and        rsp, 0xffffffffffffffe0
sub        rsp, 0x160
mov        dword [rsp+0x160+var_A4], 0x40000000
mov        dword [rsp+0x160+var_A8], 0x40800000
mov        dword [rsp+0x160+var_AC], 0x40c00000
mov        dword [rsp+0x160+var_B0], 0x41000000
mov        dword [rsp+0x160+var_B4], 0x41200000
mov        dword [rsp+0x160+var_B8], 0x41400000
mov        dword [rsp+0x160+var_BC], 0x41600000
mov        dword [rsp+0x160+var_C0], 0x41800000
vmovss     xmm0, dword [rsp+0x160+var_BC]
vmovss     xmm1, dword [rsp+0x160+var_C0]
Copy the code

As a result, although we didn’t find the exact instructions of failure, but found the error function compute_delta, it is located in runVectorOperationsButtonAction method, it seems to have been an inline to this version of binary file. Nevertheless, we have had enough help to explore the binaries in the relevant areas and confirm that the vector operation VMOVSS has taken place. Rosetta does not support this feature.

The original code causing the problem is:

Void compute_delta() {/* Initialize the two argument vectors */ __m256 evens = _mm256_set_ps(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0); __m256 odds = _mm256_set_ps (1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0); /* Compute the difference between the two vectors */ __m256 result = _mm256_sub_ps(evens, odds); /* Display the elements of the result vector */ float* f = (float*)&result; printf("%f %f %f %f %f %f %f %f\n", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]); return; }Copy the code

To avoid this problem, we should use a useful method to check whether the current environment supports AVX, as follows:

bool avx_v1_supported() { int ret = 0; size_t size = sizeof(ret); if (sysctlbyname("hw.optional.avx1_0", &ret, &size, NULL, 0) == -1) { if (errno == ENOENT) return false; return false; } bool supported = (ret ! = 0); return supported; }Copy the code

This function returns true if AVX version 1 is supported (and there are no errors in retrieving the information).

Run iOS on a Mac

Since Apple Silicon Macs and iOS devices share the same ARM CPU architecture, Apple provides additional features. Unmodified iOS apps may run on ARM-based macOS. To that end, ARM-based macOS has some special iOS support libraries.

We can think of macOS (subject) as providing the supporting libraries and frameworks, providing the UIKit that iOS (object) applications expect.

When such an application crashes, we get a crash report, which is a macOS crash report, but most of the details involve the iOS library.

icdab_wrapIOS app crashes on macOS

If we run the iOS app ICdab_wrap on an Apple Silicon Mac, it loads normally because macOS provides the UIKit framework, and ICdab_wrap assumes that the framework already exists. The application is designed to demonstrate a problem that unpacking Nil is optional.

When it crashes, we can see:

Code Type:             ARM-64 (Native)
Parent Process:        ??? [1]
Responsible:           icdab_wrap [2802]
User ID:               501
Copy the code

This indicates that the application is running native code, not translated code.

Date/Time:             2020-11-14 11:58:17.668 +0000
OS Version:            Mac OS X 10.16 (20A5343i)
Report Version:        12
Anonymous UUID:        0118DF8D-2876-0263-8668-41B1482DDC38
Copy the code

That means we’re obviously running on a Mac.

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BREAKPOINT (SIGTRAP)
Exception Codes:       EXC_ARM_BREAKPOINT at 0x00000001c6c8f1f0
 (brk 1)
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Trace/BPT trap: 5
Termination Reason:    Namespace SIGNAL, Code 0x5
Terminating Process:   exc handler [2802]

Application Specific Information:
dyld3 mode
Fatal error: Unexpectedly found nil while implicitly unwrapping
 an Optional value: file icdab_wrap/PlanetViewController.swift,
 line 45
Copy the code

This means the program crashed while unpacking the Nil option.

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib                  0x00000001c6c8f1f0
 closure #1 in closure #1 in closure #1 in
 _assertionFailure(_:_:file:line:flags:) + 404
1   libswiftCore.dylib                  0x00000001c6c8f1f0
 closure #1 in closure #1 in closure #1 in
 _assertionFailure(_:_:file:line:flags:) + 404
2   libswiftCore.dylib                  0x00000001c6c8e660
 _assertionFailure(_:_:file:line:flags:) + 488
3   www.perivalebluebell.icdab-wrap     0x0000000104937da4
 PlanetViewController.imageDownloaded(_:) + 196
 (PlanetViewController.swift:45)
.
.
.

16  com.apple.AppKit                    0x0000000189740824
 _DPSNextEvent + 880
17  com.apple.AppKit                    0x000000018973f1fc
 -[NSApplication(NSEvent)
 _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1300
18  com.apple.AppKit                    0x00000001897313c4
 -[NSApplication run] + 600
19  com.apple.AppKit                    0x0000000189703550
 NSApplicationMain + 1064
20  com.apple.AppKit                    0x00000001899e92f8
 _NSApplicationMainWithInfoDictionary + 24
21  com.apple.UIKitMacHelper            0x00000001bd9a6038
 UINSApplicationMain + 476
22  com.apple.UIKitCore                 0x00000001d333d1b0
 UIApplicationMain + 2108
23  www.perivalebluebell.icdab-wrap     0x0000000104933a38 main +
 88 (AppDelegate.swift:12)
24  libdyld.dylib                       0x00000001c758ca50 start
 + 4
Copy the code

This indicates that when the program is loaded libdyld. Dylib, its expected UIKit UIKitCore is implemented through UIKitMacHelper support layer.

Binary Images: 0 x10492c000 x10493bfff 0 + www.perivalebluebell.icdab-wrap (1.0 1) < E9A2E2CC b0 E879 to 37-820 - c - F336DF2AACDA > /Users/USER/Library/Developer/Xcode/DerivedData/icdab-gbtgrhpqeh gqogaglrpuvzajteku/Build/Products/Debug-iphoneos/icdab_wrap.app/i cdab_wrap 0x104a1c000 - 0x104a27fff libobjc-trampolines.dylib (817) <4A2C66DE-9358-3AE9-A69F-36687DB19CE3> /usr/lib/libobjc-trampolines.dylib 0x104b34000 - 0x104baffff dyld (828) <7A9F335B-50E3-3018-A9CC-26E57B61D907> /usr/lib/dyld . . 0x189700000 - 0x18a400fff Com.apple.appkit (6.9-2004.102) < 96941aAC-01D7-36e7-9253-2C1187864719 > / System/Library/Frameworks/AppKit framework Versions/C/AppKit.. x1bd77f000 0-0 x1bd9a1fff com. Apple. UIFoundation (1.0) - 714) <D3335C2E-2366-30AD-A5F3-6058164D69EE> /System/Library/PrivateFrameworks/UIFoundation.framework/Version S /A/UIFoundation 0x1bd9a2000-0x1Bda37ffF com.apple.UIKitMacHelper (1.0-3979.1.400) <F2F6D8F7-8178-3113-856E-F99614A4F13E> /System/Library/PrivateFrameworks/UIKitMacHelper.framework/Versi Ons /A/UIKitMacHelper 0x1bda38000-0x1Bda4bfff com.apple.UIKitServices (1.0-1) < d8c4d101-a04C-37e6-87A3-6ad9adFec787 > /System/Library/PrivateFrameworks/UIKitServices.framework/Versio ns/A/UIKitServices . . 0x1c9b1b000 - 0x1c9b1bfff Com. Apple. MobileCoreServices (1112.0.10-1112.0.10) < 992 daec7-6964-3686 - b353d925 A910-4365 > /System/iOSSupport/System/Library/Frameworks/MobileCoreServices. framework/Versions/A/MobileCoreServices . . 0x1d333a000 -0x1D462FFFF com.apple.UIKitCore (1.0-3979.1.400) < 023078DD-44DA-3a11-82CA-12F8412661A2 > /System/iOSSupport/System/Library/PrivateFrameworks/UIKitCore.fr amework/Versions/A/UIKitCore . . 0x1d72fa000 - 0x1d7337fff libswiftUIKit.dylib (15) <68377BCA-6493-3E34-920E-0765BD07F2A7> /System/iOSSupport/usr/lib/swift/libswiftUIKit.dylibCopy the code

In most cases, these crashes can be analyzed as directly as crashes on iOS. The problem is most likely due to the different physical environment. For example, iOS devices have gyroscopes, while macOS devices do not.

Support iOS apps on Mac

Apple provides guidance on best practices for deploying iOS applications on the Mac. You can perform the following operations:

  1. If you are sure that your iOS application is not suitable for macOS. You can unconfigure it in App Store Connect.
  2. Allows applications installed on iOS to be installed on macOS, but adds optional hardware functionality to check availability.
  3. Enhance the application to make it easier for Mac users to use alternative features. For example, add iOS keyboard support.
  4. Add code to detectiOS-on-MacThe scene.
  5. Connect to Mac through Mac Catalyst technology. That means having a great iPadOS app first.
  6. Write pure native macOS applications.

For example, in the application icdab_gyro we will show how to detect ios-on-Mac scenarios:

Let info = ProcessInfo() if #available(iOS 14.0, *) { if info.isiOSAppOnMac { print("We are an iOS app running on a Mac") } }Copy the code

In addition, when using a gyroscope

var motion = CMMotionManager()
Copy the code

And use gyroscopes only when available:

If motion. IsGyroAvailable {self. Motion. GyroUpdateInterval = 1.0/60.0 self. Motion. StartGyroUpdates (.).Copy the code

communication

The article continues to update every week, you can search “iOS growth refers to north” on wechat to read and urge more. Learn together and grow