diff --git a/Assignment.xcodeproj/project.xcworkspace/xcuserdata/abhinavkumar.xcuserdatad/UserInterfaceState.xcuserstate b/Assignment.xcodeproj/project.xcworkspace/xcuserdata/abhinavkumar.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..73ff627
Binary files /dev/null and b/Assignment.xcodeproj/project.xcworkspace/xcuserdata/abhinavkumar.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
new file mode 100644
index 0000000..b0c2178
--- /dev/null
+++ b/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,6 @@
+
+
+
diff --git a/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcschemes/xcschememanagement.plist b/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..ec91b33
--- /dev/null
+++ b/Assignment.xcodeproj/xcuserdata/abhinavkumar.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+
+
+
+
+ SchemeUserState
+
+ Assignment.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+
+
diff --git a/Assignment/api/ApiService.swift b/Assignment/api/ApiService.swift
index 46662a1..95acd44 100644
--- a/Assignment/api/ApiService.swift
+++ b/Assignment/api/ApiService.swift
@@ -7,27 +7,48 @@
import Foundation
-class ApiService : NSObject {
+class ApiService {
private let baseUrl = ""
private let sourcesURL = URL(string: "https://api.restful-api.dev/objects")!
- func fetchDeviceDetails(completion : @escaping ([DeviceData]) -> ()){
- URLSession.shared.dataTask(with: sourcesURL) { (data, urlResponse, error) in
+ func fetchDeviceDetails(completion : @escaping (Result<[DeviceData], Error>) -> Void) {
+ URLSession.shared.dataTask(with: sourcesURL) { data, response, error in
if let error = error {
print("Network error: \(error.localizedDescription)")
- completion([]) // Return an empty array on network failure
+ DispatchQueue.main.async{
+ completion(.failure(error))
+ }
+ // Return an empty array on network failure
return
}
- if let data = data {
- let jsonDecoder = JSONDecoder()
- let empData = try! jsonDecoder.decode([DeviceData].self, from: data)
- if (empData.isEmpty) {
- completion([])
- // Error
+
+ guard let data = data else {
+ DispatchQueue.main.async{
+ completion(.success([]))
+
+ }
+ return
+ }
+ do {
+ let devices = try JSONDecoder().decode([DeviceData].self, from: data)
+ DispatchQueue.main.async{
+ completion(.success(devices))
+ }
+ } catch{
+ print("decode error")
+ DispatchQueue.main.async{
+ completion(.failure(error))
+ // let jsonDecoder = JSONDecoder()
+ // let empData = try! jsonDecoder.decode([DeviceData].self, from: data)
+ // if (empData.isEmpty) {
+ // completion([])
+ // // Error
+ // }}
}
}
- }.resume()
+ } .resume()
+
}
}
diff --git a/Assignment/ui/ContentView.swift b/Assignment/ui/ContentView.swift
index 253924a..bab4840 100644
--- a/Assignment/ui/ContentView.swift
+++ b/Assignment/ui/ContentView.swift
@@ -8,11 +8,15 @@
import UIKit
-class ContentViewController: UIViewController {
+class ContentViewController: UIViewController{
+
+
private let viewModel = ContentViewModel()
private var devices: [DeviceData] = []
+ private var filteredDevices: [DeviceData] = []
private var tableView: UITableView!
+ private let searchController = UISearchController(searchResultsController: nil)
private var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
@@ -38,46 +42,79 @@ class ContentViewController: UIViewController {
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
view.addSubview(activityIndicator)
-
+ //api data fetch
+ setupSearchBar()
fetchData()
navigationItem.title = "Computers"
view.backgroundColor = .white
+
}
func fetchData() {
activityIndicator.startAnimating()
-
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- if let data = self.viewModel.data {
- self.devices = data
- self.tableView.reloadData()
- }
- self.activityIndicator.stopAnimating()
+//
+// DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+// if let data = self.viewModel.data {
+// self.devices = data
+// print(data)
+//
+// self.tableView.reloadData()
+// }
+ viewModel.fetchDevices{ [weak self] devices in
+ guard let self = self else { return}
+ self.devices = devices
+ self.tableView.reloadData()
+ self.activityIndicator.stopAnimating()
self.tableView.isHidden = false
}
}
+ private var isFiltering:Bool{
+ searchController.isActive &&
+ !(searchController.searchBar.text?.isEmpty ?? true)
+ }
+ private func setupSearchBar(){
+ searchController.searchResultsUpdater = self
+ searchController.obscuresBackgroundDuringPresentation = false
+ searchController.searchBar.placeholder = "Search Devices"
+ navigationItem.searchController = searchController
+ navigationItem.hidesSearchBarWhenScrolling = false
+ definesPresentationContext = true
+ }
}
extension ContentViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return devices.count
+ return isFiltering ? filteredDevices.count: devices.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DeviceCell", for: indexPath)
- let device = devices[indexPath.row]
+ let device = isFiltering ? filteredDevices[indexPath.row]
+ :devices[indexPath.row]
cell.textLabel?.text = device.name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- let selectedDevice = devices[indexPath.row]
- _ = DetailViewController(device: selectedDevice)
+ let device = isFiltering ? filteredDevices[indexPath.row]
+ :devices[indexPath.row]
+ let detailVC = DetailViewController(device: device)
+ navigationController?.pushViewController(detailVC, animated: true)
+
}
}
-
+extension ContentViewController: UISearchResultsUpdating{
+func updateSearchResults(for searchController: UISearchController) {
+ let searchText = searchController.searchBar.text ?? ""
+ filteredDevices = devices.filter{
+ $0.name.lowercased().contains(searchText.lowercased())
+ }
+ tableView.reloadData()
+
+ }
+}
diff --git a/Assignment/vm/ContentViewModel.swift b/Assignment/vm/ContentViewModel.swift
index b4d8326..7f3d562 100644
--- a/Assignment/vm/ContentViewModel.swift
+++ b/Assignment/vm/ContentViewModel.swift
@@ -8,19 +8,28 @@
import Foundation
-class ContentViewModel : ObservableObject {
+class ContentViewModel {
private let apiService = ApiService()
- @Published var navigateDetail: DeviceData? = nil
- var data: [DeviceData]? = []
+// @Published var navigateDetail: DeviceData? = nil
+// var data: [DeviceData]? = []
+ private var devices: [DeviceData] = []
- func fetchAPI() {
- apiService.fetchDeviceDetails(completion: { item in
- self.data = item
- })
- }
- func navigateToDetail(navigateDetail: DeviceData) {
- self.navigateDetail = navigateDetail
+ func fetchDevices(completion:@escaping ([DeviceData]) -> Void){
+ apiService.fetchDeviceDetails{ result in
+ switch result {
+ case.success(let devices):
+ completion(devices)
+ case .failure(let error):
+ print("error",error.localizedDescription)
+ completion([])
+ }
+ }
+ }
}
-}
+
+// func navigateToDetail(navigateDetail: DeviceData) {
+// self.navigateDetail = navigateDetail
+// }
+