Swift:V2登录模块

首先说明几个关键累的作用:

  • UserModel类。

用户模型类。一般我们获取了用户信息是放在一个字典里的,现在我们把字典的数据转化成UserModel,这样在我们使用数据的时候可以做到更加便捷和清晰。

同时,我们把访问与用户数据相关的接口放在这个类里,这样做可以增加代码的简洁性。

  • User类。

User类是一个单例类,用来保存UserModel实例。一般我们获取了数据,并转化为UserModel后,会直接把UserModel实例回调到LoginViewController,用于更新界面。而V2里的做法是把UseModel实例存储到单例User里,什么时候使用什么时候访问。

此外,我们在User里设置了一个观察属性username,通过监听这个属性的变化来更新UI。

User类还有其他和用户相关的作用,不过总体来说是为了信息的存储使用。

实现用户模块用到的接口:

Controller:

1.点击登陆按钮:

func doLoginAction() {
        //参数处理
        var username: String?
        var password: String?
        if let len = self.usernameTextField.text?.characters.count, len > 0{
            username = self.usernameTextField.text
        }
        else{
            self.usernameTextField.becomeFirstResponder()
            return
        }
        
        if let len = self.passwordTextField.text?.characters.count, len > 0{
            password = self.passwordTextField.text
        }
        else{
            self.passwordTextField.becomeFirstResponder()
            return
        }
        
        V2BeginLoadingWithStatus(status: "正在登录")
        UserModel.login(username: username!, password: password!) {(response) in
            if response.success{
                V2Success(status: "登陆成功")
                
                //获取用户信息。注意到没有数据返回,是因为获取的数据实体存储到了单例类User,通过KVO监听实现UI更新
                UserModel.getUserInfoByUsername(username: response.value!, completionHandler: { (response) in
                    self.dismiss(animated: true, completion: nil)
                })
            }
            else{
                V2Error(status: response.message)
            }
        }
    }

说明:要注意在getUserInfoByUsername()的回调里没有数据,是因为我们直接把数据存放到了单例类User,通过监听User类的username属性来更新内容

 

UserModel类:

1.登陆接口1

这个接口实际上不需要参数,直接访问地址获取onceStr、usernameStr、passwordStr

//登录接口1
    //1.获取once,回帖、登录都需要用到once。2.获取username、password两个关键字。一般来说我们访问服务器时,字典中参数的key就叫username,但是这里需要获取。
    class func login(username: String, password: String, completionHandler: @escaping (V2ValueResponse<String>) -> Void){
        
        Alamofire.request(V2EXURL + "signin", headers: MOBILE_CLIENT_HEADERS).response{ (response) in
            if let data = response.data, let utf8Text = String.init(data: data, encoding: .utf8), let jiDoc = Ji.init(htmlString: utf8Text){
                //xml数据转字符串(数据处理)
                let onceStr: String? = jiDoc.xPath("//*[@name='once'][1]")?.first?["value"]
                let usernameStr: String? = jiDoc.xPath("//*[@id='Wrapper']/div/div[1]/div[2]/form/table/tr[1]/td[2]/input[@class='sl']")?.first?["name"]
                let passwordStr:String? = jiDoc.xPath("//*[@id='Wrapper']/div/div[1]/div[2]/form/table/tr[2]/td[2]/input[@class='sl']")?.first?["name"]
                
                if let onceStr = onceStr, let usernameStr = usernameStr, let passwordStr = passwordStr {
                    UserModel.login(username: username, password: password, once: onceStr, usernameFieldName: usernameStr, passwordFieldName: passwordStr, completionHandler: completionHandler)
                    return
                }
            }
            completionHandler(V2ValueResponse.init(success: false, message: "获取必要字段失败"))
        }
        
    }

 

2.登陆接口2

该接口接受参数once、next、passwordStr、usernameStr,成功访问网络后获得头像和username(昵称),然后将username回调。

    //登录接口2
    //说明:通过登录接口1获取的once、usernameStr、passwordStr关键字,然后根据输入的用户名和密码,实现对登录接口的访问,并返回用户名和头像
    class func login(username: String, password: String, once: String, usernameFieldName: String, passwordFieldName: String, completionHandler: @escaping (V2ValueResponse<String>) -> Void) {
        let parameters = [
            "once": once,
            "next": "/",
            passwordFieldName: password,
            usernameFieldName: username
        ]
        
        var dict = MOBILE_CLIENT_HEADERS
         dict["Referer"] = "https://v2ex.com/signin"
        Alamofire.request(V2EXURL+"signin", method: .post, parameters: parameters, headers: dict).response { (response) in
            let htmlString = String.init(data: response.data!, encoding: .utf8)
            if let htmlString = htmlString, let jiHtml = Ji.init(htmlString: htmlString) {
                if let avatarImg = jiHtml.xPath("//*[@id='Top']/div/div/table/tr/td[3]/a[1]/img[1]")?.first {
                    if let username = avatarImg.parent?["href"]{
                        if username.hasPrefix("/member/") {
                            let username = username.replacingOccurrences(of: "/member/", with: "")
                            completionHandler(V2ValueResponse.init(success: true, value: username))
                            return;
                        }
                    }
                    
                }
            }
            completionHandler(V2ValueResponse.init(success: false))
        }
    }

 

3.回调后,根据username访问用户信息接口

获得回调的username后,需要再次调用获取用户信息的接口,获取用户对象的所有属性信息。

    //3.获取用户信息
    //说明:通过『登录接口2』获取的username,访问服务器获取整个用户对象的信息。
    class func getUserInfoByUsername(username: String, completionHandler: ((V2ValueResponse<String>) -> Void)?) {
        let parames = ["username": username]
        Alamofire.request(V2EXURL + "api/members/show.json", parameters:parames, headers: MOBILE_CLIENT_HEADERS).responseJSON { (reponse:DataResponse) in
            if let model = reponse.result.value as? Dictionary<String, Any>{
                let userModel = UserModel()
                userModel.username = model["username"] as! String?
                userModel.avatar_mini = model["avatar_mini"] as! String?
                userModel.avatar_normal = model["avatar_normal"] as! String?
                userModel.avatar_large = model["avatar_large"] as! String?
                
                V2User.sharedInstance.userModel = userModel
                
                completionHandler!(V2ValueResponse.init(success: true, message: "成功"))
            }
        }

    }

成功后返回的就是用户对象的所有数据。把返回的属性和UserModel的属性一一对应就完成对UserModel的操作。

转载于:https://my.oschina.net/u/2943743/blog/863068

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接着分析 (result (type_ident (component id='Bool' bind=Swift.(file).Bool))) (brace_stmt range=[re.swift:1:59 - line:14:1] (pattern_binding_decl range=[re.swift:2:5 - line:2:33] (pattern_named type='[UInt8]' 'b') Original init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) )) Processed init: (call_expr type='[UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:33] nothrow (constructor_ref_call_expr type='(String.UTF8View) -> [UInt8]' location=re.swift:2:19 range=[re.swift:2:13 - line:2:19] nothrow (declref_expr implicit type='(Array<UInt8>.Type) -> (String.UTF8View) -> Array<UInt8>' location=re.swift:2:19 range=[re.swift:2:19 - line:2:19] decl=Swift.(file).Array extension.init(_:) [with (substitution_map generic_signature=<Element, S where Element == S.Element, S : Sequence> (substitution Element -> UInt8) (substitution S -> String.UTF8View))] function_ref=single) (argument_list implicit (argument (type_expr type='[UInt8].Type' location=re.swift:2:13 range=[re.swift:2:13 - line:2:19] typerepr='[UInt8]')) )) (argument_list (argument (member_ref_expr type='String.UTF8View' location=re.swift:2:29 range=[re.swift:2:21 - line:2:29] decl=Swift.(file).String extension.utf8 (declref_expr type='String' location=re.swift:2:21 range=[re.swift:2:21 - line:2:21] decl=re.(file).check(_:_:).encoded@re.swift:1:14 function_ref=unapplied))) ))) (var_decl range=[re.swift:2:9 - line:2:9] "b" type='[UInt8]' interface type='[UInt8]' access=private readImpl=stored writeImpl=stored readWriteImpl=stored)
06-10

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值