美文网首页IOS每日BUG。iOS Developer程序员
我用Swift开发项目踩过的坑

我用Swift开发项目踩过的坑

作者: 江水东流 | 来源:发表于2017-03-15 15:30 被阅读1012次

    好多人学习swift,语法什么的很快就学会了,但是要做项目的话,有不少细节及注意点.最近我用swift开发项目,踩过的坑一一列出.

    宏定义

    oc上的宏定义没有了,swift中用let或者函数代替,swift随便建立一个swift文件都可以当成oc的pch文件使用,在里面写常量.

    func kfont(f: CGFloat) -> UIFont {return UIFont.systemFont(ofSize: f)}
    let kScreenWidth = UIScreen.main.bounds.size.width

    • 强转成字典和数组

      let dic = data as! [String:AnyObject]
      let statues = dic["statuses"] as! [AnyObject]
      option+ command +/ 代码注释
      option + 点击变量 显示变量类型
      删除数组中指定元素要用 NSMutableArray
      var selectedBtnArray : NSMutableArray = []//选中的按钮

    • //字典转json
      

      static func toJSONString(dict: [String: Any])-> String {
      let data = try? JSONSerialization.data(withJSONObject: dict, options: JSONSerialization.WritingOptions.prettyPrinted)
      let strJson = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
      return strJson! as String
      }
      json格式字符串转字典:
      guard let dic = response as? [String: Any] else { return }
      //string转字典
      func getDictionaryFromJSONString(jsonString: String) ->NSDictionary{
      let jsonData:Data = jsonString.data(using: .utf8)!
      let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
      if dict != nil {
      return dict as! NSDictionary }
      return NSDictionary()
      }

    • string —> data data — string

    let testData = str.data(using: String.Encoding.utf8.rawValue)
    let data = json.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!

        var backToString = String(data: imageData, encoding: String.Encoding.utf8) as String!
    
    • string去掉空格和换行
      let str = backToString?.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
    • tableView的数据源代理方法可以写在类下面的extension里面

    extension ZJDetectController{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
    }

    • kvo
      1,在写swift的KVO的过程中,其不能监听基本数据类型的属性,若想监听需将其改成NSNumber类型,或其它类型,否则监听的代理方法不走。
      2,在写swift的KVO的过程中,被监听的属性必须用“dynamic”修饰,否则监听的代理方法不走。
      //kvo的属性要这样做 dynamic NSNumber
      dynamic var totalH : NSNumber = 155 //一行 self?.totalH = NSNumber(value: Float(btn.maxY + 35))

    addView.addObserver(self, forKeyPath: "totalH", options: .new, context: nil)
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard let change = change else { return }
    let totalH : CGFloat = change[NSKeyValueChangeKey.newKey] as! CGFloat
    print("totalH",totalH)
    currentAddView?.height = totalH
    }
    deinit {
    self.removeObserver(self, forKeyPath: "totalH")

    • set get

    var zimu : String?{
    didSet{
    titleLabel?.text = zimu
    }
    }
    // var zimu2: String?{
    // guard let kzimu = zimu else {
    // return nil
    // }
    //
    // return "22(kzimu)"
    // }

    • 键盘和文本框精确对齐

    注册键盘willShow的通知
    override func keyboardWillShow(notification: Notification){
    let dict: [String: AnyObject] = notification.userInfo as! [String : AnyObject]
    let aValue : CGRect = (dict as NSDictionary).object(forKey: UIKeyboardFrameEndUserInfoKey) as! CGRect
    let keyboardH = aValue.size.height
    var delta: CGFloat = 0.0
    if keyboardH <= CGFloat(0) {
    return
    }
    let window = UIApplication.shared.keyWindow!
    history_Y_offset = (currentTextView?.convert((currentTextView?.bounds)!, to: window).origin.y)!
    delta = self.history_Y_offset - (kScreenHeight - keyboardH - 90);
    var offset = self.backScrollVi.contentOffset;
    offset.y += delta;
    if ((offset.y) < CGFloat(0) ) {
    offset.y = 0;
    }
    if (self.history_Y_offset + 80 + keyboardH > kScreenHeight) {
    self.backScrollVi.setContentOffset(offset, animated: true)
    }
    }

    • 用闭包自定义一个可以点击的label,label文字可以有偏移量

    var inset : UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
    var labelTapClosure: (( _ label: ZJLabel)->())?
    override init(frame: CGRect) {
    super.init(frame: frame)
    self.isUserInteractionEnabled = true
    let tap = UITapGestureRecognizer(target: self, action: #selector(zjLabelTap(recognizer:)))
    self.addGestureRecognizer(tap)
    }
    @objc func zjLabelTap(recognizer: UITapGestureRecognizer){
    let label = recognizer.view as! ZJLabel
    if labelTapClosure != nil {
    labelTapClosure?(label)
    }
    }
    convenience init(insets: UIEdgeInsets) {
    self.init()
    inset = insets
    }
    override func drawText(in rect: CGRect) {
    return super.drawText(in: UIEdgeInsetsInsetRect(rect, inset))
    }

    • 异步

    DispatchQueue.global().async {
    print("开始执行异步任务")
    Thread.sleep(forTimeInterval: 2)
    print("异步任务执行完毕")
    DispatchQueue.main.async {
    print("回到UI线程")
    }
    }

    • 颜色16进制转换

    extension UIColor {
    //类方法 static func
    static func colorWithHex(hexColor:Int64)->UIColor{
    let red = ((CGFloat)((hexColor & 0xFF0000) >> 16))/255.0;
    let green = ((CGFloat)((hexColor & 0xFF00) >> 8))/255.0;
    let blue = ((CGFloat)(hexColor & 0xFF))/255.0;
    return UIColor(red: red, green: green, blue: blue, alpha: 1)
    }
    }

    • 代理

      // 定义代理协议
      protocol ZJLoginViewDelegate: NSObjectProtocol {
      func didClickLoginBtn(account: String,passWord: String)
      }
      // 定义代理对象
      weak var loginDelegate: ZJLoginViewDelegate?
      if loginDelegate != nil {
      loginDelegate?.didClickLoginBtn(account: kaccount , passWord: kpassWord )
      }

    • 闭包之间传递

    typealias DateClosure = (( _ dateStr: String)->())?
    var callBackClosure : DateClosure?
    convenience init(date: (( _ dateStr: String)->())? ) { self.init()
    callBackClosure = date
    }
    @objc private func btnClick(){
    if callBackClosure != nil {
    callBackClosure!!(dateStr ?? "")
    }
    }

    • 闭包传值
      传出类

      var loginButtonClosure: (( _ account: String, _ pass: String)->())?
      if loginButtonClosure != nil {
      loginButtonClosure?(kaccount, kpassWord )

      }
      传入类
      loginVi.loginButtonClosure = {(account, pass) in
      }
    • 直接从字典取值判断字典value 为空
            guard let dic = response as? [String: Any] else { return }
    
            guard let resultDict = dic["result"] as? [String: Any] else {   return}
            //添加
            for  e in resultDict {
                if (e.value as AnyObject).isEqual(NSNull.init()) {//value为null
                }else{
                   let str = String(describing: e.value)
                    print("非空",e.value,str)
                    self.dictSave[e.key] = String(describing:resultDict[e.key])
                }
    
    • bug
      自定义textField时候 设置leftViewframe时候不能在layoutSubView里面时用self.width和 self.leftViewMode = .always 要不会死循环

    编译不动时候,点击到下面的界面,会有向右的箭头指向一个方法,这个方法数据有问题


    屏幕快照 2017-03-15 15.42.12.png
    • 解析网络数据

    guard let dic = response as? [String: Any] else { return }
    guard let statusArray = dic["result"] as? [[String: Any]] else { return}
    let statusArr = NSArray.yy_modelArray(with: ChectDetectM.self, json: statusArray) as! [ChectDetectM] //转成模型数组
    // 普通转模型
    let loginM1 = ZJLoginM.yy_model(withJSON: json)

    封装AFN

    import UIKit
    import AFNetworking
    enum RequestType: Int {
    case GET
    case POST
    }
    class JDNetworkTools: AFHTTPSessionManager {
    // 闭包回调类型的别名
    typealias CallBackType = (Any?,Error?)->()
    // 单例全局访问点
    static let sharedTools: JDNetworkTools = {
    let tools = JDNetworkTools(baseURL: NSURL(string: kBaseURL)! as URL)
    tools.responseSerializer.acceptableContentTypes?.insert("text/html")
    tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
    tools.requestSerializer.timeoutInterval = 20
    return tools
    }()
    //@escaping 逃逸闭包 在当函数参数传入异步返回执行时候加上
    fileprivate func request(type: RequestType,url: String,params: Any?,callback: @escaping CallBackType){
    //utr8
    let urlS = url.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
    guard let urlStr = urlS else { return }
    if type == RequestType.GET {
    get(urlStr, parameters: params, progress: nil, success: { (, response) in
    callback(response,nil)
    }, failure: { (
    , error) in
    callback(nil,error)
    })
    }else if type == RequestType.POST {
    post(urlStr, parameters: params, progress: nil, success: { (, response) in
    callback(response, nil)
    }, failure: { (
    , error) in
    callback(nil, error)
    })
    }
    }
    }
    extension JDNetworkTools{
    // MARK: 登陆
    func login(aesStr: NSString,callback: @escaping CallBackType) {
    let url = "auth/login.do"
    let params: [String: Any] = [
    "token": aesStr,
    ]
    request(type: .GET, url: url, params: params, callback: callback)
    }
    }

    相关文章

      网友评论

        本文标题:我用Swift开发项目踩过的坑

        本文链接:https://www.haomeiwen.com/subject/qkshwttx.html