Aqua
iOS Programming – Portfolio 2

by Peter Stingel (pesti19)
Overview
- Introduction
- Methods and Materials
- Results
- Discussion
Introduction
This is the report that describes the application Aqua. The idea idea of the app is to help easier find places like toilets or tap water. In recent years I was cycling and traveling quite a lot. Each time when I visited a new place and wanted to find toilet I knew only about one place, which is well known to everyone – it’s McDonalds. I searched through AppStore and founds only few app which might help me to find these places, but most of them had terrible design. So, I have decided to create my own App with pleasant UI and UX.
Main goal is to create an app where user will be able easily search and find places with toilets and tap water. Each place is going to be shown on the map and user will able to navigate himself to the place. User will also be able to filter these places, list the places based on the distance from his location, make list of favourite places.
Methods and Materials
Brainstorming
One friend of mine is interested to create a same app for Android . We started with writing down the basic functionality that app should have. After evaluating, whether we are able to implement them. Once we had all this written down, we started to prototype the app look.
First prototype
We created the first prototype using an Adobe application Illustrator. We prototyped Launch and Map Screen all together with the actions you can perform on certain screen.
Evaluation
We showed the first prototype to three potential users and watched them carefully how they interact with the app. After a while we asked them for feedback, what they would liked / din’t like, would like to improve or add to the application.
Second prototype
Based on the feedback we made changed to the application and created an improved version of an application.
Use-Case Diagrams
I created general user case diagram of the basic functionality that app should support.
Implementation
Tools used in the process of creation
- XCode – An Apple IDE for creating iOS, iPadOS, MacOs, WatchOS apps
- Swift – programming language that app was written in
- Frameworks
- GoogleMapsAPI – Google API that provides all the functionality related to the maps
Results
First prototype
In first prototype we created a design for whole application, based on our personal preferences and what we thought that is missing in apps that are on market now.
Evaluation
Feedback – User no.1
- try to hide filter menu – it isn’t necessary to see it all the time
- it would be good to locate place directly on map
- missing feedback form / help
Feedback – User no.2
- did you consider creating a floating menu with control functions?
- there is no option do enter additional details for toilet – price, access to disabled people
Second prototype
Second prototype considers feedback from users and is clearly improved version of the first one.
Use-Case Diagrams

Implementation
User location
//https://developers.google.com/maps/documentation/ios-sdk/current-place-tutorial extension MapVC: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let location: CLLocation = locations.last! let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: zoomLevel) if mapView.isHidden { mapView.isHidden = false mapView.camera = camera } else { mapView.animate(to: camera) //Stop updating location otherwise it will call the delegate again and again self.locationManager.stopUpdatingLocation() } } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { switch status { case .restricted: print("Location access was restricted.") case .denied: let alert = UIAlertController(title: "Location disabled", message: "In order to show current location, you need to allow localization in settings", preferredStyle: UIAlertController.Style.alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) self.present(alert, animated: true, completion: nil) mapView.isHidden = false case .notDetermined: print("Location status not determined.") case .authorizedAlways: fallthrough case .authorizedWhenInUse: print("Location status is OK.") @unknown default: fatalError() } } }
Filtering places
class Parsers { static func localCountries() -> [String] { if let path = Bundle.main.path(forResource: "countries", ofType: "json") { do { let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: .dataReadingMapped) let jsonResult = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as! [String:[String]] var cityNames = [String]() for country in jsonResult { for city in country.value { let city = "\(city), \(country.key)" cityNames.append(city) } } return cityNames } catch { print("Error parsing jSON: \(error)") return [] } } return [] } static func getSortedCities() -> Dictionary<Character, [String]> { let cities = localCountries() var sortedCities: Dictionary<Character, [String]> = Dictionary<Character, [String]>() if !cities.isEmpty { for city in cities { let cityLowerCase = city.lowercased() let firstChar = cityLowerCase.first! if firstChar.isLetter { var unsortedCites = sortedCities[firstChar] if (unsortedCites != nil) { unsortedCites!.append(city) sortedCities.updateValue(unsortedCites!, forKey: firstChar) } else { sortedCities[firstChar] = [city] } } } } return sortedCities } }
Adding autocomplete
Setting up autocomplete to search only when at least 3 characters were entered.
func initSearchField() { tfSearch.delegate = self tfSearch.minCharactersNumberToStartFiltering = 3 tfSearch.startVisibleWithoutInteraction = false tfSearch.theme.font = UIFont.systemFont(ofSize: 17) tfSearch.theme.bgColor = UIColor.white tfSearch.theme.borderColor = UIColor.lightGray.withAlphaComponent(0.5) tfSearch.theme.separatorColor = UIColor.lightGray.withAlphaComponent(0.5) tfSearch.theme.cellHeight = 50 tfSearch.theme.placeholderColor = UIColor.lightGray tfSearch.tableCornerRadius = 18.0 tfSearch.tableXOffset = -12.0 tfSearch.tableYOffset = 8.0 tfSearch.maxNumberOfResults = 3 tfSearch.itemSelectionHandler = { filteredResults, itemPosition in let item = filteredResults[itemPosition] self.tfSearch.text = item.title self.tfSearch.resignFirstResponder() } }
Link to BitBucket
Video
Discussion
At the beginning of the course I set the goal to create an app which will help users to easier find places with toilets or tap water. This goal was accomplished partially.
In conclusion I have spent more time on graphical part of the app than I expected that I will. However many graphics changes helped the app to look more fresh and modern. For now approximately half of the functionality is working. User can find the places on the map, get their info, list the places from the map in the table view, add new place.
Parts which still need some improvement are sending places to the web server, filtering places, showing favourite places and showing the place based on the search.
Requirements of the course:
- Multiple Screens / Views [MUST] – ✅
- A Table View or other structural view [MUST] ✅
- Buttons, Labels [MUST] ✅
- Data storage using Core Data [MUST] ✅