VNRequest is an abstract base class of the Vision framework that represents a unit of image or video stream analysis. Each type of analysis — face detection, text recognition, barcode search, classification — is implemented as a concrete subclass of VNRequest. According to Apple Developer Documentation (2024), a developer creates a request instance, configures its parameters, passes an image through VNImageRequestHandler, and receives results as an array of VNObservation.
Key Takeaways
VNRequest is a fundamental element of the Vision architecture, implementing the Request-Response pattern for image and video analysis. Each VNRequest subclass is responsible for a specific computer vision task: face detection, text recognition, content classification.
The VNRequest architecture separates “what to analyze” (the request) from “how to process” (the handler). The developer configures the request (analysis type, additional parameters) and passes it to the handler along with the image. The handler executes the request and returns results without requiring the developer to understand the internal ML algorithms.
All VNRequest subclasses follow a unified structure: initialization with an optional completion handler, property configuration (region of interest, accuracy level), and passing to the handler. This makes the API predictable and easily extensible — adding a new type of analysis means creating a new VNRequest subclass.
import Vision
// 1. Create request
let request = VNDetectFaceRectanglesRequest { req, _ in
// 3. Process results
guard let faces = req.results as? [VNFaceObservation]
else { return }
print("Found \\(faces.count) faces")
}
// 2. Execute via handler
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([request])
Key VNRequest properties: regionOfInterest (area of interest on the image to speed up analysis), preferBackgroundProcessing (background mode), revision (algorithm version), and cancellationSupport. Proper configuration of these properties allows optimizing performance for a specific task.
According to Apple WWDC 2024, over 7 years of Vision’s existence, the number of available VNRequest subclasses grew from 8 (iOS 11) to 25+ (iOS 18), covering all major computer vision tasks on mobile devices.
Vision includes over 25 VNRequest subclasses divided into categories: detection, recognition, tracking, and classification. Each subclass inherits VNRequest and adds task-specific properties.
VNDetectFaceRectanglesRequest — face detection in images. Returns VNFaceObservation with bounding box coordinates and confidence. VNDetectHumanRectanglesRequest — similarly for people. VNDetectHumanBodyPoseRequest — human pose estimation (skeletal keypoints).
VNRecognizeTextRequest — text recognition with support for 13 languages and two accuracy levels. VNReadCodeRequest — for specialized codes. VNDetectTextRectanglesRequest — finding text regions without recognition (faster, but only rectangles).
VNClassifyImageRequest — image classification across 1,000 ImageNet categories. VNGenerateImageFeaturePrintRequest — feature vector extraction for image comparison. VNDetectContoursRequest — object contour detection.
| Category | Example Request | Result |
|---|---|---|
| Face Detection | VNDetectFaceRectanglesRequest | VNFaceObservation |
| Text Recognition | VNRecognizeTextRequest | VNRecognizedTextObservation |
| Barcodes | VNDetectBarcodesRequest | VNBarcodeObservation |
| Classification | VNClassifyImageRequest | VNClassificationObservation |
| Tracking | VNTrackObjectRequest | VNDetectedObjectObservation |
| Contours | VNDetectContoursRequest | VNContoursObservation |
VNImageRequestHandler — a handler for static images. It accepts CGImage, CIImage, or Data (JPEG/PNG) and executes one or more VNRequest instances. This is the primary way to use Vision for photos, screenshots, and uploaded images.
VNSequenceRequestHandler — a handler for image sequences (video frames). It accepts the same set of image types but is designed for frame-by-frame processing while maintaining state between frames (necessary for object tracking).
// VNImageRequestHandler for single image
let imageHandler = VNImageRequestHandler(
cgImage: cgImage,
orientation: orientation,
options: [:])
// VNSequenceRequestHandler for video
let sequenceHandler = VNSequenceRequestHandler()
try sequenceHandler.perform([trackingRequest],
on: cgImage)
Important difference: VNSequenceRequestHandler does not support parallel execution of multiple requests — each perform() call processes one set of requests for one frame. For multi-threaded video processing, create separate handler instances for different threads.
VNImageRequestHandler can run on a background queue. Apple recommends DispatchQueue.global(qos: .userInitiated) for interactive scenarios (user awaits results) and .background for batch processing (e.g., analyzing an entire photo library).
VNObservation — the base class for all Vision request results. Each VNObservation subclass contains data specific to the analysis type: bounding box coordinates, recognized text, confidence, unique identifier (uuid), and timestamp (timeRange).
Key VNObservation subclasses: VNFaceObservation (face detection result with bounding box and landmarks), VNRecognizedTextObservation (recognized text with candidates), VNBarcodeObservation (decoded barcode with payload and symbology), VNClassificationObservation (classification category with confidence).
func handleTextResults(request: VNRequest) {
guard let observations = request.results
as? [VNRecognizedTextObservation]
else { return }
for observation in observations {
let bbox = observation.boundingBox
let text = observation.topCandidates(1).first ?? ""
print("\\(text) at \\(bbox)")
}
}
Confidence property (from 0.0 to 1.0) is present in all VNObservation instances and indicates the model’s confidence in the result. Apple recommends discarding observations with confidence < 0.5 for most tasks. For critical applications (medicine, security), the threshold should be raised to 0.8–0.9.
VNObservation also contains timeRange (for video requests) and uuid (unique ID for cross-frame matching). This allows tracking the same object (e.g., a face) across a sequence of video frames.
One of the key advantages of VNRequest is the ability to execute multiple different requests on the same image in a single handler.perform() call. Vision internally optimizes execution order and reuses common computations (e.g., image preprocessing).
This allows obtaining a complete set of data about an image in one pass: simultaneously detect faces, recognize text, find barcodes, and classify content. This approach is significantly more efficient than calling each request sequentially.
import Vision
// Multiple requests in a single array
let faceRequest = VNDetectFaceRectanglesRequest()
let textRequest = VNRecognizeTextRequest()
let barcodeRequest = VNDetectBarcodesRequest()
let classifyRequest = VNClassifyImageRequest()
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([
faceRequest,
textRequest,
barcodeRequest,
classifyRequest
])
// Access results from each request
print("Faces: \\(faceRequest.results?.count ?? 0)")
print("Text blocks: \\(textRequest.results?.count ?? 0)")
Limitations: not all requests can be combined with others. For example, VNGenerateImageFeaturePrintRequest must be executed separately. Apple recommends grouping requests by type (detection, recognition, classification) and testing combinations on target devices.
Performance: combining 3–4 requests in a single perform() is 30–40% faster than sequential execution because Vision reuses shared ML computations and image preprocessing (scaling, color correction).
VNCoreMLRequest is a bridge between Core ML and Vision, allowing any Core ML model to be run as a Vision request. The model is wrapped in VNCoreMLModel, passed to VNCoreMLRequest, and Vision automatically handles image preprocessing (scaling, cropping to model input size).
VNCoreMLRequest inherits VNRequest, so it supports all standard features: regionOfInterest, completion handler, multiple requests. This allows combining a custom ML model with built-in Vision detectors in a single pipeline.
import Vision
import CoreML
// Wrap Core ML model
guard let mlModel = try VNCoreMLModel(
for: MyCustomClassifier().model)
else { return }
// Create VNCoreMLRequest
let coreMLRequest = VNCoreMLRequest(model: mlModel) { request, _ in
guard let results = request.results
as? [VNClassificationObservation]
else { return }
for result in results.prefix(5) {
print("\\(result.identifier): \\(result.confidence)"
}
}
coreMLRequest.imageCropAndScaleOption = .centerCrop
coreMLRequest.regionOfInterest = faceBoundingBox
imageCropAndScaleOption determines how Vision scales the image to model input: .centerCrop (center cropping), .scaleFill (stretching), or .scaleFit (scaling while maintaining aspect ratio). The choice depends on the model type and object position in the image.
Practical example: face detection via VNDetectFaceRectanglesRequest, then classification of each face via VNCoreMLRequest with a custom model (e.g., gender or age estimation). By combining two requests in one perform(), you get a complete face analysis pipeline in a single pass.
Frequently Asked Questions
Yes, every VNRequest has a cancel() property that cancels the request execution. However, cancellation only works before processing begins — if the ML model has already started, cancellation will not interrupt the computation. For reliable cancellation, use DispatchWorkItem.cancel() together with VNRequest.cancel() in the completion handler.
VNDetectFaceRectanglesRequest only finds face bounding rectangles. VNDetectFaceLandmarksRequest additionally identifies 68 facial keypoints (eyes, eyebrows, nose, mouth, contour). VNDetectFaceLandmarksRequest is slower but provides more data for animation, masks, and AR effects. For simple face counting, VNDetectFaceRectanglesRequest is sufficient.
Yes, VNDetectBarcodesRequest is the correct request for all types of barcodes and QR codes. It supports EAN, UPC, Code 39, Code 128, PDF417, Aztec, QR, and other formats. The result is returned in VNBarcodeObservation with payload and symbology. For video streams, use AVCaptureMetadataOutput — it’s faster for live scanning.
Yes, VNImageRequestHandler accepts CIImage via the init(ciImage:options:) initializer. It also supports Data (JPEG/PNG) and NSURL (file path). CIImage is convenient when the image is already loaded through the Core Image pipeline — this avoids unnecessary data copying in memory.
There is no limit on the count, but in practice 3–5 requests is optimal. More than 5 requests can cause increased memory consumption, as each request loads its own ML model. If you need to run 10+ different analyses, split them into 2–3 groups and execute sequentially.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also