2025 AI & Machine Learning
WWDC25 · 20 min · AI & Machine Learning
Read documents using the Vision framework
Learn about the latest advancements in the Vision framework. We’ll introduce RecognizeDocumentsRequest, and how you can use it to read lines of text and group them into paragraphs, read tables, etc. And we’ll also dive into camera lens smudge detection, and how to identify potentially smudged images in photo libraries or your own camera capture pipeline.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 2 snippets
Detect tables
/// Process an image and return the first table detected
func extractTable(from image: Data) async throws -> DocumentObservation.Container.Table {
// The Vision request.
let request = RecognizeDocumentsRequest()
// Perform the request on the image data and return the results.
let observations = try await request.perform(on: image)
// Get the first observation from the array.
guard let document = observations.first?.document else {
throw AppError.noDocument
}
// Extract the first table detected.
guard let table = document.tables.first else {
throw AppError.noTable
}
return table
} Parse contacts
/// Extract name, email addresses, and phone number from a table into a list of contacts.
private func parseTable(_ table: DocumentObservation.Container.Table) -> [Contact] {
var contacts = [Contact]()
// Iterate over each row in the table.
for row in table.rows {
// The contact name will be taken from the first column.
guard let firstCell = row.first else {
continue
}
// Extract the text content from the transcript.
let name = firstCell.content.text.transcript
// Look for emails and phone numbers in the remaining cells.
var detectedPhone: String? = nil
var detectedEmail: String? = nil
for cell in row.dropFirst() {
// Get all detected data in the cell, then match emails and phone numbers.
let allDetectedData = cell.content.text.detectedData
for data in allDetectedData {
switch data.match.details {
case .emailAddress(let email):
detectedEmail = email.emailAddress
case .phoneNumber(let phoneNumber):
detectedPhone = phoneNumber.phoneNumber
default:
break
}
}
}
// Create a contact if an email was detected.
if let email = detectedEmail {
let contact = Contact(name: name, email: email, phoneNumber: detectedPhone)
contacts.append(contact)
}
}
return contacts
} Resources
Related sessions
-
17 min -
14 min -
15 min -
19 min