2016-11-11 11:35:24 qiuxuewei2012 阅读数 2843

在项目中使用文本输入框出UITextField之外还会经常使用 UITextView ,难免会有需求监听UITextView文本框内文本数量.下面介绍在swift3中两种常用方式

方式一: 全局通知

1.注册通知
在合适位置注册监听UITextView文本变化的全局通知

 //UITextView 监听开始输入的两种方法
        //方法一:通知
        NotificationCenter.default.addObserver(self, selector: #selector(ComposeVC.textViewChange), name: NSNotification.Name.UITextViewTextDidChange, object: nil)

2.实现监听方法 此处方法名为 textViewChange

@objc fileprivate func textViewChange() {
        XWLog("textView文字改变 :\(composeTextView.text)")
}

3.在控制器销魂不忘销魂通知

//移除通知
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

方式二: 代理

1.设置代理

//1.设置代理
composeTextView.delegate = self

2.遵守代理协议,实现代理方法

//MARK: - TEXTVIEW DELEGATE
extension ComposeVC : UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        if textView.text.lengthOfBytes(using: .utf8) > 0 {
            //文本框内有文字个数大于0 进行相应操作

        }else{
            //文本框内有文字个数等于0 进行相应操作

        }
    }
}
2018-07-30 15:46:00 qq_31901919 阅读数 527

根据项目需求,要求监听用户是否真的拨打电话以及打电话时长!
直接上代码咯。。。

    private var beforeDate : Date!
    private var callCenter : Any?//声明属性
    //(注意:这里必须是全局属性,不能定义局部变量,由于iOS10.0以后版本和之前的版本方法不同,所以我这里声明了一个任意类型的全局变量)

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }
//    拨打电话
    @IBAction func callPhone(_ sender: Any) {
        if let phoneURL = URL.init(string: "telprompt://10086") {

            if #available(iOS 10.0, *) {//ios10.0之后调用此方法
                self.callCenter = CXCallObserver()
                UIApplication.shared.open(phoneURL, options: [:]) { (isSuccess) in
                    if(!isSuccess){
                        return
                    }
                    //设置电话代理
                    if let cObserver = self.callCenter as? CXCallObserver{
                        cObserver.setDelegate(self, queue: DispatchQueue.main)
                    }
                }
            } else {//ios10.0之前
                self.callCenter = CTCallCenter()
                UIApplication.shared.openURL(phoneURL)
                if let caCenter = self.callCenter as? CTCallCenter {
                    caCenter.callEventHandler = { (call: CTCall) -> Void in
                        if call.callState == CTCallStateDisconnected {
                            print("电话挂断")
                            //计算通话时长
                            self.getCallPhoneTime()
                        }
                        if call.callState == CTCallStateConnected {
                            print("电话接通")
                            //记录当前时间
                            self.setBeginDate()
                        }
                        if call.callState == CTCallStateIncoming {
                            print("通话途中收到别的来电")
                        }
                        if call.callState == CTCallStateDialing {
                            print("电话播出")
                        }
                    }
                }
            }
        }else{
            print("电话不能接通!")
            return
        }
    }
    //iOS10.0以后版本下的电话监听代理
    @available(iOS 10.0, *)
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        NSLog("outgoing :%d  onHold :%d   hasConnected :%d   hasEnded :%d",call.isOutgoing,call.isOnHold,call.hasConnected,call.hasEnded)
        /** 以下为我手动测试 如有错误欢迎指出
         拨通:  outgoing :1  onHold :0   hasConnected :0   hasEnded :0
         拒绝:  outgoing :1  onHold :0   hasConnected :0   hasEnded :1
         链接:  outgoing :1  onHold :0   hasConnected :1   hasEnded :0
         挂断:  outgoing :1  onHold :0   hasConnected :1   hasEnded :1

         新来电话:    outgoing :0  onHold :0   hasConnected :0   hasEnded :0
         保留并接听:  outgoing :1  onHold :1   hasConnected :1   hasEnded :0
         另一个挂掉:  outgoing :0  onHold :0   hasConnected :1   hasEnded :0
         保持链接:    outgoing :1  onHold :0   hasConnected :1   hasEnded :1
         对方挂掉:    outgoing :0  onHold :0   hasConnected :1   hasEnded :1
         */

        //接通
        if (call.isOutgoing && call.hasConnected && !call.hasEnded) {
            //记录当前时间
            self.setBeginDate()
        }
        //挂断
        if (call.isOutgoing && call.hasConnected && call.hasEnded) {
            //计算通话时长
            self.getCallPhoneTime()
        }
    }

    //记录当前时间
    func setBeginDate() {
        self.beforeDate = Date.init()
    }
    //计算通话时长
    func getCallPhoneTime() {

        let dat = Date.init(timeInterval: 0, since: self.beforeDate)
        let a = dat.timeIntervalSinceNow

        let timeString = String.init(format: "%0.f", fabs(a))//转为字符型
        NSLog("%@秒",timeString)
    }
2018-11-12 09:14:05 weixin_43566445 阅读数 638

实现功能:

自动缓存,网络状态监听,无网络状态自动调用缓存数据.

统一全局manager,一次设定baseURL与header.全局使用.

优化调用方式,使网络请求更轻便,更直观.

#使用第三方库:

Alamofire: 核心功能,网络请求.

SwiftyJSON: 数据缓存时使用,方便地处理JSON数据.

/建议配合使用MBProgressHud,但因为非必须,demo中去掉了./


1.自动缓存

在网络请求成功时调用,将数据存储.

/// 进行数据缓存
    ///
    /// - Parameters:
    ///   - responseObject: 缓存数据
    ///   - request: 请求
    ///   - parameters: 参数
    public func cacheResponseObject(responseObject: AnyObject,
                                   request: URLRequest,
                                   parameters: Dictionary<String,Any>?){
        if !(responseObject is NSNull) {
            let directoryPath:String = cachePath
            ///如果没有目录,那么新建目录
            if !FileManager.default.fileExists(atPath: directoryPath, isDirectory: nil){
                do {
                    try FileManager.default.createDirectory(atPath: directoryPath,
                                                            withIntermediateDirectories: true,
                                                            attributes: nil)
                }catch let error {
                    print("create cache dir error: " + error.localizedDescription + "\n")
                    return
                }
            }
            ///将get请求下的参数拼接到url上
            let absoluterURL = self.generateGETAbsoluteURL(url: (request.url?.absoluteString)!, parameters)
            ///对url进行md5加密
            let key = absoluterURL.md5()
            ///将加密过的url作为目录拼接到默认路径
            let path = directoryPath.appending(key)
            ///将请求数据转换成data
            let dict:AnyObject = responseObject
            var data:Data? = nil
            do{
                try data = JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
            }catch{
            }
            ///将data存储到指定路径
            if data != nil{
                let isOk = FileManager.default.createFile(atPath: path,
                                                          contents: data,
                                                          attributes: nil)
                if isOk{
                    print("cache file ok for request: \(absoluterURL)\n")
                }else{
                    print("cache file error for request: \(absoluterURL)\n")
                }
            }
        }
    }

2.网络状态监听.

  ///监听网络状态
    public func detectNetwork(netWorkStatus: @escaping ELNetworkStatus){
        let reachability = NetworkReachabilityManager()
        reachability?.startListening()
        reachability?.listener = { status in
            if reachability?.isReachable ?? false {
                switch status {
                case .notReachable:
                    ew_NetworkStatus = EWNetworkStatus.NotReachable
                case .unknown:
                    ew_NetworkStatus = EWNetworkStatus.Unknown
                case .reachable(.wwan):
                    ew_NetworkStatus = EWNetworkStatus.WWAN
                case .reachable(.ethernetOrWiFi):
                    ew_NetworkStatus = EWNetworkStatus.WiFi
                }
            }else{
                ew_NetworkStatus = EWNetworkStatus.NotReachable
            }
            netWorkStatus(ew_NetworkStatus.rawValue)
        }
    }

3.无网络时获取缓存数据

   ///从缓存中获取数据
    public func cahceResponseWithURL(url: String,paramters: Dictionary<String,Any>?) -> Any?{
        var cacheData:Any? = nil
        let directorPath = cachePath
        let absoluteURL = self.generateGETAbsoluteURL(url: url, paramters)
        ///使用md5进行加密
        let key = absoluteURL.md5()
        let path = directorPath.appending(key)
        let data:Data? = FileManager.default.contents(atPath: path)
        if data != nil{
            cacheData = data
            print("Read data from cache for url: \(url)\n")
        }
        return cacheData
    }
 ///解析缓存数据
    class func successResponse(responseData: Any,callback success: EWResponseSuccess){
        success(self.tryToParseData(responseData: responseData))
    }
    ///解析数据
    class func tryToParseData(responseData: Any) -> AnyObject {
        if responseData is Data{
            do{
                let json =  try JSON(data: responseData as! Data)
                return json as AnyObject
            }catch{
                return responseData as AnyObject
            }
        }else{
            return responseData as AnyObject
        }
    }

4.设定manager

//获取alamofire.manager
   private lazy var manager: SessionManager = {
        let config:URLSessionConfiguration = URLSessionConfiguration.default
        let serverTrustPolicies: [String: ServerTrustPolicy] = [
            ///正式环境的证书配置,修改成自己项目的正式url
            "www.baidu.com": .pinCertificates(
                certificates: ServerTrustPolicy.certificates(),
                validateCertificateChain: true,
                validateHost: true
            ),
            ///测试环境的证书配置,不验证证书,无脑通过
            "192.168.1.213:8002": .disableEvaluation,
            ]
        config.httpAdditionalHeaders = ew_httpHeaders
        config.timeoutIntervalForRequest = ew_timeout
        //根据config创建manager
        return SessionManager(configuration: config,
                                 delegate: SessionDelegate(),
                                 serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
    }()

5.核心网络请求功能

///核心方法
    public func requestWith(url: String,
                           httpMethod: Int32,
                           params: Dictionary<String,Any>?,
                           success: @escaping EWResponseSuccess,
                           error: @escaping EWResponseFail){
        if (self.baseUrl() == nil) {
            if URL(string: url) == nil{
                print("URLString无效")
                return
            }
        } else {
            if URL(string: "\(self.baseUrl()!)\(url)" ) == nil{
                print("URLString无效")
                return
            }
        }
        let encodingUrl = encodingURL(path: url)
        let absolute = absoluteUrlWithPath(path: encodingUrl)
        let lastUrl = buildAPIString(path: absolute)
        //打印header进行调试.
        if let params = params{
            print("\(lastUrl)\nheader =\(String(describing: ew_httpHeaders))\nparams = \(params)")
        }else {
            print("\(lastUrl)\nheader =\(String(describing: ew_httpHeaders))")
        }
        //get
        if httpMethod == 0{
            //无网络状态获取缓存
            if ew_NetworkStatus.rawValue == EWNetworkStatus.NotReachable.rawValue
                || ew_NetworkStatus.rawValue == EWNetworkStatus.Unknown.rawValue {
                let response = self.cahceResponseWithURL(url: lastUrl,
                                                                 paramters: params)
                if response != nil{
                    self.successResponse(responseData: response!, callback: success)
                }else{
                    return
                }
            }
            manager.request(lastUrl,
                             method: .get,
                             parameters: params,
                             encoding: URLEncoding.default,
                             headers: nil).responseJSON {
                                (response) in
                                switch response.result{
                                case .success:
                                    if let value = response.result.value as? Dictionary<String,Any>{
                                        ///添加一些全部接口都有的一些状态判断
                                        if value["status"] as! Int == 1010 {
                                            error("登录超时,请重新登录" as AnyObject)
                                            _ = Keychain.clear()
                                            return
                                        }
                                        success(value as AnyObject)
                                        //缓存数据
                                        self.cacheResponseObject(responseObject: value as AnyObject,
                                                                 request: response.request!,
                                                                 parameters: nil)
                                    }
                                case .failure(let err):
                                    error(err as AnyObject)
                                    debugPrint(err)
                                }
            }
        }else{
            //post
            manager.request(lastUrl,
                             method: .post,
                             parameters: params!,
                             encoding: JSONEncoding.default,
                             headers: nil).responseJSON { (response) in
                                switch response.result{
                                case .success:
                                    ///添加一些全部接口都有的一些状态判断
                                    if let value = response.result.value as? Dictionary<String,Any> {
                                        if value["status"] as! Int == 1010 {
                                            error("登录超时,请重新登录" as AnyObject)
                                            _ = Keychain.clear()
                                            return
                                        }
                                        success(value as AnyObject)
                                    }
                                case .failure(let err):
                                    error(err as AnyObject)
                                    debugPrint(error)
                                }
            }
        }
    }

6.添加请求方法


extension EWNetworking{
    ///get请求demo
    public func getDataTest(id: String,
                       success: @escaping EWResponseSuccess,
                       failure: @escaping EWResponseFail){
        let path = "test"
        EWNetworking.ShareInstance.getWith(url: path, params: ["id": id], success: { (response) in
            guard let json = response as? [String:Any] else { return }
            ///保证接口调通, 否则返回错误信息
            guard json["status"] as! NSNumber == 1 else {
//                MBProgressHud.showTextHudTips(message: json["msg"] as? String)
                print(json["msg"])
                failure(response)
                return
            }
            guard let dict = json["obj"] as? [String:Any] else {
                failure(NSError(domain: "转字典失败", code: 2000, userInfo: nil))
                return
            }
            guard let dataArray = dict["data"] else {
                failure(NSError(domain: "获取数组失败", code: 2000, userInfo: nil))
                return
            }
            success(dataArray as AnyObject)
        }) { (error) in
            failure(error)
//            MBProgressHud.showTextHudTips(message: "网络请求错误")
        }
    }
    ///post请求demo
    public func postDataTest(id: String,
                                success: @escaping EWResponseSuccess,
                                failure: @escaping EWResponseFail){
        let path = "v1/passport/register"
        EWNetworking.ShareInstance.postWith(url: path, params: ["id": id], success: { (response) in
            guard let json = response as? [String:Any] else { return }
            guard json["status"] as! NSNumber == 1 else {
//                MBProgressHud.showTextHudTips(message: json["msg"] as? String)
                print(json["msg"])
                failure(response)
                return
            }
            success(response as AnyObject)
        }) { (error) in
            failure(error)
//            MBProgressHud.showTextHudTips(message: "网络请求错误")
        }
    }
}

7.调用请求demo

 func getDemo(){
        EWNetworking.ShareInstance.getDataTest(id: "1", success: { [weak self] (response) in
            guard let weakSelf = self else { return }
            guard let model = response as? [String] else { return }
            ///根据获取model来进行相应操作
        }) { (error) in
        }
    }
    func postDemo(){
        EWNetworking.ShareInstance.postDataTest(id: "1", success: { [weak self] (response) in
            guard let weakSelf = self else { return }
            guard let model = response as? [String] else { return }
            ///根据获取model来进行相应操作
        }) { (error) in
        }
    }

github地址:AlamofireEncapsulation

网络请求是开发中非常非常核心的一部分,也是非常非常常用的一部分,所以优化我们的请求方式对提高开发效率非常有帮助,更轻便的请求方法更直观,也更易维护.
Alamofire是很好的网络请求框架,但是正因为如此我们才需要对其封装使得更适合个人使用.
这种封装方式只是个人使用时的优化,可能有更好的方法,所以发出来纯属抛砖引玉.

有问题欢迎探讨.

2016-11-17 11:45:09 haogaoming123 阅读数 1274

AVplayer播放完视频后怎么释放,我把监听都移除了,退出控制器后依然会有声音?而且还会走闭包?

当遇到这类问题的时候,可能就是你在释放类的时候,没有将AVPlayer完全释放掉的原因。

self.player.currentItem.cancelPendingSeeks()
self.player.currentItem.asset.cancelLoading()
//当代码中调用了addPeriodicTimeObserverForInterval方法的时候,还需要释放addPeriodicTimeObserverForInterval返回的playbackObserver对象
self.player.removeTimeObserver:playbackObserver()

至此,才可以将AVPlayer运行中的操作释放掉,在加上deinit{}方法中remove掉的监听通知方法就ok了!

我的简书链接:http://www.jianshu.com/p/0ebd070efbfa





2015-10-11 22:13:55 hsf_study 阅读数 268


    在swift 中,所有的函数如果不使用 private 修饰,是全局共享的。若果private修饰后,就无法来监听事件。因为按钮监听方法,就无法让`运行循环`来调用的,因此不能直接使用 private。
   

    @objc 关键字能够保证运行循环能够调用,走的 oc 的消息机制,调用之前不再判断方法是否存在和 private 联用,就能够做到对方法的保护。

   



    

    
  
没有更多推荐了,返回首页