Monday, March 11, 2019

Create BKS using portecle

download certificate from windows google chrome with cer extention
        open portcle
            create new bks file
            open downloaded certificate
            save with entering pwds

        use saved bks file in android app with the given passwords
Swift - AppToApp communication 

https://developer.apple.com/documentation/uikit/core_app/communicating_with_other_apps_using_custom_urls

communicate with using URL
---------
create url schemes
    go to prokject-> info -> urlTypes
        fill identifier - Actually there is no usage at all. you can use anything. only the sceme and role considered.
        URL schemes - unique app scheme which other apps use to open the app, cannot use existing ios system schemes in here (https://developer.apple.com/library/content/featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007899)
        Role -
            Editor - schemes if we are defines
            Viewer - existing schemes in iOS system (like photo viewer, email , sms apps)

    how it works
        if we want to open app2 from app1
            in app2
                identifier - dont know the correct usage. in apple Doc also not gives a full Description
                schecme - used iPay
                role - Editor (this is our own define scheme. so need to use as Editor. if systemdefine scheme should as view)

            in App1
                app1 we should also have to define url scheme for matching for appys2. scheme should be same and role should None.
                    identifier - can use anything
                    schecme - used iPay
                    role - None

                let kCustomURLScheme = "ipay://" // only the sceme used. not identifier
                let customURL = URL(string: customURLScheme)!
                if UIApplication.shared.canOpenURL(customURL) {
                    if #available(iOS 10.0, *) {
                        UIApplication.shared.open(customURL, completionHandler: { (success) in
                            print("Open url : \(success)")
                        })
                    } else {
                        UIApplication.shared.openURL(customURL)
                    }
                    return true
                }
    ** if we use same scheme for two application

        system starts first installed application. if we uninstall first app then it will open second app.


Swift push notification

https://firebase.google.com/docs/cloud-messaging/ios/client
    create project
    add required POD
    create apns key in apple developer portal
    upload that token in to firebase project
------------
push notfication in appDelegate method execution steps

didFinishLaunchingWithOptions
didReceiveRegistrationToken  -- this return the push token

        didRegisterForRemoteNotificationsWithDeviceToken  --  this will run when app kill and run again

send notification from firebase
app is in foreground - userNotificationCenter - willPresent
app in bg -
    notification shows in notification bar
    click on notification' - userNotificationCenter - didReceive

app kill and send notification  (same as above)
     notification shows in notification bar
    click on notification' - userNotificationCenter - didReceive

-------------
{
    "to": "PUSH_TOKEN_HERE",
    "notification": {
        "body": "You have authorized LKR 20.00 to test from your A/C *******0269 on 23-04-2018 at 11:10. TXN ID : 20857",
        "title": "Payment Successful !!",
        "icon": ""
    },
    "data": {
        "notificationType": "WEB_PAYMENT",
        "data": {
            "instrumentReference": "W000000000000631"
        }
    }
}

notification  - this part automatically handled by app when only app in background (both android and ios). it shows notification. we need to pass body and title

data - this part only trigger when app is in forground (in both ios & android). we can catch these values inside data object.

CocoaPods

What is CocoaPods
    CocoaPods manages library dependencies for your Xcode projects.

    The dependencies for your projects are specified in a single text file called a Podfile. CocoaPods will resolve dependencies between libraries, fetch the resulting source code, then link it together in an Xcode workspace to build your project.

POD
    command line tool to work with pod files

Installation
    sudo gem install cocoapods

    pod required ruby installation. checko ruby version
        ruby -v

    to maintain pod local repository use
        pod setup
            this will create master repo in user-> name-> .cocoapods -> repos...
            i think this is lile maven repo. we can maintain repo from local rather than downloading same repo.
            this is the main repo path
                https://github.com/CocoaPods/CocoaPods

add pod in to project
    pod init
        to init pod it needs a xcode project. without project no pod init ;)
        this will create a pod file.

open pod file using text editor
    use xcode interminal use this command
        open -a Xcode Podfile

adding required library projects as this
    pod 'JLocationKit', '~> 1.0.3'

downloading lib projects
    pod install

update missing pods
    pod install --repo-update

to run pod project open xcode using App.xcworkspace
    do not open using project file

remove pod from a project
    $ sudo gem install cocoapods-deintegrate cocoapods-clean
    $ pod deintegrate
    $ pod clean

    $ rm Podfile
uiviewcontroller life cycle

application  - AppDelegate
viewDidLoad
viewWillAppear
viewDidAppear
applicationDidBecomeActive  - AppDelegate
applicationWillResignActive - AppDelegate

home click
----------
applicationDidEnterBackground - AppDelegate
applicationWillEnterForeground - AppDelegate

again open app from icon click
--------------
applicationDidBecomeActive - AppDelegate
applicationWillResignActive - AppDelegate

app killed by using running apps
---------------
applicationWillTerminate - AppDelegate


viewDidLoad  -  oncreate
viewWillAppear  - onresume
viewDidAppear  - onresume
viewWillDisappear - onpause ( these will called when open another controller, not at home click )

viewDidDisappear - ondestroy ( these will called when open another controller , not at home click)

Swift localization

first need to setting project localization
    select project-> info -> localization
        click + sign and select required languages

in ios string files can add in two places
    for storyboard wise localization
        these strings cannot apply programatically
        in inspector tab select required locations
            this will create new string files in project->project name folder->  lancode.IProj folder -> Main.String
                if launcher storyboard localization added it will create LaunchScreen.strings file in same folder

        *** These language applied when user changed the device language in setting.
        when app specific language change can do by changing the budle as below. but user needs to restart the app to use these strings.

    programatically access strings
        select project-> new file -> String -> name as Localizable.strings (name should be this)
            this will create a file in  project-> Localizable.strings file
        select that file and click localize button in inspector tab
            select required languages
            add strings in this format
                "key" = "value";

        these string files access in program by attach bundle path to these files. to change path
            let path: String? = Bundle.main.path(forResource: lang, ofType: "lproj")
            if path == nil {
                bundle = Bundle.main
            }
            else {
                bundle = Bundle(path: path!)

            }
Swift- Working with rest service

parts of a web request
    protocol    - rules
    subdomain   - point a more specifc server or etc
    domain      - unique reference to specific site
    port        -
    path        - refer specifi sub directory or file
    query param - more detail of request

    request type - GET, POST etc
    headers - key value pair which tells server how to handle the request
            response also has header which describe how the client use the information
    body    - data send or received

playgroud setup for network request
    playground default support for synchronous request. means lines runs top to bottom. so to call network requet has some changes in playground. add these lines in top
        import PlaygroundSupport

        PlaygroundPage.current.needsIndefiniteExecution = true

///////////////////////
 like in java we can seperately invoke service call and get the response as callback function. everything step by step in here. last class is using all concepts

        import Foundation
        import PlaygroundSupport


        PlaygroundPage.current.needsIndefiniteExecution = true  // make playgroud to run asnchronous request

        //let url = URL(string: "https://api.nasa.gov/planetary/apod?api_key=NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo")!
        //let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        ////    if let data = data {
        ////        print(data) // print as bytes
        ////        print(data as? NSData)// print as object
        ////    }
        //   
        //    //get as json object
        //    if let data = data,
        //        let string = String(data: data, encoding: .utf8) {
        //        print(string)
        //    }
        //    // end of return json object
        //}
        //
        //task.resume()
        ///////////////////////////////////////////////////////////

        // add query parameters seperately

        //extension URL {
        //    func withQueries(_ queries: [String: String]) -> URL? {
        //        var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
        //        components?.queryItems = queries.flatMap
        //            { URLQueryItem(name: $0.0, value: $0.1) }
        //        return components?.url
        //    }
        //}
        //
        //let baseURL = URL(string: "https://api.nasa.gov/planetary/apod")!
        //let query: [String: String] = [
        //    "api_key": "NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo",
        //    "date": "2011-07-13"
        //]
        //
        //let url = baseURL.withQueries(query)!
        //let task = URLSession.shared.dataTask(with: url) { (data,
        //    response, error) in
        //    if let data = data,
        //      let string = String(data: data, encoding: .utf8) {
        //        print(string)
        //    }
        //}
        //
        //task.resume()

        ///////////////////////////////////////////////////////////
        /*josn serilization

        struct PropertyKey {
            static let title = "title"
            static let description = "explanation"
            static let url = "url"
            static let copyright = "copyright"
        }

        class PhotoInfo{
            var url : URL
            var description : String
            var title : String
            var copyright : String?
           
            init?(json: [String: Any]) {
               
                guard let title = json[PropertyKey.title] as? String,
                    let description = json[PropertyKey.description] as? String,
                    let urlString = json[PropertyKey.url] as? String,
                    let url = URL(string: urlString) else { return nil }
           
                self.url = url
                self.description = description
                self.title = title
                self.copyright = json[PropertyKey.copyright] as? String
               
            }
        }

        extension URL {
            func withQueries(_ queries: [String: String]) -> URL? {
                var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
                components?.queryItems = queries.flatMap
                    { URLQueryItem(name: $0.0, value: $0.1) }
                return components?.url
            }
        }

        let baseURL = URL(string: "https://api.nasa.gov/planetary/apod")!
        let query: [String: String] = [
            "api_key": "NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo",
            "date": "2011-07-13"
        ]

        let url = baseURL.withQueries(query)!
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let data = data,
                let rawJSON = try? JSONSerialization.jsonObject(with:data),
                let json = rawJSON as? [String: String],
                let photoInfo = PhotoInfo(json:json) {
                    print(photoInfo)
               
            }
           
        //  to get normal json object use this way
        //    if let data = data,
        //        let rawJSON = try? JSONSerialization.jsonObject(with:
        //            data),
        //        let json = rawJSON as? [String: String] {
        //            print(json)
        //        }
        }

        task.resume()
         **/

        //////////////////////////
        //getting a callback with params
         /* func performLongRunningOperation(callbackFuncName: @escaping (retunFunctionParam1,retunFunctionParam2) ->
            Void) {
            // Code that performs a long running operation
            successFunc(returnParam1Value,returnParam2Value)
        }
        //example
        func callService (callbackFunc : @escaping (String, Int) -> Void) {
            callbackFunc("hi", 10)
        }
       
         // pass callback function as parameter and other parameters also
       
         func callService (urlStr : String, callbackFunc : @escaping (String, Int) -> Void) {
            callbackFunc("hi", 10)
         }
       
       
         callService (urlStr: "sss",callbackFunc : { (strVal,intVal) in
            print(strVal)
         })
       
         */

        ///////////////////////////// network request with callback
        struct PropertyKey {
            static let title = "title"
            static let description = "explanation"
            static let url = "url"
            static let copyright = "copyright"
        }

        class PhotoInfo{
            var url : URL
            var description : String
            var title : String
            var copyright : String?
           
            init?(json: [String: Any]) {
               
                guard let title = json[PropertyKey.title] as? String,
                    let description = json[PropertyKey.description] as? String,
                    let urlString = json[PropertyKey.url] as? String,
                    let url = URL(string: urlString) else { return nil }
               
                self.url = url
                self.description = description
                self.title = title
                self.copyright = json[PropertyKey.copyright] as? String
               
            }
        }

        extension URL {
            func withQueries(_ queries: [String: String]) -> URL? {
                var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
                components?.queryItems = queries.flatMap
                    { URLQueryItem(name: $0.0, value: $0.1) }
                return components?.url
            }
        }

        //The @escaping keyword tells the compiler that the code in the closure will be executed after the function has returned, or has finished executing all the code.

        func callService(urlStr:String , funcCallback : @escaping (PhotoInfo) -> Void) {
            let baseURL = URL(string: urlStr)!
            let query: [String: String] = [
            "api_key": "NNKOjkoul8n1CH18TWA9gwngW1s1SmjESPjNoUFo",
            "date": "2011-07-13"
            ]
           
            //here multiple conditions checking using , instear && mark
            let url = baseURL.withQueries(query)!
            let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let data = data,
            let rawJSON = try? JSONSerialization.jsonObject(with:data),
            let json = rawJSON as? [String: String],
            let photoInfo = PhotoInfo(json:json) {
                funcCallback(photoInfo)
                }
            }

            //                if let data = data{
            //                    print(data)
            //                    let rawJSON = try? JSONSerialization.jsonObject(with:data)
            //                    if let jsona = rawJSON as? [String: String] {
            //                        if let photoInfoa = PhotoInfo(json:jsona){
            //                            funcCallback(photoInfoa)
            //                        }
            //                    }
            //                }
           
           
            task.resume()
        }

        var urls = "https://api.nasa.gov/planetary/apod"

        callService (urlStr: urls, funcCallback:  { (photoInfoObj ) in
            print(photoInfoObj.title)
        } )

        //we can call this way also.
        callService (urlStr: urls) { (photoInfoObj ) in
            print(photoInfoObj.title)
        }