• 事前准备
    • 查看swift版本
  • swift脚本编程小知识
    • 终端输入和输出
      • 输出
      • 输入
    • 在swift脚本中调用其他命令
  • 开始编写脚本
    • 读取inputpng
    • 生成AppIconappiconset和Contentsjson
    • 生成不同尺寸的image

自从Xcode8之后就不支持插件了,没法用Xcode一键生成AppIcon,一直没找到好的解决方案,一怒之下决定自己写一个脚本用来生成AppIcon,下面是正文,小弟抛砖引玉,有写的不好的地方有请大佬们见谅:

源码地址

事前准备

查看swift版本

首先你要确定你的Mac上的swift版本:

swift --version

我电脑上的执行结果是这样的:

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工程,这样的话有代码提示,要不然写起来太痛苦,如果大佬们有更好的办法,可以指导一下小弟。

swift脚本编程小知识

终端输入和输出

刚入手脚本我们第一件事前就应该了解在终端如何进行输入和输出,下面是输入和输出的办法:

输出

输入很简单,大家也很熟悉,就是print,下面是代码示例:

print("Hello World!")

然后大家可以执行以下试试(test.swift是你的文件名):

swift test.swift

执行后就能在终端上看到一行字:Hello World!

这样子我们的第一个swift脚本就完成了。

输入

知道了怎么输出我们还得知道怎么输入,输入也非常简单,下面是代码示例:

print("请输入文字:")
if let input = readLine() {
    print("你输入的文字:\(input)")
}

执行之后显示的结果:

请输入文字:
Hello world!
你输入的文字:Hello world!

这样输入也完成了,我们也算swift脚本编程入门了。

在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命令的路径。

开始编写脚本

读取input.png

首先我们要从将需要转化的图片读取出来,下面是主要代码:

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格式")
}

生成AppIcon.appiconset和Contents.json

这里就设计到文件操作了,用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)
    }
}

生成不同尺寸的image

生成图片我们用的是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地址上去下载执行以下试试,如果有什么做的不好的地方,欢迎大家指教~~

swift脚本编程:一键生成AppIcon的更多相关文章

  1. 在XCode中,如何为每个目标iOS应用程序使用不同的AppIcon?

    我有一个XCode项目,共有4个不同应用程序的目标,共享大量相同的源代码.我试图让每个人都显示不同的应用程序图标.进入项目>一般>[选择目标]>应用程序图标和启动映像,我看到:但是点击每个AppIcon,我可以得到完全相同的应用程序图标,而不是每个项目的图标.这只是XCode中的一个错误吗?如何为不同的目标使用不同的应用程式图示?

  2. ios – 在XCode 5中使用多个资产目录的问题

    我有一个应用程序有2个变体,只有不同的品牌.对于每个版本,我在资产目录中都有一个AppIcon和LaunchImage.我为每个版本创建了一个不同的目标.在第二个版本中,当我尝试在第二个资产目录中选择AppIcon时,它默认为第一个.删除第一个资产目录似乎解决了它,但我宁愿更少的“黑客”解决方案.解决方法我认为迄今为止我提出的最佳解决方案是重新命名后续资产目录中的资产.例如,您可能有两个资产目录包

  3. swift脚本编程:一键生成AppIcon

    swift脚本编程小知识终端输入和输出刚入手脚本我们第一件事前就应该了解在终端如何进行输入和输出,下面是输入和输出的办法:输出输入很简单,大家也很熟悉,就是print,下面是代码示例:然后大家可以执行以下试试:执行后就能在终端上看到一行字:HelloWorld!这样子我们的第一个swift脚本就完成了。输入知道了怎么输出我们还得知道怎么输入,输入也非常简单,下面是代码示例:执行之后显示的结果:这样输入也完成了,我们也算swift脚本编程入门了。

  4. iOS 11 AppIcon不显示问题小结

    小编在更新xcode9后,在运行老项目时遇到iOS 11 AppIcon不显示问题,下面小编大家分享一下我的思路,需要的朋友参考下吧

  5. ios – 如何为Twitter /行动表制作社交分享例外?

    我使用以下代码在我的应用程序中调用操作表共享:问题是:postText超过140个字符,因此无法通过twitter共享,字符数将是-x,我的问题是:如何我可以做一个例外,以便不同的消息说shortPostText将是选择twitter进行共享时使用的那个吗?

  6. xcassets:针对7.0之前的iOS版本的iPhone应用程序需要XXxXX应用程序图标

    当尝试使用xcassets处理所有图标和图像时,我收到警告,说明我需要57×57,57×57@2x,72×72和72×72@2x图标,因为我的目标是iOS5设备.问题是:>默认的AppIcon组不接受这些图标.>为Icon和Icon-72添加单独的条目也不会修复警告.解决方法通过右键单击并选择编辑器>解决了这个问题.新的App图标.这创建了一个新的AppIcon组,包含iOS6和7图标占位符.问题

  7. cocos2dx工程 配置图标(Icon)和启动图(LaunchImage)的方式

    icon和启动图的设置位置是一样的,下面看看如何设置吧,这里先引用一篇博客,AppIcon,LaunchImagexcode设置还有官方文档给出的步骤。点击左侧的项目名,右边会打开项目设置,“target”选择为XXX-mobile,然后在“General”项下可以看到“AppIconsandLaunchImages”这一项。当然也可以自己定义,在项目配置的“AppIconsandLaunchImages”这一项下,原来的按钮便成了选项框,可以手动选择使用xcassets文件中哪一项来管理图片。官方文档官

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部