Appearance
Swift有用的代码片断
NavigationView 横屏展示问题
在一些大屏手机设备,比如说iPhone 13 Pro Max这样的设备,NavigationView会像在iPad上以侧边栏展示,如下图所示 
而这有时候不是我们预期的,我们期望是展示成如下形式

可以通过如下代码进行扩展View,然后在需要的View中进行调用.phoneOnlyStackNavigationView()即可保证在手机设备上都是以stack的形式进行展示。当然也可以根据自己的需要调整自己的逻辑。
swift
extension View {
//必须要加ViewBuilder,不然要用AnyView包裹
@ViewBuilder func phoneOnlyStackNavigationView() -> some View {
//如果是手机,刚使用stack形式
if UIDevice.current.userInterfaceIdiom == .phone {
self.navigationViewStyle(.stack)
} else {
self
}
}
}
fixedOrientation
图片,因为拍照时握持手机方向不同,记录图片的朝向。在渲染的时候,系统会根据朝向自动调整展示的方向。但对于某些场景,比如我们切割图片的时候,就会产生很多问题。所以我们需要对图片的朝向进行修复.具体的代码如下,逻辑请看备注
swift
extension UIImage {
func fixedOrientation() -> UIImage {
//如果图片本身就是朝上的,直接返回
if imageOrientation == .up{
return self
}
//初始化一个转换器
var transform: CGAffineTransform = CGAffineTransform.identity
switch imageOrientation {
//如果是朝下的,把原点设置为图片的右下角,然后旋转180度
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by:CGFloat(Double.pi))
break
//如果是朝左的,把原点设置为图片左下角(横着的时候宽高是反着的),并且顺时针旋转90度
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat(Double.pi/2))
break
//如果是朝右的,把原点设置为图片右上角(横着的时候宽高是反着的),并且逆时针旋转90度
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat(-Double.pi/2))
break
case .up, .upMirrored:
break
@unknown default:
break
}
//对镜像的情况进行处理
switch imageOrientation {
//对上下镜像,左右翻转
case .upMirrored, .downMirrored:
transform.translatedBy(x: size.width, y: 0)
transform.scaledBy(x: -1, y: 1)
break
//对左右镜像,上下翻转
case .leftMirrored, .rightMirrored:
transform.translatedBy(x: size.height, y: 0)
transform.scaledBy(x: -1, y: 1)
case .up,.down,.left,.right:
break
@unknown default:
break
}
let cgImage = cgImage!
//根据原始图片的信息初始化CGContext
let ctx: CGContext = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: cgImage.bytesPerRow, space: cgImage.colorSpace!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
//连接转换器
ctx.concatenate(transform)
//根据左右还是上下选择宽高
switch imageOrientation {
case .left,.leftMirrored,.right,.rightMirrored:
ctx.draw(cgImage,in:CGRect(x: 0, y: 0, width: size.height, height: size.width))
break
default:
ctx.draw(cgImage,in:CGRect(x: 0, y: 0, width: size.width, height: size.height))
break
}
let cgImageN: CGImage = ctx.makeImage()!
return UIImage(cgImage: cgImageN)
}
}
SF Symbol使用UIImage再渲染模糊及颜色问题
在SwiftUI中,如果直接使用Image(systemName:"xxxx")来初始化,图片无论大小都是非常清晰。因为SF Symbol是矢量图片。但如果先用UIImage(systemName:"xxxxx")来初始化,则有可能会导致渲染的图片非常模糊。
查了一下,UIImage有一个SymbolConfiguration,可以设置点大小,字体字重等。正确设置再渲染就非常清晰了。
swift
let config = UIImage.SymbolConfiguration(pointSize: nodeSize.width, weight: .bold)
var image = UIImage(systemName: "\(puzzle[x+4*y]).square.fill",withConfiguration: config)!
而使用颜色问题,我们扩展一个UIImage,先填充颜色,再用mask clip。即可获取一个上色后的SF Symbol
swift
extension UIImage {
func withColor(_ color: UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return self }
color.setFill()
ctx.translateBy(x: 0, y: size.height)
ctx.scaleBy(x: 1.0, y: -1.0)
ctx.clip(to: CGRect(x: 0, y: 0, width: size.width, height: size.height), mask: cgImage)
ctx.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
guard let colored = UIGraphicsGetImageFromCurrentImageContext() else { return self }
UIGraphicsEndImageContext()
return colored
}
}
Xcode 14 beta
升级到Mac OS 13之后Xcode 13.4.1不能正常运行,需要下载Xcode 14 beta,下载安装完成之后,发现git无法正常使用
需要重新安装CommandLine Tools,删除老的安装目录,然后安装新的即可
sh
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install