踩过的坑和奇怪的API笔记
- UINavigationController 导航栏
- 设置导航栏颜色
- 去掉导航栏下面的分割线
- 设置导航栏字体和字体颜色
- UITabBar
- UITabBar和导航栏结合使用
- 获取UITabBar的高度
- 跳转界面隐藏UITabBar的方案
- UITableView
- UITableViewCell里点击事件不生效
- 设置分割线内边距
- 隐藏所有分割线分割线
- 隐藏底部多余行及分割线
- UICollectionView & UIScrollView
- cell里的按钮区域只能点击无法滑动
- 允许多选
- ScrollView是否显示滑动条
- ScrollView使ContentSize小于UIScrollView大小也能滑动
- ScrollView分页滑动
- UIScrollView截长图
- UIView
- 截图
- 拼接图片
- 获取当前UIView的UIVIewController
- UIImage
- 重设图片大小和等比例缩放
- 裁切图片
- 获取纯色UIImage
- 改变颜色
- 获取网络图片
- UIButton
- UIButton中图片和文字的位置变换
- UIColor & Color
- UIColor 十六进制
- Color 十六进制
- CGRect
- CGRect等比例缩放
- 点击事件不生效可能的原因
- Date
- 获取农历日期
- 当前月有多少天
- 今天是今年第几天
- 本周是今年第几周
- String
- sha256
- unicode
- urlEncoded
- Base64
- Dictionary
- 合并字典
- Application
- 手机真实宽高(px)
- 设计宽高
- 手机序列号(唯一标识)
- 手机别名:用户定义的名称
- 设备名称
- 手机系统版本
- 手机型号
- 地方型号 (国际化区域名称)
- 是否是IPad
UINavigationController 导航栏
设置导航栏颜色
navigationController?.navigationBar.barTintColor = .blue
去掉导航栏下面的分割线
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
- 此时导航栏颜色和View背景相同,应该类似吧导航栏设置透明了的效果
- 使用方法一设置导航栏颜色为
.clear
并不能达到相同效果 - 本方法会导致方法一设置导航栏颜色失效,此时使用以下代码设置导航栏颜色
navigationController?.navigationBar.backgroundColor = .orange
设置导航栏字体和字体颜色
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.black,NSAttributedString.Key.font : UIFont.systemFont(ofSize: 25)]
UITabBar
UITabBar和导航栏结合使用
tabBarCtrl = UITabBarController()
tabBarCtrl.tabBar.tintColor = .DesignGreen
let view1 = ViewHome()
view1.tabBarItem.image = UIImage(named: "xiaozujian")
view1.tabBarItem.title = "组件"
let view2 = ViewIcon()
view2.tabBarItem.image = UIImage(named: "tubiao")
view2.tabBarItem.title = "图标"
let view1 = UINavigationController.init(rootViewController: viewHome)
let view2 = UINavigationController.init(rootViewController: viewIcon)
tabBarCtrl.addChild(view1)
tabBarCtrl.addChild(view2)
tabBarCtrl.selectedIndex = 0 //默认选择
self.window?.rootViewController = tabBarCtrl
window?.makeKeyAndVisible()
获取UITabBar的高度
let height = tabBarCtrl.tabBar.bounds.size.height
跳转界面隐藏UITabBar的方案
override func viewWillDisappear(_ animated: Bool) {
tabBarCtrl.tabBar.isHidden = true
}
UITableView
UITableViewCell里点击事件不生效
使用 cell.contentView.addSubview
代替 cell.addSubview
设置分割线内边距
tableView.separatorInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
隐藏所有分割线分割线
- 方法一:
self.separatorStyle = .none
- 方法二:
tableView.separatorInset = UIEdgeInsets(top: 0, left: tableView.frame.width, bottom: 0, right: 0)
隐藏底部多余行及分割线
tableview.tableFooterView = UIView(frame: CGRect.zero)
UICollectionView & UIScrollView
cell里的按钮区域只能点击无法滑动
使用`UILabel`或`UIImageView`等绑定`UITapGestureRecognizer` 代替`UIButton`
func InitUI(){
let img = UIImageView(frame:CGRect(xxxxxx))
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(ClickBtn(_:)))
img.addGestureRecognizer(singleTapGesture)
img.isUserInteractionEnabled = true
}
@objc func ClickBtn(_ tap:UITapGestureRecognizer){
}
允许多选
collection.allowsMultipleSelection = true
ScrollView是否显示滑动条
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
ScrollView使ContentSize小于UIScrollView大小也能滑动
scrollView.alwaysBounceVertical = true
scrollView.alwaysBounceHorizontal = true
ScrollView分页滑动
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (!decelerate)
{
scrollView.setContentOffset(CGPoint(x: CGFloat(Int(scrollView.contentOffset.x/pageWidth + 0.5))*pageWidth, y: scrollView.contentOffset.y), animated: true)
selectPage = Int(scrollView.contentOffset.x/pageWidth + 0.5)
}
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
scrollView.setContentOffset(CGPoint(x: CGFloat(Int(scrollView.contentOffset.x/pageWidth + 0.5))*pageWidth, y: scrollView.contentOffset.y), animated: true)
selectPage = Int(scrollView.contentOffset.x/pageWidth + 0.5)
}
UIScrollView截长图
///截长图
extension UIScrollView {
/// 截长屏Image
var captureLongImage: UIImage? {
var image: UIImage? = nil
let savedContentOffset:CGPoint? = contentOffset
let savedFrame:CGRect? = frame
contentOffset = .zero
frame = CGRect(x: 0, y: 0,
width: contentSize.width,
height: contentSize.height)
UIGraphicsBeginImageContextWithOptions(
CGSize(width: frame.size.width,
height: frame.size.height),
false,
0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
contentOffset = savedContentOffset ?? contentOffset
frame = savedFrame ?? frame
return image
}
fileprivate func writeImageToAlbum(_ image: UIImage) {
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(image:didFinishSavingWithError:contextInfo:)), nil)
}
@objc fileprivate func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafeRawPointer) {
if let _ = error as NSError? {
print("保存失败,请重试")
} else {
print("保存成功!")
}
}
}
UIView
截图
extension UIView {
/// 截屏Image
func captureImage(size:CGSize)-> UIImage? {
// 参数①:截屏区域 参数②:是否透明 参数③:清晰度
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
func captureImageInPos( rect: CGRect) -> UIImage? {
UIGraphicsBeginImageContext(rect.size)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.translateBy(x: -rect.minX, y: -rect.minY)
self.draw(.zero)
let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return croppedImage
}
}
拼接图片
//拼接图片
func combinTwoImage(image1:UIImage,image2:UIImage) -> UIImage
{
let width = max(image1.size.width, image2.size.width)
let height = image1.size.height + image2.size.height
let offScreenSize = CGSize.init(width: width, height: height)
UIGraphicsBeginImageContextWithOptions(offScreenSize, false, 0.0)
let rect = CGRect.init(x:0, y:0, width:width, height:image1.size.height)
image1.draw(in: rect)
let rect2 = CGRect.init(x:0, y:image1.size.height, width:width, height:image2.size.height)
image2.draw(in: rect2)
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext();
return image;
}
获取当前UIView的UIVIewController
extension UIView{
func ParentCtrl()->UIViewController{
var vc:UIResponder = self
while vc.isKind(of: UIViewController.self) != true {
vc = vc.next!
}
return vc as! UIViewController
}
}
UIImage
重设图片大小和等比例缩放
extension UIImage {
/**
* 重设图片大小
*/
func reSizeImage(reSize: CGSize )-> UIImage {
//UIGraphicsBeginImageContext(reSize);
UIGraphicsBeginImageContextWithOptions (reSize, false , UIScreen .main.scale);
//绘制图片
self.draw(in: CGRect(x: 0,
y: 0,
width: reSize.width,
height: reSize.height))
let reSizeImage: UIImage = UIGraphicsGetImageFromCurrentImageContext ()!
UIGraphicsEndImageContext ();
return reSizeImage;
}
/**
* 等比率缩放
*/
func scaleImage(scaleSize: CGFloat )-> UIImage {
let reSize = CGSize(width: self .size.width * scaleSize, height: self .size.height * scaleSize)
return reSizeImage(reSize: reSize)
}
}
裁切图片
extension UIImage{
func crop(_ rect: CGRect) -> UIImage? {
let img = self.reSizeImage(reSize: UIScreen.main.currentMode!.size)
var newRect = rect
let WIDTH:CGFloat = UIScreen.main.bounds.width
let RELWIDTH = UIScreen.main.currentMode?.size.width
let scale = (RELWIDTH!/WIDTH)
newRect.origin.x *= scale*scale
newRect.origin.y *= scale*scale
newRect.size.width *= scale*scale
newRect.size.height *= scale*scale
guard let imageRef = img.cgImage?.cropping(to: newRect) else { return nil }
return UIImage(cgImage: imageRef)
}
}
获取纯色UIImage
extension UIImage {
convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
color.setFill()
UIRectFill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
guard let cgImage = image?.cgImage else { return nil }
self.init(cgImage: cgImage)
}
}
改变颜色
extension UIImage {
func changeColor(color:UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: 0, y: self.size.height)
context?.scaleBy(x: 1.0, y: -1.0)//kCGBlendModeNormal
context?.setBlendMode(.normal)
let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
context?.clip(to: rect, mask: self.cgImage!);
color.setFill()
context?.fill(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
获取网络图片
func GetImgByUrl(path:String)->UIImage{
let url = NSURL(string: path)!
let data = NSData(contentsOf: url as URL)!
return UIImage(data: data as Data,scale: 1.0)!
}
UIButton
UIButton中图片和文字的位置变换
enum ButtonEdgeInsetsStyle {
case ButtonEdgeInsetsStyleTop // image在上,label在下
case ButtonEdgeInsetsStyleLeft // image在左,label在右
case ButtonEdgeInsetsStyleBottom // image在下,label在上
case ButtonEdgeInsetsStyleRight // image在右,label在左
}
extension UIButton {
func layoutButtonEdgeInsets(style:ButtonEdgeInsetsStyle,space:CGFloat) {
let labelWidth : CGFloat = self.titleLabel?.frame.size.height ?? 36
let labelHeight : CGFloat = self.titleLabel?.frame.size.width ?? 20
var imageEdgeInset = UIEdgeInsets.zero
var labelEdgeInset = UIEdgeInsets.zero
let imageWith = self.imageView?.frame.size.width
let imageHeight = self.imageView?.frame.size.height
switch style {
case .ButtonEdgeInsetsStyleTop:
imageEdgeInset = UIEdgeInsets(top: -labelHeight-space/2.0, left: (bounds.width - imageWith!)/2, bottom: 0, right: 0)
labelEdgeInset = UIEdgeInsets(top: 0, left: -imageWith!, bottom: -imageHeight!-space/2.0, right: 0)
case .ButtonEdgeInsetsStyleLeft:
imageEdgeInset = UIEdgeInsets(top: 0, left: -space/2.0, bottom: 0, right: space/2.0);
labelEdgeInset = UIEdgeInsets(top: 0, left: space/2.0, bottom: 0, right: -space/2.0);
case .ButtonEdgeInsetsStyleBottom:
imageEdgeInset = UIEdgeInsets(top: 0, left: 0, bottom: -labelHeight-space/2.0, right: -labelWidth)
labelEdgeInset = UIEdgeInsets(top: -imageHeight!-space/2.0, left: -imageWith!, bottom: 0, right: 0)
case .ButtonEdgeInsetsStyleRight:
// To Do print("坐标是====\(labelWidth)=====\(space)")
imageEdgeInset = UIEdgeInsets(top: 0, left: labelWidth+space/2.0, bottom: 0, right: -labelWidth-space/2.0)
labelEdgeInset = UIEdgeInsets(top: 0, left: -imageWith!-space/2.0, bottom: 0, right: imageWith!+space/2.0)
}
self.titleEdgeInsets = labelEdgeInset
self.imageEdgeInsets = imageEdgeInset
}
}
UIColor & Color
UIColor 十六进制
extension UIColor{
convenience init(hex: Int, alpha: CGFloat = 1){
let components = (
R: CGFloat((hex >> 16) & 0xff) / 255,
G: CGFloat((hex >> 08) & 0xff) / 255,
B: CGFloat((hex >> 00) & 0xff) / 255
)
self.init(
red: components.R,
green: components.G,
blue: components.B,
alpha: alpha
)
}
}
Color 十六进制
extension Color {
init(hex: Int, alpha: Double = 1) {
let components = (
R: Double((hex >> 16) & 0xff) / 255,
G: Double((hex >> 08) & 0xff) / 255,
B: Double((hex >> 00) & 0xff) / 255
)
self.init(
.sRGB,
red: components.R,
green: components.G,
blue: components.B,
opacity: alpha
)
}
}
CGRect
CGRect等比例缩放
extension CGRect{
init(x:CGFloat,y:CGFloat,w:CGFloat,h:CGFloat,scale:CGFloat){
self.init(x: x*scale, y: y*scale, width: w*scale, height: h*scale)
}
}
点击事件不生效可能的原因
- 部分控件默认用户交互式关闭的,需要手动打开,UIView或父级View的isUserInteractionEnabled为false
view.isUserInteractionEnabled = true
- 当前点击的UIView或区域超出了父级View的范围。
- 当前点击的UIView或区域被其他透明View覆盖
- UITableViewCell里点击事件不生效,使用
cell.contentView.addSubview
代替cell.addSubview
Date
获取农历日期
extension Date{
static var ChineseDate: String{
//设置农历日历
let chinese = Calendar(identifier: .chinese)
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "zh_CN")
formatter.calendar = chinese
//日期样式
formatter.dateStyle = .long
//公历转为农历
let str = formatter.string(from: Date())
return String(str.dropFirst(4))
}
}
当前月有多少天
extension Date{
static var DayCountOfMonth:Int{
let ca = Calendar.init(identifier: .gregorian)
var lastMonthComps = DateComponents()
lastMonthComps.month = 0
let curDate = ca.date(byAdding: lastMonthComps, to: Date())
var interval:Double = 0
var firstDate:Date = Date()
var lastDate :Date = Date()
let calendar = NSCalendar.current
let bl = calendar.dateInterval(of: .month, start: &firstDate, interval: &interval, for: curDate!)
if bl {
lastDate = firstDate.addingTimeInterval(interval-1)
}
let day = Calendar.current.component(.day, from: lastDate);
return day
}
}
今天是今年第几天
extension Date{
static var dayOfYear:Int{
let from = Calendar.current.dateComponents([.year], from: Date())
return (Calendar.current.dateComponents([.day], from: Calendar.current.date(from: from)!,to: Date()).day ?? 0) + 1
}
}
本周是今年第几周
extension Date{
static var weekOfYear:Int{
return Calendar.current.component(.weekOfYear, from: Date())
}
}
String
sha256
extension String {
func sha256() -> String{
if let stringData = self.data(using: String.Encoding.utf8) {
return hexStringFromData(input: digest(input: stringData as NSData))
}
return ""
}
private func hexStringFromData(input: NSData) -> String {
var bytes = [UInt8](repeating: 0, count: input.length)
input.getBytes(&bytes, length: input.length)
var hexString = ""
for byte in bytes {
hexString += String(format:"%02x", UInt8(byte))
}
return hexString
}
private func digest(input : NSData) -> NSData {
let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
var hash = [UInt8](repeating: 0, count: digestLength)
CC_SHA256(input.bytes, UInt32(input.length), &hash)
return NSData(bytes: hash, length: digestLength)
}
}
unicode
extension String {
var unicodeStr:String {
let tempStr1 = self.replacingOccurrences(of: "\\u", with: "\\U")
let tempStr2 = tempStr1.replacingOccurrences(of: "\"", with: "\\\"")
let tempStr3 = "\"".appending(tempStr2).appending("\"")
let tempData = tempStr3.data(using: String.Encoding.utf8)
var returnStr:String = ""
do {
returnStr = try PropertyListSerialization.propertyList(from: tempData!, options: [.mutableContainers], format: nil) as! String
} catch {
print(error)
}
return returnStr.replacingOccurrences(of: "\\r\\n", with: "\n")
}
var unicode:String{
var str = ""
for scalar in self.unicodeScalars {
str = str + "\\u\(String(scalar.value, radix: 16))"
}
return str
}
}
urlEncoded
extension String {
//将原始的url编码为合法的url
func urlEncoded() -> String {
let encodeUrlString = self.addingPercentEncoding(withAllowedCharacters:
.urlQueryAllowed)
return encodeUrlString ?? ""
}
//将编码后的url转换回原始的url
func urlDecoded() -> String {
return self.removingPercentEncoding ?? ""
}
}
Base64
extension String {
//Base64编码
func encodBase64() -> String?{
let strData = self.data(using: String.Encoding.utf8)
let base64String = strData?.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
return base64String
}
//Base64解码
func decodeBase64() -> String?{
let decodedData = NSData(base64Encoded: self, options: NSData.Base64DecodingOptions.init(rawValue: 0))
let decodedString = NSString(data: decodedData! as Data, encoding: String.Encoding.utf8.rawValue) as String?
return decodedString
}
}
Dictionary
合并字典
extension Dictionary {
public func deepMerged(with other: [Key: Value]) -> [Key: Value] {
var result: [Key: Value] = self
for (key, value) in other {
if let value = value as? [Key: Value], let existing = result[key] as? [Key: Value] {
result[key] = (existing.deepMerged(with: value) as! Value)
} else {
result[key] = value
}
}
return result
}
}
Application
手机真实宽高(px)
let RELWIDTH = UIScreen.main.currentMode?.size.width
let RELHEIGHT = UIScreen.main.currentMode?.size.height
设计宽高
let WIDTH:CGFloat = UIScreen.main.bounds.width let HEIGHT:CGFloat = UIScreen.main.bounds.height
手机序列号(唯一标识)
UIDevice.current.identifierForVendor?.uuidString
手机别名:用户定义的名称
UIDevice.current.name
设备名称
UIDevice.current.systemName
手机系统版本
UIDevice.current.systemVersion
手机型号
UIDevice.current.model
地方型号 (国际化区域名称)
UIDevice.current.localizedModel
是否是IPad
UIDevice.current.userInterfaceIdiom == .pad