Skip to content

onurduyar/DeezerApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Logo

Deezer App

The application has been developed using the MVVM architectural pattern, aiming to offer users the capability to explore music genres and artists, as well as access comprehensive details about them. Employing a RESTful API, the app retrieves data regarding categories, artists, and albums. This app enables users to explore a vast music collection, discover their preferred songs, navigate through albums and playlists, and save their favorites for future reference.

GitFlow Strategy

Features

  • Programmatic UI
  • Generic Network Layer
  • Only URLSession
  • CoreData
  • NSCache
  • NotificationCenter
  • CustomCells
  • Custom Hex. UIColor
  • Generic BaseVC and BaseViewModel

Project Development Process

During the development process of this project, Trello was used for project management and git version control system was used for code base management. During the project development process, I determined and assigned tasks as if I was working in a team.

Screenshots

Category ArtistList Artist
Tracks Favorites
-

Gantt Schema

Requirements

Project Architecture - MVVM

Code Samples

UIImage+Extension -- NSCache

let cache = NSCache<AnyObject, AnyObject>()

extension UIImageView {
    func downloadImage(from url: URL?){
        guard let url else {
            return
        }
        if let image = cache.object(forKey: url.absoluteString as NSString) as? UIImage{
            self.image = image
            return
        }
        
        let session = URLSession(configuration: .default)
        let urlRequest = URLRequest(url: url)
        let task = session.dataTask(with: urlRequest) { data, response, error in
            if let error {
                fatalError(error.localizedDescription)
            }
            guard let data,let image = UIImage(data: data) else {
                return
            }
            
            DispatchQueue.main.async {
                self.image = image
            }
            cache.setObject(image, forKey: url.absoluteString as NSString)
        }
        task.resume()
    }
}

BaseViewModel

protocol BaseViewModel {
    associatedtype Model
    var data: Model? { get set }
    func fetchData(by id: Int?,completion: @escaping ((Result<Model?, Error>) -> Void ))
}

extension BaseViewModel {
    func fetchData(by id: Int?,completion: @escaping ((Result<Model?, Error>) -> Void )) {}
}

Generic BaseVC

class BaseViewController<T: UIView>: UIViewController {
    // Properties
    let baseViewModel: any BaseViewModel
    
    var contentView: T {
        return view as! T
    }
    
    // Init
    init(viewModel: any BaseViewModel) {
        self.baseViewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // LifeCycle
    override func loadView() {
        view = T()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //baseViewModel.delegate = self
    }
    
    // Methods
    func fetchData(id :Int? = nil) {
        fatalError("fetchData must be overridden")
    }
}

// MARK: - BaseViewModelDelegate
extension BaseViewController: BaseViewModelDelegate {
    func onDataUpdated() {
        fatalError("onDataUpdated must be overridden")
    }
}
protocol BaseViewModelDelegate: AnyObject {
    func onDataUpdated()
}

protocol CollectionViewDelegate: AnyObject,UICollectionViewDelegate,UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
}
protocol TableViewDelegate: AnyObject,UITableViewDelegate,UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
}

UIColor+Extension -- HexColor

extension UIColor {
    convenience init(hex: String) {
        var cString: String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
        
        if cString.hasPrefix("#") {
            cString.remove(at: cString.startIndex)
        }
        
        if (cString.count) != 6 {
            self.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)
            return
        }
        
        var rgbValue: UInt64 = 0
        Scanner(string: cString).scanHexInt64(&rgbValue)
        
        self.init(red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
                  green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
                  blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
                  alpha: CGFloat(1.0))
    }
}
video.mp4

About

Simple music app using deezer api.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages