From bc5818f9eb2aaa611402d2f8bf7dde51ada23cc8 Mon Sep 17 00:00:00 2001 From: JSR Date: Thu, 19 Mar 2026 18:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EiOS=E6=A8=A1=E6=8B=9F?= =?UTF-8?q?=E5=99=A8=E9=80=89=E6=8B=A9=E5=B9=B6=E5=90=AF=E5=8A=A8=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + scripts/ios-sim.js | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100755 scripts/ios-sim.js diff --git a/package.json b/package.json index 5073a58..7757b56 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "tauri": "tauri", "tauri:dev": "tauri dev", "tauri:build": "tauri build", + "ios:sim": "node scripts/ios-sim.js", "format": "prettier --write .", "lint": "eslint --cache .", "lint:fix": "eslint --cache . --fix", diff --git a/scripts/ios-sim.js b/scripts/ios-sim.js new file mode 100755 index 0000000..def2602 --- /dev/null +++ b/scripts/ios-sim.js @@ -0,0 +1,82 @@ +#!/usr/bin/env node + +const { execSync, spawn } = require('node:child_process'); +const readline = require('node:readline'); + +function getAvailableDevices() { + const raw = execSync('xcrun simctl list devices available -j', { + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'pipe'], + }); + const parsed = JSON.parse(raw); + const devicesByRuntime = parsed.devices || {}; + const all = []; + + for (const [runtime, devices] of Object.entries(devicesByRuntime)) { + for (const device of devices) { + if (!device.isAvailable) continue; + if (device.name.includes('iPad') || device.name.includes('iPhone')) { + all.push({ + name: device.name, + udid: device.udid, + state: device.state, + runtime, + }); + } + } + } + + all.sort((a, b) => a.name.localeCompare(b.name) || a.runtime.localeCompare(b.runtime)); + return all; +} + +function promptChoice(max) { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + return new Promise((resolve, reject) => { + rl.question('请输入要使用的机型编号: ', (answer) => { + rl.close(); + const idx = Number(answer.trim()); + if (!Number.isInteger(idx) || idx < 1 || idx > max) { + reject(new Error(`无效编号: ${answer}`)); + return; + } + resolve(idx - 1); + }); + }); +} + +async function main() { + const devices = getAvailableDevices(); + + if (devices.length === 0) { + throw new Error('未找到可用 iOS 模拟器,请先在 Xcode 安装模拟器运行时。'); + } + + console.log('可用 iOS 模拟器:'); + devices.forEach((d, i) => { + const runtime = d.runtime.replace('com.apple.CoreSimulator.SimRuntime.', ''); + console.log(`${i + 1}. ${d.name} | ${runtime} | ${d.state} | ${d.udid}`); + }); + + const pickedIndex = await promptChoice(devices.length); + const picked = devices[pickedIndex]; + console.log(`\n已选择: ${picked.name} (${picked.runtime})`); + + const child = spawn('pnpm', ['tauri', 'ios', 'dev', picked.name], { + stdio: 'inherit', + shell: process.platform === 'win32', + }); + + child.on('exit', (code) => { + process.exit(code ?? 1); + }); +} + +main().catch((err) => { + console.error(`执行失败: ${err.message}`); + process.exit(1); +});