I have created an app which uses Vision to extract text from an image and stores this text in a UITextView. What I would like to do is save the extracted text on iCloud so that it can be accessed across all the users devices.
I have created a swift file (shown below) which will save items to iCloud. I will attach my code for the text extraction in a new post below.
Any suggestions in how to merge the text in the UITextView and the items that are stored in iCloud in the code shown below would be greatly appreciated.
Many thanks for your help.
import CloudKit
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
let tableView: UITableView = {
let tableView = UITableView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return tableView
}()
private let database = CKContainer(identifier: "iCloud.MyGroceryList").publicCloudDatabase
var items = [String]()
override func viewDidLoad() {
super.viewDidLoad()
title = "Grocery List"
view.addSubview(tableView)
tableView.dataSource = self
let control = UIRefreshControl()
control.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged)
tableView.refreshControl = control
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add,
target: self,
action: #selector(didTapAdd))
fetchItems()
}
@objc func fetchItems() {
let query = CKQuery(recordType: "GroceryItem",
predicate: NSPredicate(value: true))
database.perform(query, inZoneWith: nil) { [weak self] records, error in
guard let records = records, error == nil else {
return
}
DispatchQueue.main.async {
self?.items = records.compactMap({ $0.value(forKey: "name") as? String })
self?.tableView.reloadData()
}
}
}
@objc func pullToRefresh() {
tableView.refreshControl?.beginRefreshing()
let query = CKQuery(recordType: "GroceryItem",
predicate: NSPredicate(value: true))
database.perform(query, inZoneWith: nil) { [weak self] records, error in
guard let records = records, error == nil else {
return
}
DispatchQueue.main.async {
self?.items = records.compactMap({ $0.value(forKey: "name") as? String })
self?.tableView.reloadData()
self?.tableView.refreshControl?.endRefreshing()
}
}
}
@objc func didTapAdd() {
let alert = UIAlertController(title: "Add Item",
message: nil,
preferredStyle: .alert)
alert.addTextField { field in
field.placeholder = "Enter Name..."
}
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { [weak self] _ in
if let field = alert.textFields?.first, let text = field.text, !text.isEmpty {
self?.saveItem(name: text)
}
}))
present(alert, animated: true)
}
@objc func saveItem(name: String) {
let record = CKRecord(recordType: "GroceryItem")
record.setValue(name, forKey: "name")
database.save(record) { [weak self] record, error in
if record != nil, error == nil {
DispatchQueue.main.asyncAfter(deadline: .now()+2) {
self?.fetchItems()
}
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = view.bounds
}
// MARK: - Table
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
For my A level Computer Science project I have created an app for iOS/iPadOS which allows users to take or select a picture and extract the text from that image.
Using a Mac Catalyst, my app also works well on Mac, however I would like to add some customisation features so that it looks and feels better on a Mac.
I have created a Touch Bar storyboard and was wondering if I could add it to my app, I was thinking of something along the lines of 'If User device = Mac then load TouchBarStoryboard else don't'.
If you have any ideas on how I could implement this, please do let me know.
Below is an image of the storyboard I created for the Touch Bar.
On iOS, my GUI looks like this:
Therefore I thought the Touch Bar would offer the user an alternative to using the mouse when switching between the 5 tabs.
Many thanks for your help.
For my A level Computer Science project I have created an app for iOS/iPadOS which allows users to take or select a picture and extract the text from that image.
Using a Mac Catalyst, my app also works well on Mac, however I would like to add some customisation features so that it looks and feels better on a Mac.
I have created a Touch Bar storyboard and was wondering if I could add it to my app, I was thinking of something along the lines of 'If User device = Mac then load TouchBarStoryboard else don't'.
If you have any ideas on how I could implement this, please do let me know.
Below is an image of the storyboard I created for the Touch Bar.
On iOS, my GUI looks like this:
Therefore I thought the Touch Bar would offer the user an alternative to using the mouse when switching between the 5 tabs.
Many thanks for your help.
Hi, I am creating an app that recognises and extracts text from image.
The line of code request.recognitionLevel = .accurate can also take the value of request.recognitionLevel = .fast .
I would like to build a toggle which switches the value of request.recognitionLevel between fast and accurate however I am unsure on how to do this.
Any help would be greatly appreciated.
Many thanks for your time.
My code is shown below:
import SwiftUI
import UIKit
import Vision
class ViewController2: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.backgroundColor = .systemCyan // Background colour of the select photo button
button.setTitle("Select Photo", for: .normal) // Button text
button.setTitleColor(.white, for: .normal) // Button text Colour
// Rounding the edges of the 'Select Photo' button:
button.layer.cornerRadius = 25
button.layer.borderWidth = 20
button.layer.borderColor = UIColor.systemCyan.cgColor
// Rounding the edges of the 'Share' button:
shareButton.layer.cornerRadius = 25
shareButton.layer.borderWidth = 10
shareButton.layer.borderColor = UIColor.systemCyan.cgColor
stopAnimating() // Activity indicator disappears
}
// Defining the activity indicators show and spin
private func startAnimating() {
self.activityIndicator.startAnimating()
}
// Defining the activity indicators stop and hide
private func stopAnimating(){
self.activityIndicator.stopAnimating()
}
@IBAction func selectPhotoButton(_ sender: Any) { // When selectPhoto button is pressed,
SelectPhotoButtonPressed() // run the function SelectPhotoButtonPressed.
}
private func SelectPhotoButtonPressed(){
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
let imageSelector = UIImagePickerController() // Apple's interface for taking pictures and loading items from camera roll
imageSelector.sourceType = .photoLibrary // Opens the device's photo library
imageSelector.delegate = self // Leaves the UIImagePickerController when a picture is selected
self.present(imageSelector, animated: true, completion: nil) // Present the imageSelector
}
}
// Text Recognition
// Create request
var request = VNRecognizeTextRequest(completionHandler: nil)
private func VisionOCR(image: UIImage?){
var textString = "" // Variable textString = string
// Create completion handler
request = VNRecognizeTextRequest(completionHandler: { (request, error)in // Locates all the text in the image.
// Results are in the request
guard let results = request.results as?[VNRecognizedTextObservation] else {fatalError("Recieved Invalid Observation")}
for visionResult in results{
guard let recognisedText = visionResult.topCandidates(1).first else{ // Text stored in chronological order.
print("No text")
continue
}
textString += "\n\(recognisedText.string)"
DispatchQueue.main.async{ // FIFO queue
self.stopAnimating() // Hide the activityIndicator
self.textView.text = textString // Assign the textView the recoginsed text
}
}
})
// Properties
request.minimumTextHeight = 0.03125 // Default mimnimum height for text to be recognised in comparison to image, (1/32).
request.recognitionLevel = .accurate // Choice between accurate and fast.
request.recognitionLanguages = ["en_UK", "en-US", "fr-FR", "it-IT", "de-DE", "es-ES", "pt-BR", "zh-Hans", "zh-Hant", "yue-Hans", "yue-Hant", "ko-KR", "ja-JP", "ru-RU", "uk-UA"] // Recognisable languages.
request.usesLanguageCorrection = true // Applies language correction.
let requests = [request]
// Request handler
DispatchQueue.global(qos: .userInitiated).async{ // FIFO queue, qos (quality of service) determines priotity for scheduling tasks
guard let img = image?.cgImage else {fatalError("Missing image to scan")} // Variable image = computer generated image
// Create request handler
let requestHandler = VNImageRequestHandler(cgImage: img, options: [:]) // Performs Vision requests
// Send request to request handler
try? requestHandler.perform(requests) // Schedules Vision requests to be performed
}
}
}
extension ViewController2: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey :Any]){
picker.dismiss(animated: true, completion: nil)
startAnimating()
self.textView.text = ""
let image = info[UIImagePickerController.InfoKey.originalImage]as?UIImage
self.imageView.image = image
VisionOCR(image: image)
}
}
public struct storyboardview2: UIViewControllerRepresentable{
public func makeUIViewController(context content: Context) -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let controller = storyboard.instantiateViewController(identifier: "selectPhoto")
return controller
}
public func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
Below is the code for a tutorial in my app. At the end of the tutorial, there is a button called 'Continue to App'. When this button is pressed, I would like to take the user to my 'storyboardview' however at the moment the button currently performs no action.
Any help would be very much welcomed.
Many thanks...
import Foundation
import SwiftUI
import UIKit
struct CameraHelp: View {
@State private var cameraIndex = 0
private let cameras: [Camera] = Camera.sampleCameras
private let dotAppearance = UIPageControl.appearance()
var body: some View {
TabView(selection: $cameraIndex) {
ForEach(cameras) { camera in
VStack {
Spacer()
CameraView(camera: camera)
Spacer()
//
HStack {
//Spacer()
if camera == cameras.last {
//Button("Continue to App", action: goToZero)
Button("Continue to App", action: GoToApp)
.buttonStyle(.bordered)
}
// else {
// Button("Next", action: incrementCamera)
// .buttonStyle(.borderedProminent)
// }
}
Spacer()
Spacer()
Spacer()
Spacer()
Spacer()
Spacer()
//Spacer()
}
.tag(camera.tag)
}
}
.animation(.easeInOut, value: cameraIndex)// 2
.indexViewStyle(.page(backgroundDisplayMode: .interactive))
.tabViewStyle(PageTabViewStyle())
.onAppear {
dotAppearance.currentPageIndicatorTintColor = .black
dotAppearance.pageIndicatorTintColor = .gray
}
}
// func incrementCamera() {
// cameraIndex += 1
// }
func GoToApp() {
//Tutorial()
var body: some View {
abc()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Tutorial()
}
}
}
// Action on 'Camera' tab:
struct abc: View {
var body: some View {
storyboardview().edgesIgnoringSafeArea(.all) // ViewController (Camera page)
}
}
The code below shows the GUI for my app, however none of the buttons on my storyboard are clickable. This code forms part of my A-level computer science project and all help will be very much welcomed.
The code for my GUI is shown below:
//
// ContentView.swift
// Custom app bar 3
//
// Created by ### on 08/09/2022.
//
import SwiftUI
import UIKit
import MapKit
struct ContentView100: View {
@State var selected = 2 // The app will open on this page.
var body: some View {
TabView(selection: $selected) {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Button(action: {}) {
//HapticsManager.shared.vibrate(for: .success)
ContentView5().edgesIgnoringSafeArea(.all) // Naviagtion Stacks (Help page)
}
.tabItem {
Image(systemName: "questionmark.circle.fill")
Text("Help")
}.tag(0) //On menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Button(action: {}) {
//HapticsManager.shared.vibrate(for: .success)
storyboardview2().edgesIgnoringSafeArea(.all) // ViewController2 (Photos page)
}
.tabItem {
Image(systemName: "photo")
Text("Photos")
}.tag(1) //On menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Button(action: {}) {
//HapticsManager.shared.vibrate(for: .success)
storyboardview().edgesIgnoringSafeArea(.all) // ViewController (Camera page)
}
.tabItem {
Image(systemName: "camera")
Text("Camera")
}.tag(2) //On menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Button(action: {}) {
// HapticsManager.shared.vibrate(for: .success)
storyboardview3().edgesIgnoringSafeArea(.all) // ViewController3 = OCR - does not belog here (History page)
}
.tabItem {
Image(systemName: "clock")
Text("History")
}.tag(3) //On menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Button(action: {}) {
// HapticsManager.shared.vibrate(for: .success)
Tutorial().edgesIgnoringSafeArea(.all) // Tutorial - does not belong here (Settings page)
}
.tabItem {
Image(systemName: "gearshape")
Text("Settings")
}.tag(4) //On menu bar
}
}
struct Company: Identifiable, Hashable {
var id = UUID()
let ticker: String
}
struct storyboardview: UIViewControllerRepresentable{
func makeUIViewController(context content: Context) -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let controller = storyboard.instantiateViewController(identifier: "takePhoto")
return controller
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
struct storyboardview2: UIViewControllerRepresentable{
func makeUIViewController(context content: Context) -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) //Working
let controller = storyboard.instantiateViewController(identifier: "selectPhoto") //Working
return controller //Working
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
}