自從Xcode8以後就不支持插件了,無法用Xcode一鍵生成AppIcon,一直沒找到好的解決方案,一怒之下決定本身寫一個腳本用來生成AppIcon,下面是正文,小弟拋磚引玉,有寫的很差的地方有請大佬們見諒:git
源碼地址github
首先你要肯定你的Mac上的swift版本:shell
swift --version複製代碼
我電腦上的執行結果是這樣的:macos
Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37)
Target: x86_64-apple-macosx10.9複製代碼
而後就能夠用Xcode建一個swift文件來編寫swift腳本了,不過單獨建一個swift文件,Xcode編輯起來很是不友好,個人方案是建一個在Mac上運行的Command Line Tool工程,這樣的話有代碼提示,要否則寫起來太痛苦,若是大佬們有更好的辦法,能夠指導一下小弟。編程
剛入手腳本咱們第一件事前就應該瞭解在終端如何進行輸入和輸出,下面是輸入和輸出的辦法:json
輸入很簡單,你們也很熟悉,就是print
,下面是代碼示例:swift
print("Hello world!")複製代碼
而後你們能夠執行如下試試(test.swift是你的文件名):app
swift test.swift複製代碼
執行後就能在終端上看到一行字:Hello world!框架
這樣子咱們的第一個swift腳本就完成了。ide
知道了怎麼輸出咱們還得知道怎麼輸入,輸入也很是簡單,下面是代碼示例:
print("請輸入文字:")
if let input = readLine() {
print("你輸入的文字:\(input)")
}複製代碼
執行以後顯示的結果:
請輸入文字:
Hello world!
你輸入的文字:Hello world!複製代碼
這樣輸入也完成了,咱們也算swift腳本編程入門了。
咱們常常用的命令有不少,好比echo、mkdir、cd等等,咱們能不能在swift中直接調用呢,答案是能夠的,下面咱們用簡單的例子來了解一下,你們想深刻的話能夠去研究一下傳送門:
import Foundation
func execute(path: String, arguments: [String]? = nil) -> Int {
let process = Process()
process.launchPath = path
if arguments != nil {
process.arguments = arguments!
}
process.launch()
process.waitUntilExit()
return Int(process.terminationStatus)
}
let status = execute(path: "/bin/ls")
print("Status = \(status)")複製代碼
以上的腳本至關於在終端中執行了ls命令,若是你們不知道命令的路徑的話,能夠用where查找一下,例如:
where ls複製代碼
這是執行後的結果:
ls: aliased to ls -G
/bin/ls複製代碼
這裏的/bin/ls就是ls命令的路徑。
首先咱們要從將須要轉化的圖片讀取出來,下面是主要代碼:
import Foundation
let inputPath = "input.png"
let inoutData = try Data(contentsOf: url)
print("圖片大小:\(inoutData.count / 1024) kb")
let dataProvider = CGDataProvider(data: inoutData as CFData)
if let inputImage = CGImage(pngDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent) {
/// inputImage就是須要轉化的圖片
}else {
print("轉換失敗,圖片必須是png格式")
}複製代碼
這裏就設計到文件操做了,用FileManager就好了,相信你們已經輕車熟路了,我就貼一些主要代碼,你們看完整版去個人github源碼看就好了:
import Foundation
/// AppIcon的model
struct AppIconImageItem: Codable {
let size: String
let idiom: String
let filename: String
let scale: String
let role: String?
let subtype: String?
}
struct AppIconInfo: Codable {
let version: Int
let author: String
}
struct AppIcon: Codable {
var images: [AppIconImageItem]
let info: AppIconInfo
}
/// 建立contentsJson
///
/// - Parameter appIcon: 傳入的appIcon
func createAppIconContentsJson(appIcon: AppIcon) {
print("\n開始生成contentsJson\n")
let encoder = JSONEncoder()
do {
encoder.outputFormatting = .prettyPrinted
let appIconData = try encoder.encode(appIcon)
if let appIconStr = String.init(data: appIconData, encoding: .utf8) {
let contentJsonPath = "AppIcon.appiconset/Contents.json"
let contentJsonUrl = URL(fileURLWithPath: contentJsonPath)
try appIconStr.write(to: contentJsonUrl, atomically: true, encoding: .utf8)
print("contentsJson生成成功\n")
}else {
print("contentsJson生成失敗")
}
}catch {
print(error.localizedDescription)
}
}
/// 建立appicon文件
///
/// - Parameter appIcon: appicon
func createFile(appIcon: AppIcon, image: CGImage) {
let fileManager = FileManager.default
let filePath = "AppIcon.appiconset"
do {
if fileManager.fileExists(atPath: filePath) {
try fileManager.removeItem(atPath: filePath)
}
try fileManager.createDirectory(atPath: filePath, withIntermediateDirectories: true, attributes: nil)
createAppIconContentsJson(appIcon: appIcon)
print("~~~~~~~~~~~~~~完成~~~~~~~~~~~~~~")
}catch {
print("文件目錄\(filePath)建立失敗")
print(error.localizedDescription)
}
}複製代碼
生成圖片咱們用的是Foundation框架裏面的Core Graphics框架,下面是主要代碼:
import Foundation
/// 生成單個image
///
/// - Parameters:
/// - size: 圖片的size
/// - scale: 倍數,例如@2x就是2倍
/// - filename: 文件名
func createImage(size: CGSize, scale: CGFloat, image: CGImage, filename: String) {
print("開始生成圖片: \(filename)")
let width = Int(size.width * scale)
let height = Int(size.height * scale)
let bitsPerComponent = image.bitsPerComponent
let bytesPerRow = image.bytesPerRow
let colorSpace = image.colorSpace
if let context = CGContext.init(data: nil,
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bytesPerRow: bytesPerRow,
space: colorSpace!,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) {
context.interpolationQuality = .high
context.draw(image, in: .init(origin: .zero, size: .init(width: width, height: height)))
if let inputImage = context.makeImage() {
let outputImagePath = "AppIcon.appiconset/\(filename)"
let outputUrl = URL(fileURLWithPath: outputImagePath) as CFURL
let destination = CGImageDestinationCreateWithURL(outputUrl, kUTTypePNG, 1, nil)
if let destination = destination {
CGImageDestinationAddImage(destination, inputImage, nil)
if CGImageDestinationFinalize(destination) {
print("圖片: \(filename) 生成成功\n")
}else {
print("圖片: \(filename) 生成失敗\n")
}
}
}else {
print("圖片: \(filename) 生成失敗\n")
}
}
}複製代碼
最後給你們貼如下完成的截圖:
上面只是一部分主要代碼,完整的代碼太多了,你們能夠去個人github地址上去下載執行如下試試,若是有什麼作的很差的地方,歡迎你們指教~~