Development record of developer who study hard everyday.

,

How to solve error: constant expression required

 How to solve error: constant expression required


After I upgrade Gradle version upto 8.0, I encounter "constant expression required" error.

This is because AGP 8.0 doesn't allow reference to resourceID.

In my case, I use below code:

switch(view.id) {

    case sample1: 

    case sample2:

    ......

}


Solution1:

Change switch statement to if-else statement


Solution2:

Add below properties to gradle.properties file

android.nonFinalResIds = false






















Share:
Read More
,

How to solve "Can not find symbol BuildConfig" errorr

 How to solve "Can not find symbol BuildConfig" errorr



android {
    buildFeatures {
        buildConfig = true
    }
}

Put on above code into build.gradle file (app level).

This is because AGP 8.0 sets the default value of android.defaults.buildfeatures.buildconfig to false.












Share:
Read More
,

AndroidStudio "Loading Devices.." error

 How to solve "Loading Devices.." error on Android Studio


When I am developing android app using Android Studio, Android Studio can not detect connected devices like below capture.



After several trials, I found the solution.

Just reboot your mac........

Share:
Read More
, ,

iOS Router pattern example

 iOS Router pattern example


1. Why do we need Router pattern?

If we use Router pattern, we can make network layer abstract.

So, We can avoid boilerplater code to make network request.


2. Example code

1)Http Router

protocol HttpRouter: URLRequestConvertible {

    var baseUrlString: String { get }

    var path: String { get }

    var method: HTTPMethod { get }

    var headers: HTTPHeaders? { get }

    var parameters: Parameters? { get }

    func body() throws -> Data?

    

    func request(usingHttpService service: HttpService) throws -> DataRequest

}


extension HttpRouter {

    var parameter: Parameters? { return nil }

    

    func body() throws -> Data? { return nil }

    

    func asURLRequest() throws -> URLRequest {

        var url = try baseUrlString.asURL()

        url.appendPathComponent(path)

        

        var request = try URLRequest(url: url, method: method, headers: headers)

        request.httpBody = try body()

        return request

    }

    

    func request(usingHttpService service: HttpService) throws -> DataRequest {

        return try service.request(asURLRequest())

    }

}


2) AuthHttpRouter

import Foundation

import Alamofire


enum AuthHttpRouter {

    case login(AuthModel)

    case signUp(AuthModel)

    case validate(token: String)

    case refreshToken(token: String)

    case logout(token: String)

    case validateEmail(email: String)

}


extension AuthHttpRouter: HttpRouter {

    

    

    var baseUrlString: String {

        return "https://letscodeeasy.com/groceryapi/public/api"

    }

    

    var path: String {

        switch(self) {

        case .login:

            return "login"

        case .signUp:

            return "register"

        case .validate:

            return "user"

        case .refreshToken:

            return "token/refresh"

        case .logout:

            return "logout"

        case .validateEmail:

            return "validate/email"

        }

    }

    

    var method: HTTPMethod {

        switch (self) {

        case .login, .signUp, .refreshToken, .logout, .validateEmail:

            return .post

        case .validate:

            return .get

        }

    }

    

    var headers: HTTPHeaders? {

        switch(self) {

        case .login, .signUp, .validateEmail:

            return ["Content-Type": "application/json; charset=UTF-8"]

        case .validate(let token), .refreshToken(let token), .logout(let token):

            return [

                "Authorization" : "Bearer \(token)",

                "Content-Type" : "application/json; charset=UTF-8"

            ]

        }

    }

    

    var parameters: Parameters? {

        return nil

    }


    func body() throws -> Data? {

        switch self {

        case .signUp(let user):

            return try JSONEncoder().encode(user)

        case .validateEmail(let email):

            return try JSONEncoder().encode(["email" : email])

        default:

            return nil

        }

    }

}

AuthHttpRouter class implement HttpRouter protocol.

So, We can pick up the path, method, body parameter when we make a network request.


3) HttpService

protocol HttpService {

    var sessionManager: Session { get set }

    func request(_ urlRequest: URLRequestConvertible) -> DataRequest

}


4) AuthHttpService

import Alamofire


final class AuthHttpService : HttpService {

    var sessionManager: Session = Session.default

    

    func request(_ urlRequest: URLRequestConvertible) -> DataRequest {

        return sessionManager.request(urlRequest).validate(statusCode: 200..<400)

    }

}

AuthHttpService implements HttpService protocol.

We make a network request using AuthHttpService class.

The detailed request content is exposed on lower level of network layer, AuthAPI. 


5) AuthAPI

import Foundation

import Combine


protocol AuthAPI {

    func checkEmail(email: String) -> Future<Bool, Never>

    func signUp(username: String, email: String, password: String) -> Future<(statusCode: Int, data: Data), Error>

}


6)AuthService

import Foundation

import Combine


enum SignUpError : Error {

    case emailExists

    case invalidData

    case invalidJSON

    case error(error: String)

}


enum AuthResult<T> {

    case success(value: T)

    case failure(message: String)

}


class AuthService {

    lazy var httpService = AuthHttpService()

    static let shared: AuthService = AuthService()

    private init() {}

}


extension AuthService: AuthAPI {

    func signUp(username: String, email: String, password: String) -> Future<(statusCode: Int, data: Data), Error> {

        return Future<(statusCode: Int, data: Data), Error> { [httpService] promise in

            do {

                try AuthHttpRouter

                    .signUp(AuthModel(name: username, email: email, password: password))

                    .request(usingHttpService: httpService)

                    .responseJSON { response in

                        guard

                            let statusCode = response.response?.statusCode,

                            let data = response.data,

                            statusCode == 200 else {

                            promise(.failure(SignUpError.invalidData))

                            return

                        }

                        promise(.success((statusCode: statusCode, data: data)))

                    }

            } catch {

                print("Something went wrong : \(error)")

                promise(.failure(SignUpError.invalidData))

            }

        }

        

    }

    

    func checkEmail(email: String) -> Future<Bool, Never> {

        return Future<Bool, Never> { [httpService] promise in

            do {

                try AuthHttpRouter

                    .validateEmail(email: email)

                    .request(usingHttpService: httpService)

                    .responseJSON { response in

                        guard response.response?.statusCode == 200 else {

                            print("checkEmail fail")

                            promise(.success(false))

                            return

                        }

                        promise(.success(true))

                        print("checkEmail success")

                    }

            } catch {

                promise(.success(false))

                print("checkEmail error")

            }

            

        }

    }

}

AuthService class implement AuthAPI protocol.

We start to make a network request on this layer.

If you use MVVM pattern, you make a network request using AuthService on ViewModel.



















Share:
Read More