Develop the iOS App using the Swift - Part #2

By @steemthinkcom3/8/2018utopian-io

New Features

  • What feature(s) did you add?

On the basis of the previous version, the following features were updated: steemconnect login, comment, vote, release function

  • How did you implement it/them?

This function is updated, mainly related to two files.

STClient.swift

//
//  SteemClient.swift
//  SteemThink
//
//  Created by zhouzhiwei on 2018/2/22.
//  Copyright © 2018年 zijinph. All rights reserved.
//
import UIKit
import MBProgressHUD
let baseURL:String = "https://v2.steemconnect.com"
let appId:String = ""
//GET /get_discussions_by_trending
let discussions_by_trending = "https://api.steemjs.com/get_discussions_by_trending?"
//GET /get_discussions_by_created
let discussions_by_created = "https://api.steemjs.com/get_discussions_by_created?"
//GET /get_discussions_by_hot
let discussions_by_hot = "https://api.steemjs.com/get_discussions_by_hot?"
//GET /get_accounts
let get_accounts = "https://api.steemjs.com/get_accounts?"
let get_content_replies = "https://api.steemjs.com/get_content_replies?"
let get_login_url = "https://v2.steemconnect.com/oauth2/authorize?client_id=steemthink.com&redirect_uri=https://cnsteem.github.io/sc2-angular&scope=vote,comment"
//POST /broadcast
let post_broadcast = "https://v2.steemconnect.com/api/broadcast/"
class STClient: NSObject {    
    typealias STClientCallBack = (_ response: Any?,_ error: Error?)->()    
    //MARK: - vote
    class func vote(
                    voter:String,
                    author:String,
                    permlink:String,
                    weight:NSInteger,
                    finished:@escaping STClientCallBack){
        let param = ["voter": voter,
                     "author": author,
                     "permlink":permlink,
                     "weight":weight,
                     ] as [String : Any]
        self.broadcast(body: ["operations":[["vote",param]]],finished: finished)
    }
    //MARK: - post&comment
    class func comment(
                 parentAuthor:String,
                 parentPermlink:String,
                 author:String,
                 permlink:String,
                 body:String,
                 finished:@escaping STClientCallBack) {
        let param = ["parent_author": parentAuthor,
                     "parent_permlink": parentPermlink,
                     "author":author,
                     "permlink":permlink,
                     "title":"",
                     "body":body,
                     "json_metadata": ""]        
        self.broadcast(body: ["operations":[["comment",param]]],finished: finished)
    }    
    class func broadcast(body:Dictionary<String, Any>,
        finished:@escaping STClientCallBack) {
//        print("jsonData ==============="+"\(NSDictionary_STExtension.getJSONStringFromDictionary(dictionary: body))")
        self.post(url: post_broadcast, body: body, finished: finished)
    }    
    class func post(url:String,body:Dictionary<String, Any>,finished:@escaping STClientCallBack) -> Void {
        let client = STAFNetworkTools.sharedTools;
//        Set the requested header tag
        client.requestSerializer.setValue(UserDataManager.sharedInstance.getToken(), forHTTPHeaderField: "Authorization")
        client.request(method: .POST, urlString: url, parameters: body as AnyObject) { (response, error) in
            finished(response,error)
        }
    }    
    class func get(url:String!,parameters:AnyObject?,to:UIView?,finished:@escaping STClientCallBack){
        var hud:MBProgressHUD?
        if (to != nil){
            hud = MBProgress_STExtension.ST_ShowHUDAddedToView(view: to!, title: "", animated: true)
        }
        STAFNetworkTools.sharedTools.request(method: .GET, urlString: url, parameters: parameters) { (response: Any?,error: Error?) in
            if (hud != nil) {
                hud?.hide(animated: true)
            }
            if (error != nil) && (to != nil) {
                MBProgress_STExtension.ST_ShowHUDHidAfterSecondWithMsgType(title: (error?.localizedDescription)!, view: to!, afterSecond: 1.5, msgType: STMBProgress.Error)
            }
            finished(response,error)
        }
    }
}

STAFNetworkTools.swift

//
//  AFNetworkTools.swift
//  SteemThink
//
//  Created by zhouzhiwei on 2018/2/22.
//  Copyright © 2018 zijinph. All rights reserved.
//
import UIKit
import AFNetworking
/// Request method
/// - GET:  get
/// - POST: post
enum AFRequestMethod: String {
    case GET = "GET"
    case POST = "POST"
}
class STAFNetworkTools: AFHTTPSessionManager {
    static let sharedTools: STAFNetworkTools = {
        let instance = STAFNetworkTools()
        instance.responseSerializer.acceptableContentTypes?.insert("text/html")
        instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
        instance.requestSerializer = AFJSONRequestSerializer.init()
        instance.requestSerializer.timeoutInterval = 20.0
        return instance
    }()     
    // (response: AnyObject?, error: NSError?)->()
    typealias AFNRequestCallBack = (_ response: Any?,_ error: Error?)->()
    ///
  /// - parameter urlString: request address
     /// - parameter parameters: Request parameters
     /// - parameter finished: The callback for the success or failure of the request
    func request(method: AFRequestMethod = .GET, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack){        
        print("urlString ============  " + urlString)
        print("parameters ============  " + String(describing: parameters))        
// dataTaskWithHttp is written in the. M file
         // corresponds to Swift, is a private modification method
         // Define the closure for which the request succeeded
        let success = { (dataTask: URLSessionDataTask, responseObject: Any?) -> Void in
            print("responseObject =========" + "\(String(describing: responseObject))")
            finished(responseObject, nil)
        }
// Define the closure of the request failed
        let failure = { (dataTask: URLSessionDataTask?, error: Error) -> Void in
            print("request Error =========" + error.localizedDescription)
            finished(nil, error)
        }        
        if method == .GET {
            get(urlString,parameters:parameters,progress:nil,success:success,failure:failure)
        }else{
            post(urlString, parameters: parameters, progress: nil, success:success, failure: failure)
        }
    }    
    func requestBack(method: AFRequestMethod = .GET, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack) -> URLSessionDataTask{
        print("urlString ============  " + urlString)
        print("parameters ============  " + String(describing: parameters))
// dataTaskWithHttp is written in the. M file
         // corresponds to Swift, is a private modification method
         // Define the closure for which the request succeeded
        let success = { (dataTask: URLSessionDataTask, responseObject: Any?) -> Void in
            print("responseObject =========" + "\(String(describing: responseObject))")
            finished(responseObject, nil)
        }
// Define the closure of the request failed
        let failure = { (dataTask: URLSessionDataTask?, error: Error) -> Void in
            print("request Error =========" + error.localizedDescription)
            finished(nil, error)
        }        
        if method == .GET {
            return get(urlString,parameters:parameters,progress:nil,success:success,failure:failure)!
        }else{
            return post(urlString, parameters: parameters, progress: nil, success:success, failure: failure)!
        }
    }   
/// send request (upload file)
    func requestWithData(data: NSData, name: String, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack) {
        // Define the closure for which the request succeeded
        let success = { (dataTask: URLSessionDataTask, responseObject: AnyObject?) -> Void in
            finished(responseObject, nil)
        }        
        // Define the closure of the request failed
        let failure = { (dataTask: URLSessionDataTask?, error: NSError) -> Void in
            finished(nil, error)
        }        
        post(urlString, parameters: parameters, constructingBodyWith: { (formData) -> Void in
            formData.appendPart(withFileData: data as Data, name: name, fileName: "aa", mimeType: "application/octet-stream")
        }, progress: nil, success: success as? (URLSessionDataTask, Any?) -> Void, failure: (failure as! (URLSessionDataTask?, Error) -> Void))
    }
}
  • The following is a detailed code description

The interface part is derived from the sc2.js code in steemconnect-sdk (https://github.com/steemit/steemconnect-sdk/blob/master/src/sc2.js).

Conversion process :

1. HTTPS request header

js:

headers:{
	      Accept: 'application/json, text/plain, */*',
	      'Content-Type': 'application/json',
	      Authorization: this.options.accessToken,
	}

iOS:

instance.responseSerializer.acceptableContentTypes?.insert("text/html")
instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
instance.requestSerializer = AFJSONRequestSerializer.init()

And we have to set the token, the token is obtained from the login screen callback

let client = STAFNetworkTools.sharedTools;
//    Set request header token   
client.requestSerializer.setValue(UserDataManager.sharedInstance.getToken(), forHTTPHeaderField: "Authorization")

2. Commenting and publishing articles (Publishing articles and comments is an API, which is a little strange)

js:

SteemConnect.prototype.broadcast = function broadcast(operations, cb) {
  return this.send('broadcast', 'POST', { operations }, cb);
};
SteemConnect.prototype.comment = function comment(
  parentAuthor,
  parentPermlink,
  author,
  permlink,
  title,
  body,
  jsonMetadata,
  cb
) {
  const params = {
    parent_author: parentAuthor,
    parent_permlink: parentPermlink,
    author,
    permlink,
    title,
    body,
    json_metadata: JSON.stringify(jsonMetadata),
  };
  return this.broadcast([['comment', params]], cb);
};

iOS:

    class func comment(
                 parentAuthor:String,
                 parentPermlink:String,
                 author:String,
                 permlink:String,
                 body:String,
                 finished:@escaping STClientCallBack) {        
        let param = ["parent_author": parentAuthor,
                     "parent_permlink": parentPermlink,
                     "author":author,
                     "permlink":permlink,
                     "title":"",
                     "body":body,
                     "json_metadata": ""]
        self.broadcast(body: ["operations":[["comment",param]]],finished: finished)
    }    
    class func broadcast(body:Dictionary<String, Any>,
        finished:@escaping STClientCallBack) {
//        print("jsonData ==============="+"\(NSDictionary_STExtension.getJSONStringFromDictionary(dictionary: body))")
        self.post(url: post_broadcast, body: body, finished: finished)
}

The contents of the body should be in strict accordance with ["operations": [["comment", param]]] This format, otherwise it will request failure.

3. vote

js:

SteemConnect.prototype.vote = function vote(voter, author, permlink, weight, cb) {
  const params = {
    voter,
    author,
    permlink,
    weight,
  };
  return this.broadcast([['vote', params]], cb);
};

iOS:

//MARK: - vote
    class func vote(
                    voter:String,
                    author:String,
                    permlink:String,
                    weight:NSInteger,
                    finished:@escaping STClientCallBack){
        let param = ["voter": voter,
                     "author": author,
                     "permlink":permlink,
                     "weight":weight,
                     ] as [String : Any]
        self.broadcast(body: ["operations":[["vote",param]]],finished: finished)
}



Posted on Utopian.io - Rewarding Open Source Contributors

4

comments