Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An AI Skeptic Implements Apple Intelligence - A...

An AI Skeptic Implements Apple Intelligence - ARCtic Swift, Oulu, Finland, March 2025

Sample code: https://github.com/designatednerd/AppleIntelligenceExamples

A review of the current state of AI from someone who's a bit skeptical of the hype, followed by some concrete pointers about how to use the currently (as of March 2025) available features of Apple Intelligence™.

Ellen Shapiro

March 12, 2025
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. An AI Skeptic Implements Apple Intelligence™ ARCtic Swift | Oulu,

    Finland | March 2025 Ellen Shapiro | mastodon.social/designatednerd | figma.com
  2. !

  3. !

  4. !

  5. !

  6. ! "

  7. ! "

  8. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  9. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  10. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  11. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  12. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  13. import ImagePlayground public struct ImagePlaygroundView: View { @Environment(\.supportsImagePlayground) var supportsImagePlayground

    @State private var imagePlaygroundIsPresented: Bool = false @State private var text: String = "" @State var generatedImageURL: URL? private let prompt = "Enter text here..." public var body: some View { VStack { Text("What do you want the image playground to generate?") TextField("Do it!", text: self.$text, prompt: Text(self.prompt)) .textFieldStyle(.roundedBorder) if self.supportsImagePlayground { Button("GENERATE", action: { self.imagePlaygroundIsPresented = true }) } if let generatedImageURL { AsyncImage(url: generatedImageURL) { image in image .resizable().scaledToFit() .frame(width: 300, height: 300) } placeholder: { ProgressView() } } } .imagePlaygroundSheet(isPresented: self.$imagePlaygroundIsPresented, concept: self.text, onCompletion: { url in self.generatedImageURL = url })
  14. // iOS 18+ and friends textView.supportsAdaptiveImageGlyph = true or //

    iOS textView.pasteConfiguration = // something that supports images
  15. // iOS 18+ and friends textView.supportsAdaptiveImageGlyph = true or //

    iOS textView.pasteConfiguration = // something that supports images or // macOS textView.importsGraphics = true
  16. Saving as RTFD let rtfFileWrapper = try self.content.fileWrapper( from: NSRange(location:

    0, length: self.content.length), documentAttributes: [ .documentType: NSAttributedString.DocumentType.rtfd, .characterEncoding: String.Encoding.utf8 ]) let fileURL = URL(filePath: "test.rtfd", directoryHint: .inferFromPath, relativeTo: .documentsDirectory) try rtfFileWrapper.write(to: fileURL, originalContentsURL: nil) via https://stackoverflow.com/a/23607696/681493
  17. RTFD Directory Contents [ // Raw RTF file [docs directory]/test.rtfd/TXT.rtf,

    // HEIC image of the Genmoji™ [docs directory]/test.rtfd/AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic ]
  18. Reading RTFD let directoryURL = URL(filePath: "test.rtfd", relativeTo: .documentsDirectory) let

    loadedString = try NSMutableAttributedString( url: directoryURL, options: [ .documentType: NSAttributedString.DocumentType.rtfd, ], documentAttributes: nil) let wholeRange = NSRange(location: 0, length: loadedString.length) loadedString.addAttributes( [.font: UIFont.systemFont(ofSize: 36)], range: wholeRange)
  19. Reading RTFD let directoryURL = URL(filePath: "test.rtfd", relativeTo: .documentsDirectory) let

    loadedString = try NSMutableAttributedString( url: directoryURL, options: [ .documentType: NSAttributedString.DocumentType.rtfd, ], documentAttributes: nil) let wholeRange = NSRange(location: 0, length: loadedString.length) loadedString.addAttributes( [.font: UIFont.systemFont(ofSize: 36)], range: wholeRange)
  20. Reading RTFD let directoryURL = URL(filePath: "test.rtfd", relativeTo: .documentsDirectory) let

    loadedString = try NSMutableAttributedString( url: directoryURL, options: [ .documentType: NSAttributedString.DocumentType.rtfd, ], documentAttributes: nil) let wholeRange = NSRange(location: 0, length: loadedString.length) loadedString.addAttributes( [.font: UIFont.systemFont(ofSize: 36)], range: wholeRange)
  21. Reading RTFD let directoryURL = URL(filePath: "test.rtfd", relativeTo: .documentsDirectory) let

    loadedString = try NSMutableAttributedString( url: directoryURL, options: [ .documentType: NSAttributedString.DocumentType.rtfd, ], documentAttributes: nil) let wholeRange = NSRange(location: 0, length: loadedString.length) loadedString.addAttributes( [.font: UIFont.systemFont(ofSize: 200)], range: wholeRange)
  22. Saving as HTML let htmlFileWrapper = try self.content.fileWrapper( from: NSRange(location:

    0, length: self.content.length), documentAttributes: [ .documentType: NSAttributedString.DocumentType.html, ]) let fileURL = URL(filePath: "test.html", directoryHint: .inferFromPath, relativeTo: .documentsDirectory) try htmlFileWrapper.write(to: fileURL, originalContentsURL: nil)
  23. HTML Directory Contents [ // The actual HTML that was

    output [docs directory]/test.html/index.html, // The genmoji as a PNG file [docs directory]/test.html/Attachment.png, // The genmoji as an HEIC file [docs directory]/test.html/AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic ]
  24. Output HTML <body> <p class="p1"> <span class="s1">Hello HTML <picture> <source

    srcset="file:///AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic" type="image/x-apple-adaptive-glyph"> <img src="file:///Attachment.png" alt="Orange bird with nerd glasses"> </picture> </span> </p> </body>
  25. Output HTML <body> <p class="p1"> <span class="s1">Hello HTML <picture> <source

    srcset="file:///AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic" type="image/x-apple-adaptive-glyph"> <img src="file:///Attachment.png" alt="Orange bird with nerd glasses"> </picture> </span> </p> </body>
  26. Output HTML <body> <p class="p1"> <span class="s1">Hello HTML <picture> <source

    srcset="file:///AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic" type="image/x-apple-adaptive-glyph"> <img src="file:///Attachment.png" alt="Orange bird with nerd glasses"> </picture> </span> </p> </body>
  27. Output HTML <body> <p class="p1"> <span class="s1">Hello HTML <picture> <source

    srcset="file:///AdaptiveImageGlyph-BD50F0F2-FE0C-4657-AF91-5C898F1DDB120.heic" type="image/x-apple-adaptive-glyph"> <img src="file:///Attachment.png" alt="Orange bird with nerd glasses"> </picture> </span> </p> </body>
  28. import Translation @Observable class LanguageFetcher { var availableLanguages: [LanguagePair] =

    [] private let languageAvailability = LanguageAvailability() let usEnglish = Locale(languageComponents: Locale.Language.Components(identifier: "en_US")) func getAvailableLanguages() async { let availableLanguages = await self.languageAvailability.supportedLanguages for language in availableLanguages { let status = await self.languageAvailability.status( from: language, to: self.usEnglish.language) self.availableLanguages.append(LanguagePair(language: language, status: status)) } } }
  29. import Translation @Observable class LanguageFetcher { var availableLanguages: [LanguagePair] =

    [] private let languageAvailability = LanguageAvailability() let usEnglish = Locale(languageComponents: Locale.Language.Components(identifier: "en_US")) func getAvailableLanguages() async { let availableLanguages = await self.languageAvailability.supportedLanguages for language in availableLanguages { let status = await self.languageAvailability.status( from: language, to: self.usEnglish.language) self.availableLanguages.append(LanguagePair(language: language, status: status)) } } }
  30. import Translation @Observable class LanguageFetcher { var availableLanguages: [LanguagePair] =

    [] private let languageAvailability = LanguageAvailability() let usEnglish = Locale(languageComponents: Locale.Language.Components(identifier: "en_US")) func getAvailableLanguages() async { let availableLanguages = await self.languageAvailability.supportedLanguages for language in availableLanguages { let status = await self.languageAvailability.status( from: language, to: self.usEnglish.language) self.availableLanguages.append(LanguagePair(language: language, status: status)) } } }
  31. import Translation @Observable class LanguageFetcher { var availableLanguages: [LanguagePair] =

    [] private let languageAvailability = LanguageAvailability() let usEnglish = Locale(languageComponents: Locale.Language.Components(identifier: "en_US")) func getAvailableLanguages() async { let availableLanguages = await self.languageAvailability.supportedLanguages for language in availableLanguages { let status = await self.languageAvailability.status( from: language, to: self.usEnglish.language) self.availableLanguages.append(LanguagePair(language: language, status: status)) } } }
  32. import Translation @Observable class LanguageFetcher { var availableLanguages: [LanguagePair] =

    [] private let languageAvailability = LanguageAvailability() let usEnglish = Locale(languageComponents: Locale.Language.Components(identifier: "en_US")) func getAvailableLanguages() async { let availableLanguages = await self.languageAvailability.supportedLanguages for language in availableLanguages { let status = await self.languageAvailability.status( from: language, to: self.usEnglish.language) self.availableLanguages.append(LanguagePair(language: language, status: status)) } } }
  33. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  34. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  35. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  36. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  37. func setUpConfiguration() { // Pass nil for source and/or target

    to let the framework // automatically determine the language pairing. configuration = TranslationSession .Configuration(source: LanguageFetcher.shared.usEnglish.language, target: self.language) }
  38. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  39. import SwiftUI import Translation struct TranslateTextView: View { @State private

    var textToTranslate: String = "" @State private var translatedText: String? @State private var language: Locale.Language? @State private var configuration: TranslationSession.Configuration? var body: some View { VStack(alignment: .center) { Text("Language:") // Picker goes here .onChange(of: self.language) { _, _ in self.setUpConfiguration() } TextField("English to translate", text: self.$textToTranslate, prompt: Text("Enter your English text here")) .textFieldStyle(.roundedBorder) Button { self.translate() } // make it blue with a white label if let translatedText { Text("Translation:") Text(translatedText) // add black border } } .translationTask(configuration) { session in do { // Use the session the task provides to translate the text. let response = try await session.translate(self.textToTranslate) // Update the view with the translated result. self.translatedText = response.targetText } catch { // Handle any errors. } } } // MORE }
  40. Obligatory Summary Slide → Beware of hype - there is

    a lot of it → Beware of Apple Intelligence's limitations
  41. Obligatory Summary Slide → Beware of hype - there is

    a lot of it → Beware of Apple Intelligence's limitations → You're gonna need a real device
  42. Obligatory Summary Slide → Beware of hype - there is

    a lot of it → Beware of Apple Intelligence's limitations → You're gonna need a real device → Genmojis are easy to display, hard to store
  43. Obligatory Summary Slide → Beware of hype - there is

    a lot of it → Beware of Apple Intelligence's limitations → You're gonna need a real device → Genmojis are easy to display, hard to store → Writing tools theoretically needs TK2, not worth the hassle if you've already got tons of stuff in TK1
  44. Obligatory Summary Slide → Beware of hype - there is

    a lot of it → Beware of Apple Intelligence's limitations → You're gonna need a real device → Genmojis are easy to display, hard to store → Writing tools theoretically needs TK2, not worth the hassle if you've already got tons of stuff in TK1 → Look at what your users actually want