Git Product home page Git Product logo

sample-project's Introduction

๐Ÿ‘‹ Hi there, Iโ€™m Steven

Iโ€™m an iOS Software Engineer.

๐Ÿ˜ป I love:

  • Coding
  • Designing
  • Playing Table Tennis and Guitar
  • Learning new about IT

๐Ÿ›  Tools that I use:

  • Xcode
  • SourceTree
  • Postman
  • Figma
  • Sketch
  • AdobeXD
  • Jira
  • Confluence
  • GitHub
  • Bitbucket

๐Ÿงฐ Languages and Frameworks that I work with:

  • Swift
  • Clean Swift/MVVM
  • UIKit
  • AVFoundation
  • CoreLocation
  • Alamofire/Moya
  • Realm/CoreData
  • Apple Maps/Google Maps
  • Firebase
  • Google Places
  • Facebook SDK
  • OneSignal
  • Security
  • LocalAuthentication
  • StoreKit

๐Ÿ’ป This is how I code:

Setting up App's global behavior

class ApplicationGeneralSetupManager {
    
    static var shared = ApplicationGeneralSetupManager()
    
    func performGeneralSetup(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        setupAppDependencies(launchOptions)
        performRealmSetupAndMigration()
        setupGlobalAppearance()
        performOtherConfiguration()
    }
    
    //MARK: - Dependencies setup
    
    private func setupAppDependencies(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        /// Some setup code here 
    }
    
    // MARK: - Other setup
    
    private func performOtherConfiguration() {
        /// Some setup code here 
    }
    
    // MARK: - Realm setup
    
    private func performRealmSetupAndMigration() {
        /// Some setup code here 
    }
    
    // MARK: - Global appearance setup
    
    private func setupGlobalAppearance() {
        /// Some setup code here 
    }
}

Building UI Elements

    // MARK: - Object lifecycle
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        setup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    // MARK: - View lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupProductsCollectionView()
        interactor?.prepareCollectionViewData()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        setupNotificationsButton()
    }

    // MARK: - Actions

    @IBAction func didPressNotifications(_ sender: UIBarButtonItem) {
        performSegue(withIdentifier: "NotificationsFromMenu", sender: self)
    }
    
    @objc
    private func didPullToRefresh(_ sender: Any) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
            self.interactor?.getAllProducts()
        }
    }
    
    func showPopupErrorMessage(title: String, body: String) {
        refreshControl.endRefreshing()
        showTopErrorView(title: title, message: body)
    }
    
    private func selectFirstFiltersCell() {
        let firstCellIndex = IndexPath(item: 0, section: 0)
        filtersCollectionView.selectItem(at: firstCellIndex, animated: false, scrollPosition: .centeredHorizontally)
    }
    
    // MARK: - UI Setup
    
    private func setupProductsCollectionView() {
        let columnLayout = ColumnFlowLayout(cellsPerRow: 2,
                                            minimumInterItemSpacing: 10,
                                            minimumLineSpacing: 10,
                                            sectionInset: UIEdgeInsets(top: 0, left: 12, bottom: 20, right: 12)
        )
        refreshControl.addTarget(self, action: #selector(didPullToRefresh(_:)), for: .valueChanged)
        
        productsCollectionView.alwaysBounceVertical = true
        productsCollectionView.refreshControl = refreshControl
        productsCollectionView.dataSource = self
        productsCollectionView.delegate = self
        productsCollectionView.collectionViewLayout = columnLayout
        productsCollectionView.contentInsetAdjustmentBehavior = .always
        
        productsCollectionView.register(UINib(nibName: "ProductCollectionViewCell", bundle: nil),
                                        forCellWithReuseIdentifier: "ProductCollectionViewCell")
    }
    
    private func setupNotificationsButton() {
        if GlobalData.enteredAsAGuest {
            notificationsBarButton.image = UIImage()
            return
        }
        if GlobalData.hasUnreadNotifications {
            notificationsBarButton.image = UIImage(named: "NotificationsFilledIcon")
        } else {
            notificationsBarButton.image = UIImage(named: "NotificationsIcon")
        }
    }
    
    // MARK: - Displaying Data
    
    func displayProducts(_ data: [ProductModel]) {
        refreshControl.endRefreshing()
        
        products = data
        
        productsCollectionView.reloadData()
    }
    
    func updateProducts() {
        interactor?.updateProductList()
    }
    
    // MARK: - Routing
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let scene = segue.identifier {
            let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
            if let router = router, router.responds(to: selector) {
                router.perform(selector, with: segue)
            }
        }
    }

Working with API's

    func performSignUpRequest(with data: SignUp.RequestModel) {
        print("Sign up request, \nPOST - \(RequestLinks.signUp)")
        
        AF.request(RequestLinks.signUp, method: .post, parameters: data, encoder: JSONParameterEncoder.default, headers: nil)
            .validate()
            .responseDecodable(of: SignUp.RegistrationResponse.self) { response in
                
                switch response.result {
                case .success(let responseData):
                    self.presenter?.openPhoneVerificationScene()
                case .failure(let error):
                    let errorMessage = APIErrorsHandler.handleErrorResponse(response: response.response,
                                                                            responseData: response.data,
                                                                            error: error)
                    
                    self.presenter?.showPopupErrorMessage(title: "Error",
                                                          body: errorMessage)
                }
            }
    }

    func getUserData(completion: @escaping (Result<UserModel, APIErrors>) -> Void) {
        let headers = APIManagerSetup.defaultHeader
        var requestLink = RequestLinks.userData
        
        if TokenManager.getUserId().isEmpty {
            completion(.error(.invalidUserId))
            return
        }
        
        requestLink = requestLink + "?userId=\(TokenManager.getUserId())"
        
        print("Get user data request, \nGET - ", requestLink)
        
        AF.request(requestLink, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers)
            .validate()
            .responseDecodable(of: UserModel.self) { response in
                
                switch response.result {
                case .success(let responseData):
                    TokenManager.save(token: responseData.accessToken, userId: responseData.userId)
                    completion(.success(responseData))
                case .failure(let error):
                    print("Alamofire error - ", error)
                    completion(.error(.unableToComplete))
                }
            }
    }

    func upload(photos: [UIImage], recognizedImageIds: [String], objectId: Int, objectType: Int, operationType: ItemDetails.ItemLibraryActions) {
        let endUrl = RequestLinks.uploadPhoto + "/\(objectType)/\(objectId)"
        let headers = APIManagerSetup.defaultHeader
        
        AF.upload(multipartFormData: { multipartFormData in
            
            for (index, photo) in photos.enumerated() {
                let imageData = photo.jpegData(compressionQuality: 0.25)
                
                for id in recognizedImageIds {
                    if let idData = id.data(using: .utf8) {
                        multipartFormData.append(idData, withName: "recognized_image_ids[]")
                    }
                }
                multipartFormData.append(imageData!, withName: "photos[\(index)]", fileName: "Image-\(index).png", mimeType: "image/png")
            }
        },
                  to: endUrl, method: .post , headers: headers)
            .uploadProgress(queue: .main, closure: { progress in
                print("Upload Progress: \(progress.fractionCompleted)")
            })
            .response { response in
                
                switch response.result {
                case .success(_):
                    print("Uploaded photo successfully.")
                    self.showPopupMessageBasedOn(operationType: operationType,
                                                 errorsWithPhotos: false)
                case .failure(let error):
                    print("Got error when uploading image.", error.localizedDescription)
                    self.showPopupMessageBasedOn(operationType: operationType,
                                                 errorsWithPhotos: true)
                }
            }
    }

Processing and storing data

    func updateOrderFromOrderDetails() {
        guard let selectedOrder = selectedOrder else { return }
        guard let currentDisplayingType = currentDisplayingType else { return }
        
        if let orderToModify = allOrders.enumerated().first(where: {$0.element.id == selectedOrder.id}) {
            allOrders[orderToModify.offset] = selectedOrder
        }
        
        self.currentOrders = allOrders.filter { $0.status != .cancelled && $0.status != .completed }
        self.pastOrders = allOrders.filter { $0.status != .preparing && $0.status != .ready }
        
        prepareAndDisplayOrders(of: currentDisplayingType)
    }
    
    func loadImageFromDocumentsDirectory(fileName: String) -> UIImage {
        let placeHolderImage = UIImage(named: "PlacesPlaceholder")!
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let filePath = documentsURL.appendingPathComponent(fileName)
        
        let image = UIImage(contentsOfFile: filePath.path)
        if let savedImage = image {
            return savedImage
        } else {
            return placeHolderImage
        }
    }
    
    private func removeSavedFile(fileName: String) {
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let filePath = documentsURL.appendingPathComponent(fileName)
        do {
            if fileName.count > 0 {
                try FileManager.default.removeItem(at: filePath)
            }
        } catch let error as NSError {
            print("Error: \(error.domain)", error)
        }
    }

๐Ÿ—‚ This is the list of my projects:

Barcode & image scanner software that helps companies to keep track of their products

Position:
  • Team Lead & Creator
Key Featues:
   - Barcode scanner;
   - Custom camera picker with image recognition;
   - Offline mode;
   - Multiple customizable roles;
   - Customizable item and list cards;
   - In-App purchases;
Tech Stack:
  - Swift
  - Clean Swift architecture
  - UIKit
  - AVFoundation
  - CoreLocation
  - Alamofire
  - Realm
  - Firebase Analytics
  - StoreKit

Travel guide app that allows users to explore different European cities

Position:
  • Team Lead & Creator
Key Featues:
   - Explore and listen to audio guides of multiple places;
   - Get dirrections to selected places;
   - Walk curated routes or build your own;
   - Download city data for offline usage;
   - Save your current accommodation in selected city;
   - In-App purchases;
Tech Stack:
  - Swift
  - Clean Swift architecture
  - UIKit
  - AVFoundation
  - CoreLocation
  - Google Maps
  - Alamofire
  - Realm
  - Firebase
  - StoreKit
  - Social Media Sign up & Log In

Daily self care habit tracker

Position:
  • Team Lead
Key Featues:
   - Habit tracker;
   - Events calendar;
   - Important people organizer;
   - Daily challenges;
   - Social media sharing;
   - Customizable weekly task schedule;
Tech Stack:
  - Swift
  - MVC architecture
  - UIKit
  - AVFoundation
  - Moya 
  - Realm
  - Google Maps
  - Keychain
  - SnapKit
  - NaturalLanguage
  - Firebase Analytics
  - Facebook Analytics
  - Social Media Sign up & Log In

Fitness tracker app where you get rewards for being active

Position:
  • Team Lead & Creator
Key Featues:
   - Track steps, floors and distance covered every day;
   - Complete everyday challenges based on your activity;
   - Receive progressive rewards;
   - Purchase discounts by rewards earned for activity;
   - Invite friends and get bonuses;
Tech Stack:
  - Swift
  - Viper architecture
  - UIKit
  - Alamofire
  - Firebase 
  - Firebase Analytics
  - Health Kit

Real Estate photograpgher & editor

Position:
  • Team Lead
Key Featues:
   - Create your properties by taking pictures of them;
   - Get access to professional photo editors;
   - Receive professionaly eddited images;
Tech Stack:
  - Swift
  - MVVM architecture
  - UIKit
  - AVFoundation
  - Moya 
  - Firebase Analytics
  - Keychain
  - Audio Toolbox

sample-project's People

Contributors

eddytalvala avatar steven90311 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.