Building an iOS App with Spring Boot for CRUD Operations

Creating an iOS application that interacts with a Spring Boot backend for CRUD operations involves several steps. Below is a high-level outline of the process, including sample implementations:


Backend: Spring Boot

  1. Set Up the Spring Boot Project

    • Use Spring Initializr to generate a Spring Boot project with dependencies like:
      • Spring Web
      • Spring Data JPA
      • H2 Database (or any other DB like MySQL/PostgreSQL)
      • Spring Boot DevTools
  2. Define the Entity Class

    @Entity
    public class Item {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private String name;
        private String description;
    
        // Getters and setters
    }
  3. Create the Repository

    public interface ItemRepository extends JpaRepository<Item, Long> {}
  4. Build the Controller

    @RestController
    @RequestMapping("/api/items")
    public class ItemController {
        @Autowired
        private ItemRepository repository;
    
        @GetMapping
        public List<Item> getAllItems() {
            return repository.findAll();
        }
    
        @GetMapping("/{id}")
        public ResponseEntity<Item> getItemById(@PathVariable Long id) {
            return repository.findById(id)
                    .map(ResponseEntity::ok)
                    .orElse(ResponseEntity.notFound().build());
        }
    
        @PostMapping
        public Item createItem(@RequestBody Item item) {
            return repository.save(item);
        }
    
        @PutMapping("/{id}")
        public ResponseEntity<Item> updateItem(@PathVariable Long id, @RequestBody Item updatedItem) {
            return repository.findById(id).map(item -> {
                item.setName(updatedItem.getName());
                item.setDescription(updatedItem.getDescription());
                return ResponseEntity.ok(repository.save(item));
            }).orElse(ResponseEntity.notFound().build());
        }
    
        @DeleteMapping("/{id}")
        public ResponseEntity<Void> deleteItem(@PathVariable Long id) {
            if (repository.existsById(id)) {
                repository.deleteById(id);
                return ResponseEntity.noContent().build();
            }
            return ResponseEntity.notFound().build();
        }
    }
    
  5. Run the Spring Boot Application

    • Run the application and ensure the endpoints are accessible via a REST client like Postman or cURL.

Frontend: iOS (Swift)

  1. Set Up the iOS Project

    • Create a new project in Xcode using the App template.
    • Choose Swift as the language and SwiftUI or UIKit for the UI.
  2. Add a Network Manager

    • Create a NetworkManager class to handle API requests:
    import Foundation
    
    struct Item: Codable, Identifiable {
        var id: Int?
        var name: String
        var description: String
    }
    
    class NetworkManager {
        static let shared = NetworkManager()
        private let baseURL = "http://localhost:8080/api/items"
    
        func fetchItems(completion: @escaping ([Item]?) -> Void) {
            guard let url = URL(string: baseURL) else { return }
            URLSession.shared.dataTask(with: url) { data, _, _ in
                if let data = data {
                    let items = try? JSONDecoder().decode([Item].self, from: data)
                    DispatchQueue.main.async {
                        completion(items)
                    }
                } else {
                    DispatchQueue.main.async {
                        completion(nil)
                    }
                }
            }.resume()
        }
    
        func createItem(_ item: Item, completion: @escaping (Item?) -> Void) {
            guard let url = URL(string: baseURL) else { return }
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            request.httpBody = try? JSONEncoder().encode(item)
    
            URLSession.shared.dataTask(with: request) { data, _, _ in
                if let data = data {
                    let newItem = try? JSONDecoder().decode(Item.self, from: data)
                    DispatchQueue.main.async {
                        completion(newItem)
                    }
                } else {
                    DispatchQueue.main.async {
                        completion(nil)
                    }
                }
            }.resume()
        }
    
        func deleteItem(id: Int, completion: @escaping (Bool) -> Void) {
            guard let url = URL(string: "\(baseURL)/\(id)") else { return }
            var request = URLRequest(url: url)
            request.httpMethod = "DELETE"
    
            URLSession.shared.dataTask(with: request) { _, response, _ in
                let success = (response as? HTTPURLResponse)?.statusCode == 204
                DispatchQueue.main.async {
                    completion(success)
                }
            }.resume()
        }
    }
  3. Build the UI

    • Using SwiftUI, you can display and manage items:
    import SwiftUI
    
    struct ContentView: View {
        @State private var items: [Item] = []
    
        var body: some View {
            NavigationView {
                List {
                    ForEach(items) { item in
                        VStack(alignment: .leading) {
                            Text(item.name).font(.headline)
                            Text(item.description).font(.subheadline)
                        }
                    }
                    .onDelete(perform: deleteItem)
                }
                .navigationTitle("Items")
                .toolbar {
                    Button(action: fetchItems) {
                        Text("Refresh")
                    }
                }
            }
            .onAppear(perform: fetchItems)
        }
    
        func fetchItems() {
            NetworkManager.shared.fetchItems { fetchedItems in
                if let fetchedItems = fetchedItems {
                    self.items = fetchedItems
                }
            }
        }
    
        func deleteItem(at offsets: IndexSet) {
            offsets.forEach { index in
                if let id = items[index].id {
                    NetworkManager.shared.deleteItem(id: id) { success in
                        if success {
                            self.items.remove(at: index)
                        }
                    }
                }
            }
        }
    }
    
  4. Test the Application

    • Run the Spring Boot backend and the iOS app.
    • Make sure the iOS app connects to the backend and performs CRUD operations.

Key Notes

  • For a real-world application, consider security (e.g., authentication and authorization) using solutions like OAuth2 or JWT.
  • Test the Spring Boot API with a REST client before integrating it with the iOS app.
  • Use tools like ngrok to expose the Spring Boot API for testing on physical devices.

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete