备注:原作者分享几个
参考内容
```
func _pow_3(_ base: Double, _ exponent: Int) -> Double {
var isNegative = false
var exp = exponent
if exp < 0 {
isNegative = true
exp = -exp
}
let result = _pow_2(base, exp)
return isNegative ? 1 / result : result
}
```
参考内容
func findMedianSortedArrays_3(_ array1: [Int], _ array2: [Int]) -> Double {
let total = array1.count + array2.count
let index = total / 2
let count = array1.count < array2.count ? array2.count : array1.count
var array = [Int]()
var i = 0, j = 0;
for _ in 0...count {
if array.count >= index + 1 {
break
}
if array1[i] < array2[j] {
array.append(array1[i])
i += 1
} else {
array.append(array2[j])
j += 1
}
}
return total % 2 == 1 ? Double(array[index]) : Double(array[index] + array[index - 1]) * 0.5
}
参考内容
- UIButton setTitle的时候才会创建UILabel, setImage的时候才会创建UIImageView, 你为什么吧frame给写死... 不知道UIView有sizeToFit么, 你怎么不实现sizeThatFits, 你是完全不会用吧... 你知道UIButton用AutoLayout布局的时候只要设置origin坐标, 宽高就可以自适应了, 你自定义的时候怎么不实现呢? setBackgroundImage和setImageEdgeInsets
import UIKit protocol ButtonInterface { func setTitle(_ title: String); func setTitleColor(_ titleColor: UIColor); func setTitleEdgeInsets(_ edgeInsets: UIEdgeInsets); func setImage(_ image: UIImage); func setBackgroundImage(_ image: UIImage); func setImageEdgeInsets(_ edgeInsets: UIEdgeInsets);
} class Button: UIControl, ButtonInterface { lazy var titleLabel: UILabel = UILabel() lazy var imageView: UIImageView = UIImageView() lazy var backgroundImageView: UIImageView = UIImageView() var titleLabelIsCreated = false var imageViewIsCreated = false var backgroundImageViewCreated = false internal func setTitle(_ text: String) { if !titleLabelIsCreated {
addSubview(titleLabel)
titleLabelIsCreated = true }
titleLabel.text = text
} internal func setTitleColor(_ textColor: UIColor) { if !titleLabelIsCreated { return }
titleLabel.textColor = textColor
} internal func setTitleEdgeInsets(_ edgeInsets: UIEdgeInsets) { if !titleLabelIsCreated { return }
} internal func setImage(_ image: UIImage) { if !imageViewIsCreated {
addSubview(imageView)
imageViewIsCreated = true }
imageView.image = image
} internal func setBackgroundImage(_ image: UIImage) { if !backgroundImageViewCreated {
addSubview(backgroundImageView)
insertSubview(backgroundImageView, at: 0)
backgroundImageViewCreated = true }
backgroundImageView.image = image
} internal func setImageEdgeInsets(_ edgeInsets: UIEdgeInsets) { if !imageViewIsCreated { return }
} override func sizeThatFits(_ size: CGSize) -> CGSize { if titleLabelIsCreated && !imageViewIsCreated && !backgroundImageViewCreated { let text: NSString? = titleLabel.text as NSString? let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0 let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0 return CGSize(width: titleLabelW, height: titleLabelH + 10)
} else if !titleLabelIsCreated && imageViewIsCreated { return imageView.image?.size ?? CGSize.zero
} else if titleLabelIsCreated && imageViewIsCreated { let text: NSString? = titleLabel.text as NSString? let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0 let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0 let imageViewW: CGFloat = imageView.image?.size.width ?? 0.0 let imageViewH: CGFloat = imageView.image?.size.height ?? 0.0 return CGSize(width: titleLabelW + imageViewW, height: imageViewH > titleLabelH ? imageViewH : titleLabelH)
} else { return backgroundImageView.image?.size ?? CGSize.zero
}
} override func layoutSubviews() { super.layoutSubviews() if titleLabelIsCreated && !imageViewIsCreated {
titleLabel.frame = bounds
titleLabel.textAlignment = .center
} else if !titleLabelIsCreated && imageViewIsCreated { let y: CGFloat = 0; let width: CGFloat = imageView.image?.size.width ?? 0; let x: CGFloat = (bounds.width - width) * 0.5; let height: CGFloat = bounds.height;
imageView.frame = CGRect(x: x, y: y, width: width, height: height)
} else if titleLabelIsCreated && imageViewIsCreated { let imageViewY: CGFloat = 0; let imageViewW: CGFloat = imageView.image?.size.width ?? 0; let imageViewH: CGFloat = bounds.height; let text: NSString? = titleLabel.text as NSString? let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0 let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0 let imageViewX: CGFloat = (bounds.width - imageViewW - titleLabelW) * 0.5; let titleLabelX: CGFloat = imageViewX + imageViewW let titleLabelY = (bounds.height - titleLabelH) * 0.5 titleLabel.frame = CGRect(x: titleLabelX, y: titleLabelY, width: titleLabelW, height: titleLabelH)
imageView.frame = CGRect(x: imageViewX, y: imageViewY, width: imageViewW, height: imageViewH)
} if backgroundImageViewCreated {
backgroundImageView.frame = bounds
}
}
}
参考内容
可以参考
YTKNetworking
或者AFN
-
设计一个网络框架, 如何进行不同数据解析的设计(header, body), 并能够进行自定义
-
重连机制如何处理, 状态码错误转发机制的处理
-
如何避免回调地狱, 实现Promise的自实现.
- 两层三部分数据结构
- 标准的APP是有4个环境的,开发、测试、预发、正式,
- Client做两个操作,一个是生成NSURLRequest,一个是生成NSURLSessionDataTask并发起,另外还要暴露取消操作给Engine,
- casa:集约型API调用其实就是所有API的调用只有一个类,然后这个类接收API名字,API参数,以及回调着陆点(可以是target-action,或者block,或者delegate等各种模式的着陆点)作为参数。然后执行类似startRequest这样的方法,它就会去根据这些参数起飞去调用API了,然后获得API数据之后再根据指定的着陆点去着陆。
- casa思路:在BaseDataEngine的dealloc里面做取消网络请求操作,把BaseDataEngine绑定给ViewController,当ViewController销毁时BaseDataEngine也就跟着销毁了
- 每个接口生成一个BaseEngine实例,持有Client返回的requestID,所以就可以做取消操作,简单的使用场景
我们将错误处理分为两个步骤,一个是错误解析,一个是错误的UI展示
-
设计的接口返回数据是标准的id data, NSError *error,是Client就把error处理好,不管你是网络超时错误也好,或者是数据格式不正确也好,都error解析完整,把code错误码定义好,上层根据需要通过code来做具体的UI展示,因为有的界面的错误需要用户的点击确认,有的页面的错误只是一闪而过的提示框,把error交给BaseEngine或者DataEngine来处理errorUI,
-
定义了一套errorUI的枚举,当BaseEngine拿到error的时候就去做错误的展示