Skip to content

Commit 7b7c59c

Browse files
committed
feat(cli,templates): auto-select iOS sim; guard PythonKit
1 parent b3dd731 commit 7b7c59c

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

src/pythonnative/cli/pn.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,33 @@ def run_project(args: argparse.Namespace) -> None:
283283
os.chdir(ios_project_dir)
284284
derived_data = os.path.join(ios_project_dir, "build")
285285
try:
286+
# Detect a simulator UDID to target: prefer Booted; else any iPhone
287+
sim_udid: str | None = None
288+
try:
289+
import json as _json
290+
291+
devices_out = subprocess.run(
292+
["xcrun", "simctl", "list", "devices", "available", "--json"],
293+
check=False,
294+
capture_output=True,
295+
text=True,
296+
)
297+
devs = (_json.loads(devices_out.stdout or "{}").get("devices") or {})
298+
all_devs = [d for lst in devs.values() for d in (lst or [])]
299+
for d in all_devs:
300+
if d.get("state") == "Booted":
301+
sim_udid = d.get("udid")
302+
break
303+
if not sim_udid:
304+
for d in all_devs:
305+
if (d.get("isAvailable") or d.get("availability")) and (d.get("name") or "").lower().startswith("iphone"):
306+
sim_udid = d.get("udid")
307+
break
308+
except Exception:
309+
pass
310+
311+
xcode_dest = ["-destination", f"id={sim_udid}"] if sim_udid else ["-destination", "platform=iOS Simulator"]
312+
286313
subprocess.run(
287314
[
288315
"xcodebuild",
@@ -292,8 +319,7 @@ def run_project(args: argparse.Namespace) -> None:
292319
"ios_template",
293320
"-configuration",
294321
"Debug",
295-
"-destination",
296-
"platform=iOS Simulator,name=iPhone 15",
322+
*xcode_dest,
297323
"-derivedDataPath",
298324
derived_data,
299325
"build",

templates/ios_template/ios_template/ViewController.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
//
77

88
import UIKit
9+
// PythonKit isn't available on iOS by default; guard its use so the
10+
// template builds out of the box and falls back to a native label.
11+
#if canImport(PythonKit)
912
import PythonKit
13+
#endif
1014

1115
class ViewController: UIViewController {
1216

1317
override func viewDidLoad() {
1418
super.viewDidLoad()
19+
#if canImport(PythonKit)
1520
// Attempt Python bootstrap of app.main_page.bootstrap(self)
1621
let sys = Python.import("sys")
1722
if let resourcePath = Bundle.main.resourcePath {
@@ -26,6 +31,7 @@ class ViewController: UIViewController {
2631
} catch {
2732
print("Python bootstrap failed: \(error)")
2833
}
34+
#endif
2935

3036
// Fallback UI if Python import/bootstrap fails
3137
let label = UILabel(frame: view.bounds)

0 commit comments

Comments
 (0)