Skip to content
On this page

Swift有用的代码片断

在一些大屏手机设备,比如说iPhone 13 Pro Max这样的设备,NavigationView会像在iPad上以侧边栏展示,如下图所示 land

而这有时候不是我们预期的,我们期望是展示成如下形式

land

可以通过如下代码进行扩展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