Practical tutorials and complete example scripts for automating iOS devices with ControlFloor.
Every automation script starts by connecting to the ControlFloor server and getting a device handle:
from controlfloor import CFConnect
# Connect to the server
conn = CFConnect("wss://your-server:8080/ws", self_signed=True)
conn.login("admin", "your-password")
# Get a specific device
device = conn.getDevice("iPhone-12")
# Or use the first available device
devices = conn.getDevices()
device = devices[0]
The self_signed=True parameter is needed when the server uses
a self-signed TLS certificate. For production setups with real certificates, omit this.
# Launch an app
device.launchApplication("com.apple.mobilesafari")
# Kill and relaunch
device.relaunchApplication("com.example.myapp")
# Check what's running
active = device.getActiveApplication()
print(f"Active app: {active}")
# Kill an app
device.killApplication("com.example.myapp")
# Go to home screen
device.home()Elements are found using accessibility identifiers and labels. The search system supports type filtering, spatial filtering, and timeout-based waiting.
# Find a button by label
button = device.getElement(elementIds=["Sign In"])
# Find a text field by type
field = device.getElement(elementTypes=["textField"])
# Wait for an element to appear (up to 10 seconds)
welcome = device.getElement(elementIds=["Welcome"], timeout=10)
# Find all buttons
buttons = device.getButtons()
# Find named elements (those with accessibility labels)
named = device.getNamedElements()
# Tap an element
device.tap(elementIds=["Submit"])
# Double-tap
device.doubleTap(elementIds=["Photo"])ControlFloor offers two text input methods. Understanding when to use each is important:
typeText — Uses XCTest's native typing. Fast, but may not work in secure fields.tapText — Taps keys using pre-mapped keyboard coordinates. Works everywhere, including secure/password fields.# Focus a text field first
device.tap(elementIds=["Username"])
# Type using XCTest (fast, standard fields)
device.typeText("user@example.com")
# Tab to password field and use tapText (works in secure fields)
device.tap(elementIds=["Password"])
device.tapText("MySecureP@ss123")
# Clear existing text
device.clearCurrentElementText()
# Type special keys
device.typeSpecialKey("return")# Swipe from the center of the screen
device.centerSwipeUp()
device.centerSwipeDown()
device.centerSwipeLeft()
device.centerSwipeRight()
# Swipe on a specific element
device.swipeUp(elementIds=["scrollView"])
# Edge swipe (e.g., open Control Center)
device.edgeSwipeDown()
# Long press
device.tapAndHold(elementIds=["Photo Thumbnail"])
# Force touch / haptic press
device.tapFirm(elementIds=["App Icon"])The element search system supports powerful filtering. You can search by type, spatial position, and combine filters to find exactly the elements you need.
# Get all interactive elements
interactive = device.getInteractiveElements()
# Get elements along a horizontal line (useful for table rows)
row_elements = device.getElementsAlongLine(
x1=0, y1=300, x2=400, y2=300, step=20
)
# Get the full application element tree for debugging
tree = device.getApplicationStructure()
# Check what element is at a specific point
el = device.getElementAtPoint(x=200, y=400)
# Get the currently focused element
focused = device.getElementWithKeyboardFocus()# Take a screenshot
img = device.getScreenshot(format="png")
# Get pixel color at a point
pixel = device.getPixelAtPoint(x=100, y=200)
# Get colors in a region (useful for validating UI state)
region = device.getPixelsInRegion(
x=50, y=100, width=200, height=50
)
# Get color histogram (useful for checking if a region is mostly one color)
histogram = device.getHistogramForRegion(
x=0, y=0, width=375, height=44
)# Download a file to the device
device.startFileDownload(
url="https://example.com/testdata.json",
destination="Documents",
filename="testdata.json"
)
# List files in a directory
files = device.getFileList("Documents")
# Read file contents
data = device.getFileContents("Documents/testdata.json")
# Camera roll operations
from controlfloor.commands import (
download_to_camera_roll, clear_camera_roll
)
download_to_camera_roll(["https://example.com/photo.jpg"])
# Clipboard
from controlfloor.commands import get_clipboard, load_clipboard
load_clipboard("Text to paste")
text = get_clipboard()import time
# Use timeouts to wait for elements
el = device.getElement(elementIds=["Login"], timeout=15)
# Use allow_errors to handle expected failures gracefully
result = device.getElement(
elementIds=["Optional Banner"],
allow_errors=True
)
# Add delays between actions when needed
device.setDelay(0.5) # 500ms between commands
# Use exclusive access for long-running scripts
device.claimExclusiveAccess("Running test suite")
try:
# ... your automation code ...
pass
finally:
device.releaseExclusiveAccess()A complete script that launches an app, logs in, and verifies success.
from controlfloor import CFConnect
# Setup
conn = CFConnect("wss://server:8080/ws", self_signed=True)
conn.login("admin", "password")
device = conn.getDevice("iPhone-12")
device.setDelay(0.3)
# Launch the app fresh
device.relaunchApplication("com.example.myapp")
# Wait for the login screen
device.getElement(elementIds=["Login"], timeout=10)
# Enter credentials
device.tap(elementIds=["Username"])
device.typeText("testuser@example.com")
device.tap(elementIds=["Password"])
device.tapText("SecureP@ss123") # tapText for secure fields
# Tap the login button
device.tap(elementIds=["Sign In"])
# Verify we reached the home screen
home = device.getElement(elementIds=["Home"], timeout=15)
if home:
print("Login successful!")
else:
print("Login failed - home screen not found")Navigate to Settings, find switches, toggle them, and verify state.
from controlfloor import CFConnect
conn = CFConnect("wss://server:8080/ws", self_signed=True)
conn.login("admin", "password")
device = conn.getDevice("iPhone-12")
device.setDelay(0.5)
# Open Settings
device.relaunchApplication("com.apple.Preferences")
device.getElement(elementIds=["Settings"], timeout=10)
# Navigate to Wi-Fi settings
device.tap(elementIds=["Wi-Fi"])
device.getElement(elementIds=["Wi-Fi"], timeout=5)
# Get all switches on screen
switches = device.getSwitches()
print(f"Found {len(switches)} switches")
# Toggle Wi-Fi off
device.disableSwitch(elementIds=["Wi-Fi"])
# Wait and verify
import time
time.sleep(2)
# Toggle Wi-Fi back on
device.enableSwitch(elementIds=["Wi-Fi"])
# Go back to main Settings
device.tap(elementIds=["Settings"]) # back button
print("Settings navigation complete!")Take screenshots, analyze specific regions, and validate visual state.
from controlfloor import CFConnect
conn = CFConnect("wss://server:8080/ws", self_signed=True)
conn.login("admin", "password")
device = conn.getDevice("iPhone-12")
# Take a screenshot
screenshot = device.getScreenshot(format="png")
# Check the color of the status bar region
status_bar = device.getPixelsInRegion(
x=0, y=0, width=375, height=44
)
# Check if a specific button is the expected color
button_pixel = device.getPixelAtPoint(x=187, y=600)
print(f"Button color: {button_pixel}")
# Get color distribution in a region (useful for detecting state)
histogram = device.getHistogramForRegion(
x=20, y=100, width=335, height=200
)
# Check multiple points at once
points_to_check = [
{"x": 100, "y": 200},
{"x": 200, "y": 300},
{"x": 300, "y": 400}
]
colors = device.getPixelsAtPoints(points=points_to_check)
print("Visual validation complete!")Download files, verify they exist, and manage device storage.
from controlfloor import CFConnect
from controlfloor.commands import (
download_files, clear_camera_roll,
download_to_camera_roll, get_clipboard
)
conn = CFConnect("wss://server:8080/ws", self_signed=True)
conn.login("admin", "password")
device = conn.getDevice("iPhone-12")
# Download a test file
device.startFileDownload(
url="https://example.com/sample.pdf",
destination="Documents",
filename="sample.pdf",
overwrite=True
)
# Wait for download to complete
import time
time.sleep(5)
# Verify the file exists
files = device.getFileList("Documents")
print(f"Files in Documents: {files}")
# Download images to camera roll
download_to_camera_roll([
"https://example.com/photo1.jpg",
"https://example.com/photo2.jpg"
])
# Read clipboard
clipboard = get_clipboard()
print(f"Clipboard: {clipboard}")
# Clean up: clear the camera roll
clear_camera_roll()
print("File operations complete!")