Fastlane 小结

Fastlane 可以做什么?

Fastlane 是适用于安卓和iOS的快速打包工具。操作起来也非常简单。

用命令的形式,可以解决程序员时间。同时配合jinkens做到持续集成。

Installing fastlane

xcode-select --install    /这是fastlane的基础,其实就是xcodebuild命令做一些事情。fastlane是对xcode的命令的封装和扩展。

/ Using RubyGems
sudo gem install fastlane -NV

/ Alternatively using Homebrew
brew cask install fastlane

将Fastlane应用到项目

cd your.file.path
fastlane init

/fastlane init swift  
/swift 是beta版本,可以尝鲜

运行命令,会有交互,当有选择方案的时候选择4,手动定制流程。我当前版本1.截屏。2上传test_flight 3.上传app_store。我都不需要。其中第一次init会要求输入apple id和密码。因为需要匹配证书等配置文件。因为开源,所以也不用担心后门。安心输入就好。

跑完命令,查看项目文件多了一个fastlane文件夹里面多了两个文件-w769

打开Fastlane 文件,理解一下这个文件里的内容

default_platform(:ios) /默认的平台

/对相应平台的操作
platform :ios do
  desc "Description of what the lane does"
  lane :custom_lane do  /当我们运行fastlane custom_lane就走的这里面的命令
      /具体的action在这里面操作,可以进行git_pull等操作,下面介绍action的时候回说
  end
end

打一个ad-hoc包,来说Fastlane的action

我们修改Faselane

vim Fastlane

default_platform(:ios)
platform :ios do
  desc "Description of what the lane does"
  lane :adhoc do
    gym(
        clean:true,
        export_method:"ad-hoc",
        scheme:"XXXXX",
        configuration:"Release",
        output_directory:"./app",
        output_name:"hello"
    )
  end
end

保存 运行fastlane adhoc ,不出意外的话,我们会在项目的文件里发现一个app文件夹,里面有一个hello.ipa包,这就是我们需要的。
如果出了意外,说明配置可能出现问题,打开xcode检查有无报错。

理解Fastlane Action

上面这个例子,我们可以了解,faselane中的action是给我们封装好的一些操作。
比如gym就是关于Xcode build的命令。
这些action分为几种

模块简介
Testing测试模块
Buildingbuild模块
Screenshots截屏
Project工程文件
Code Signing代码签名
Documentation文档
Beta测试版本
Push推送证书相关
Releasing your app打包到app_store等
Source Control源码控制
Notifications通知
App Store Connectapple connect相关操作
Misc一些方便的脚本
Deprecated启用的action
Plugins插件,比如fir等脚本插件

我们根据自己的需要来编写自己的lane(脚本)
具体的action使用参考faselane文档)文档地址

可能遇到的问题

/提示 utf-8 error 的时候
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

Jenkins 安装姿势

删除 Jinkens

/Library/Application\ Support/Jenkins/Uninstall.command

使用brew安装的可以
brew uninstall jenkins

如果卸载不完全下面有个链接是说如何卸载完全的
stackoverflow

brew安装jenkins

用dmg格式安装可能会造成命令难以运行的缘故,所以我们现在

brew install jenkins

java -jar /usr/local/Cellar/jenkins/2.122/libexec/jenkins.war --httpPort=8080

去/Library/LaunchDaemons新建一个org.jenkins-ci.plist文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/Apple/DTD PLIST 1.0/EN" "/www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>StandardOutPath</key>
    <string>/var/log/jenkins/jenkins.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/jenkins/jenkins.log</string>
    <key>EnvironmentVariables</key>
    <dict>
      <key>JENKINS_HOME</key>
      <string>/Users/bob/Desktop</string>  /在这里修改JENKINS_HOME
    </dict>
    <key>GroupName</key>
    <string>daemon</string>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>org.jenkins-ci</string>
    <key>ProgramArguments</key>
    <array>
      <string>/bin/bash</string>
      <string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>UserName</key>
    <string>jenkins</string>
    <key>SessionCreate</key>
    <true/>
  </dict>
</plist>

启动Jenkins

/先赋予权限
sudo chown root:wheel /Library/LaunchDaemons/org.jenkins-ci.plist

/加载plist文件
sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

简单的权限控制

1.在插件那边下载Role-based Authorization Strategy

2.在全局安全配置中选择Role-Based strately

3.这时候系统设置里面出现manage and assign Roles,进入

4.进入manage role 编辑 admin权限和测试权限。
admin当然是满权限。新建一个测试group,然后让测试获得基本读取,运行权限。

5 . 进入 Assign Roles
新建并且配置ceshi的用户权限。添加我们需要的测试账户。
应用一下,大功告成。
561-952-5475

Xcode 10 And Swift 4.2 更新内容

Swift 4.2 更新

Cross-module inlining and specialization

跨模块内联和专业化
添加@inlinable @usableFromInline
@usableFromInline属性将内部声明标记为模块的二进制接口的一部分,允许从@inlinable代码中使用它而不将其作为模块源接口的一部分公开。

Derived Collection of Enum Cases

给枚举添加了allCase,获得完整的枚举

Introduce User-defined "Dynamic Member Lookup" Types

添加动态成员变量查找类型,在运行的时候用点语法来获得成员变量

Compiler Diagnostic Directives

在编译的时候添加了#warning 和 #error 来告诉编译器,这代码有问题

func configPath() -> String {
  #warning("this should be made more safe")
  return Bundle.main().path(forResource: "Config", ofType: "plist")!
}

Adding in-place removeAll(where:) to the Standard Library

添加 removeAll(where:) 方法

var x = [1,2,3,4,5,6,2]
x.removeAll { (xx) -> Bool in 
    return xx == 2
}
print(x)
/ output:
/ [1,3,4,5,6]

Adding toggle to Bool

Bool类型加一个切换方法,true to false ,false to true

Package Manager Local Dependencies

在PackageDescription添加了新的Api,支持在依赖声明中用磁盘路径代替git url

Random Unification

统一了Random的获取

/ Utilizes the standard library's default random
/ Alias to:
/ var rng = SystemRandomNumberGenerator()
/ Int.random(in: 0 ..< 10, using: &rng)
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomUIntFrom10Through100 = UInt.random(in: 10 ... 100, using: &myCustomRandomNumberGenerator)

/ The following are examples on how to get full width integers

let randomInt = Int.random(in: .min ... .max)
let randomUInt = UInt.random(in: .min ... .max, using: &myCustomRandomNumberGenerator)

Add last(where:) and lastIndex(where:) Methods

给Sequence添加对末尾item的支持

withUnsafePointer(to:_:) and withUnsafeBytes(of:_:) for immutable values

添加了顶层函数withUnsafePointer(to:_:) 和 withUnsafeBytes(of:_:)

Hashable Enhancements

哈希增强
以前实现Hashable需要手动定义hashValue

struct GridPoint {
  var x: Int
  var y: Int
}

extension GridPoint: Hashable {
  var hashValue: Int {
    return x.hashValue ^ y.hashValue &* 16777619
  }

  static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
    return lhs.x == rhs.x && lhs.y == rhs.y
  }
}

现在不需要了,编译器自动给出hashvalue

struct GridPoint: Hashable {
  var x: Int
  var y: Int
  
  / hashValue and == are automatically synthesized by the compiler
}

Add an allSatisfy algorithm to Sequence

给sequence 协议添加了一个allSatisfy的方法,用来检测一个数组中是否所有的值都等于给定的值

let xArray = [1,1,3,1]
let res = xArray.allSatisfy { (x) -> Bool in 
    print(x)
    return x == 1
}
print(res)
/anwser:
/1
/1
/3
/false

Package Manager System Library Targets

该提议引入了一种新类型的目标“系统库目标”,它将当前系统模块包功能从包级别移动到目标级别。

Package Manager Swift Language Version API Update

更改现有的Package.swift,将swift版本清单Api,从自由的int数组转化成swiftversion枚举数据

import PackageDescription

let package = Package(
    name: "HTTPClient",
    ...
    swiftLanguageVersions: [4]
)

Add an offset(of:) method to MemoryLayout

结构体中的内存偏移api

struct  Point {
   var x,y : Double
}

struct  Size {
   var w,h : Double

  var area : Double { return w * h}
}

struct  Rect {
   var origin : Point
   var size : Size
}

MemoryLayout<Rect>.offset(of: \.origin.x) / => 0
MemoryLayout<Rect>.offset(of: \.origin.y) / => 8
MemoryLayout<Rect>.offset(of: \.size.w) / => 16
MemoryLayout<Rect>.offset(of: \.size.h) / => 24
MemoryLayout<Rect>.offset(of: \.size.area) / => nil

Compiler Version Directive

编译指定swift版本

#if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
/ Code targeting the Swift 4.1 compiler and above.
#endif

Xcode 10 更新

c++.6.0.9消失了

需要重新导入c++库

暗黑模式

Core ML Foundation

361-222-0763

特性是否支持
编译和错误检测支持
源代码控制,build,test,debug等工具集成支持
代码折叠支持
跳转到类的定义,子程序定义,变量的定义支持
跳转到某个类,子程序,变量的全部位置支持
格式编排支持
交互帮助支持
括号匹配支持
常用语言结构模板支持
智能缩进支持
自动化的代码转换或重构支持
宏编程支持
列出常用的字符串无需重新键入支持
在查找和替换时可以使用正则表达式支持
在一组文件中进行查找和替换支持
同时编辑多个文件支持
双列diff支持
多级编辑动作撤销支持

简单的 cmd+ R 这样的快捷键我就不贴了。

代码折叠

全局代码折叠: cmd + option + shift + left/right
单个方法的代码折叠: cmd + option + left/right

跳转到某个类,变量,子程序全部使用位置

cmd + 鼠标左键 点击相应方法 然后弹出菜单中点击 callers

跳转到某个类,方法的定义处

cmd + 鼠标左键 点击相应方法 然后弹出菜单中点击 jump to definition

智能缩进

ctrl + i 可以智能缩进选中代码

自动化代码转换或者重构

我现在编写了几行代码,他们在业务上不可分离,所以我想把他们写成一个方法调用,这时候选中这几行代码,然后鼠标右键refactor,extract method 键入方法名即可

表格中的优秀的IDE所拥有的功能,来自于代码大全一书。

Swift 枚举 小记

在OC中不那么起眼的枚举,在Swift中的表现可谓惊艳。
格式化的东西可以使用枚举达到事半功倍的效果。

比如我们网络回调

enum ResponseError {
    case notFound
    case serverNotResponse
}

enum NetworkResponse {
    case success([AnyHashable:Any])
    case error(ResponseError)
}

let x = NetworkResponse.error(.notFound)

/添加泛型
enum NetworkResponse<T> {
    case success(T)
    case error(ResponseError)
}

迭代枚举

Swift中的枚举,跟代数学非常类似,我们用枚举来写一个二叉搜索树

indirect enum BST<T> {
    case Leaf
    case Node(BST<T>,T,BST<T>)
}

extension BST {
    init() {
        self = .Leaf
    }
    
    init(_ value:T) {
        self = .Node(.Leaf,value,.Leaf)
    }
}

枚举也可以扩展

extension BST where T:Comparable {
    init() {
        self = .Leaf
    }
    
    init(_ value:T) {
        self = .Node(.Leaf,value,.Leaf)
    }
    
    var count:Int {
        switch self {
        case .Leaf:
            return 0
        case let .Node(left,_,right):
            return 1 + left.count + right.count
        }
    }
    
    var isEmpty:Bool {
        if case .Leaf = self {
            return true
        }
        return false
    }
    
    func contains(x:T) -> Bool {
        switch self {
        case .Leaf:
            return falsetr
        case let .Node(_, y, _) where y == x :
            return true
        case let .Node(_, y,right) where x > y:
            return right.contains(x: x)
        case let .Node(left,y,_) where x < y:
            return left.contains(x: x)
        default:
            fatalError()
        }
    }
}

惊奇的发现,原来一整个BST都可以使用枚举来创建,也就是我们的数据结构,都可以用枚举来代替。

这可真函数式!!