iOS 27 introduces GenerateIterativeSegmentationRequest in the Vision framework, enabling interactive object segmentation from a single tap, bounding box, lasso, or scribble input. Users can progressively refine the resulting mask by adding or subtracting points.
• Replaces complex custom ML pipelines — any object in any photo can now be isolated with a single normalized point, no ML expertise required
• Iterative refinement means users can add or remove regions from a mask interactively, enabling photo editing, background removal, and object extraction UX
• Model download is handled through a built-in assetStatus / downloadAssets API, so the feature degrades gracefully before the model is cached
Demonstrates using GenerateIterativeSegmentationRequest to segment a tapped object in a photo, then refine the mask by adding a second point. Shows asset readiness check and mask retrieval.
import Vision
import UIKit
import CoreVideo
final class TapToSegmentViewController: UIViewController {
// MARK: - Asset readiness
func ensureModelReady() async throws {
let status = GenerateIterativeSegmentationRequest.assetStatus
switch status {
case .ready:
print("Model already downloaded.")
case .notDownloaded, .downloading:
print("Downloading segmentation model…")
try await GenerateIterativeSegmentationRequest.downloadAssets()
default:
break
}
}
// MARK: - Segmentation
/// `tapPoint` is in Vision normalized coordinates: origin bottom-left, values 0…1
func segmentObject(
in image: UIImage,
at tapPoint: CGPoint
) async throws -> CVPixelBuffer? {
guard let cgImage = image.cgImage else { return nil }
let handler = ImageRequestHandler(cgImage)
// Initial seed point — tap somewhere on the coffee cup
var request = GenerateIterativeSegmentationRequest()
request.seeds = [
.point(tapPoint, phase: .include)
]
let result = try await handler.perform(request)
let initialMask: CVPixelBuffer = result.pixelBuffer
print("Got initial mask: \(initialMask)")
// Refine: also include a nearby point (e.g., the saucer plate)
let refinementPoint = CGPoint(x: tapPoint.x, y: tapPoint.y - 0.08)
request.seeds.append(
.point(refinementPoint, phase: .include)
)
let refined = try await handler.perform(request)
return refined.pixelBuffer
}
// MARK: - Exclusion example
/// Remove a sub-region from the existing mask (e.g., exclude the cup, keep only coffee)
func refineByExcluding(
in image: UIImage,
includePoint: CGPoint,
excludePoint: CGPoint
) async throws -> CVPixelBuffer? {
guard let cgImage = image.cgImage else { return nil }
let handler = ImageRequestHandler(cgImage)
var request = GenerateIterativeSegmentationRequest()
request.seeds = [
.point(includePoint, phase: .include),
.point(excludePoint, phase: .exclude)
]
let result = try await handler.perform(request)
return result.pixelBuffer
}
}Coordinates use Vision's normalized system with origin at the lower-left corner (not upper-left like UIKit). Lasso stroke width must be at least 1% of the image width or results degrade. Always check assetStatus and call downloadAssets before the first segmentation to avoid runtime failures.
Requires on-device model download before first use; model availability may vary by device capability. Not available on watchOS for this specific API.
More iOS 27 APIs land every week.
Get notified when new capabilities are published — no noise, just signal.