├── AD_Demo ├── AD_Demo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── AppIcon-129x29@2x.png │ │ │ ├── AppIcon-129x29@3x.png │ │ │ ├── AppIcon-140x40@2x.png │ │ │ ├── AppIcon-140x40@3x.png │ │ │ ├── AppIcon-160x60@2x.png │ │ │ ├── AppIcon-160x60@3x.png │ │ │ ├── AppIcon-140x40~ipad.png │ │ │ ├── AppIcon-160x60@3x-1.png │ │ │ ├── AppIcon-176x76~ipad.png │ │ │ ├── AppIcon-129x29@2x~ipad.png │ │ │ ├── AppIcon-140x40@2x~ipad.png │ │ │ ├── AppIcon-176x76@2x~ipad.png │ │ │ └── Contents.json │ ├── ViewController.swift │ ├── ViewControllerSecond.swift │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── AppDelegate.swift ├── fastlane │ ├── metadata │ │ ├── AppIcon.png │ │ └── itunes_rating_config.json │ ├── Appfile │ ├── screenshots │ │ ├── zh-Hans │ │ │ ├── iPhone5-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ │ ├── iPhone6-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ │ ├── iPhone5-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ │ ├── iPhone6-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ │ ├── iPhone6Plus-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ │ └── iPhone6Plus-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png │ │ ├── README.txt │ │ └── screenshots.html │ ├── Snapfile │ ├── report.xml │ ├── Fastfile │ ├── README.md │ ├── Deliverfile │ ├── SnapshotHelper.swift │ └── SnapshotHelper2-3.swift ├── AD_Demo.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ └── gyjrong.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── AD_Demo.xcscmblueprint │ ├── xcuserdata │ │ └── gyjrong.xcuserdatad │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── AD_Demo.xcscheme │ └── project.pbxproj └── AD_DemoUITests │ ├── Info.plist │ ├── AD_DemoUITests.swift │ └── SnapshotHelper.swift ├── LICENSE └── README.md /AD_Demo/AD_Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AD_Demo/fastlane/metadata/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/metadata/AppIcon.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@3x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@3x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@2x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40~ipad.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x-1.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-176x76~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-176x76~ipad.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x~ipad.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x~ipad.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-176x76@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/AppIcon-176x76@2x~ipad.png -------------------------------------------------------------------------------- /AD_Demo/fastlane/Appfile: -------------------------------------------------------------------------------- 1 | 2 | # app 的 bundle identifier 3 | app_identifier "com.3code.ADDemo" 4 | 5 | # 你的 Apple email address 6 | apple_id "Apple 邮件地址" 7 | 8 | # 开发的 Team ID 9 | team_id "Team ID" 10 | 11 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone5-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone5-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone6-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone6-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone5-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone5-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone6-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone6-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone6Plus-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone6Plus-01firstPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/zh-Hans/iPhone6Plus-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/fastlane/screenshots/zh-Hans/iPhone6Plus-02secondPage-d41d8cd98f00b204e9800998ecf8427e.png -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/project.xcworkspace/xcuserdata/gyjrong.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mythkiven/AD_Fastlane/HEAD/AD_Demo/AD_Demo.xcodeproj/project.xcworkspace/xcuserdata/gyjrong.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AD_Demo/fastlane/Snapfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 图片尺寸 4 | devices([ 5 | "iPhone 5", 6 | "iPhone 6", 7 | "iPhone 6 Plus" 8 | ]) 9 | 10 | # 语言 11 | languages([ 12 | "zh-Hans" 13 | ]) 14 | 15 | # 储存位置 16 | output_directory "./fastlane/screenshots" 17 | 18 | # 删除以前图片? 19 | clear_previous_screenshots true 20 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/metadata/itunes_rating_config.json: -------------------------------------------------------------------------------- 1 | {"CARTOON_FANTASY_VIOLENCE": 0, 2 | "REALISTIC_VIOLENCE": 0, 3 | "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0, 4 | "PROFANITY_CRUDE_HUMOR": 0, 5 | "MATURE_SUGGESTIVE": 0, 6 | "HORROR": 2, 7 | "MEDICAL_TREATMENT_INFO": 0, 8 | "ALCOHOL_TOBACCO_DRUGS": 0, 9 | "GAMBLING": 0, 10 | "SEXUAL_CONTENT_NUDITY": 0, 11 | "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0, 12 | "UNRESTRICTED_WEB_ACCESS": 0, 13 | "GAMBLING_CONTESTS": 0 14 | } 15 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/README.txt: -------------------------------------------------------------------------------- 1 | Put all screenshots you want to use inside the folder of its language (e.g. en-US). 2 | The device type will automatically be recognized using the image resolution. Apple TV screenshots 3 | should be stored in a subdirectory named appleTV with language folders inside of it. iMessage 4 | screenshots, like Apple TV screenshots, should also be stored in a subdirectory named iMessage 5 | with language folders inside of it. 6 | 7 | The screenshots can be named whatever you want, but keep in mind they are sorted alphabetically. 8 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AD_Demo 4 | // 5 | // https://github.com/mythkiven/AD_Fastlane 6 | 7 | import UIKit 8 | 9 | class ViewController: UIViewController { 10 | 11 | override func viewDidLoad() { 12 | super.viewDidLoad() 13 | // Do any additional setup after loading the view, typically from a nib. 14 | } 15 | 16 | override func viewDidAppear(_ animated: Bool) { 17 | 18 | } 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /AD_Demo/AD_DemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 11 21 | 22 | 23 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/ViewControllerSecond.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerS.swift 3 | // AD_Demo 4 | // 5 | // https://github.com/mythkiven/AD_Fastlane 6 | 7 | 8 | import UIKit 9 | 10 | class ViewControllerSecond: UIViewController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | // Do any additional setup after loading the view, typically from a nib. 15 | } 16 | @IBAction func pop(_ sender: Any) { 17 | self.dismiss(animated: true) { 18 | 19 | } 20 | } 21 | 22 | override func viewDidAppear(_ animated: Bool) { 23 | 24 | } 25 | override func didReceiveMemoryWarning() { 26 | super.didReceiveMemoryWarning() 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/xcuserdata/gyjrong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AD_Demo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D28E87A11E495B7E00EE86E6 16 | 17 | primary 18 | 19 | 20 | D28E87B51E495B7E00EE86E6 21 | 22 | primary 23 | 24 | 25 | D28E87C01E495B7E00EE86E6 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 3行代码 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | fastlane_version "2.14.2" 6 | 7 | default_platform :ios 8 | 9 | platform :ios do 10 | 11 | # 创建证书 12 | desc "Creating a code signing certificate and provisioning profile" 13 | # 14 | lane :provision do 15 | # 16 | produce( 17 | app_name: 'AD_Demo', 18 | language: 'zh-Hans', 19 | app_version: '1.0', 20 | sku: 'com.3code.ADDemo.Test' 21 | ) 22 | # 23 | cert 24 | # 25 | sigh(force: true) 26 | end 27 | 28 | error do |lane, exception| 29 | # This block is called if there was an error running a lane. 30 | end 31 | 32 | # 拍照 33 | desc "Take screenshots" 34 | lane :screenshot do 35 | snapshot 36 | end 37 | 38 | desc "Create ipa" 39 | lane :build do 40 | increment_build_number 41 | gym 42 | end 43 | 44 | 45 | # 提交 46 | desc "Upload to App Store and submit for review" 47 | lane :upload do 48 | deliver( 49 | submit_for_review: true 50 | ) 51 | end 52 | 53 | # 一键搞定 54 | desc "Provision, take screenshots, build and upload to App Store" 55 | lane :do_everything do 56 | provision 57 | screenshot 58 | build 59 | upload 60 | end 61 | 62 | 63 | end 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | zh_CN 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 11 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /AD_Demo/AD_DemoUITests/AD_DemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AD_DemoUITests.swift 3 | // AD_DemoUITests 4 | // 5 | // https://github.com/mythkiven/AD_Fastlane 6 | 7 | import XCTest 8 | 9 | class AD_DemoUITests: XCTestCase { 10 | 11 | // override func setUp() { 12 | // super.setUp() 13 | // 14 | // // Put setup code here. This method is called before the invocation of each test method in the class. 15 | // 16 | // // In UI tests it is usually best to stop immediately when a failure occurs. 17 | // continueAfterFailure = false 18 | // // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 19 | // XCUIApplication().launch() 20 | // 21 | // // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 22 | // } 23 | 24 | // override func tearDown() { 25 | // // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | // super.tearDown() 27 | // } 28 | 29 | func testExample() { 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | 33 | let app = XCUIApplication() 34 | setupSnapshot(app) 35 | app.launch() 36 | 37 | app.buttons["next"].tap() 38 | snapshot("01firstPage") 39 | 40 | app.buttons["back"].tap() 41 | snapshot("02secondPage") 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/project.xcworkspace/xcshareddata/AD_Demo.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "CD74132223D2F2D21B638C19DC987CD1E8B30F5F", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "CD74132223D2F2D21B638C19DC987CD1E8B30F5F" : 9223372036854775807, 8 | "EFFC378D676A8C7D60853A9DC05B16B17EA9AA82" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "8A5E74E6-C8BC-4EF5-9C8F-8C095CF2611A", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "CD74132223D2F2D21B638C19DC987CD1E8B30F5F" : "AD_Fastlane\/", 13 | "EFFC378D676A8C7D60853A9DC05B16B17EA9AA82" : "" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "AD_Demo", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "AD_Demo\/AD_Demo.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/mythkiven\/AD_Fastlane.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CD74132223D2F2D21B638C19DC987CD1E8B30F5F" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/mythkiven\/getFund.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "EFFC378D676A8C7D60853A9DC05B16B17EA9AA82" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | ## Choose your installation method: 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
Homebrew 16 | Installer Script 17 | Rubygems 18 |
macOSmacOSmacOS or Linux with Ruby 2.0.0 or above
brew cask install fastlaneDownload the zip file. Then double click on the install script (or run it in a terminal window).sudo gem install fastlane -NV
30 | # Available Actions 31 | ## iOS 32 | ### ios provision 33 | ``` 34 | fastlane ios provision 35 | ``` 36 | Creating a code signing certificate and provisioning profile 37 | ### ios screenshot 38 | ``` 39 | fastlane ios screenshot 40 | ``` 41 | Take screenshots 42 | ### ios build 43 | ``` 44 | fastlane ios build 45 | ``` 46 | Create ipa 47 | ### ios upload 48 | ``` 49 | fastlane ios upload 50 | ``` 51 | Upload to App Store and submit for review 52 | ### ios do_everything 53 | ``` 54 | fastlane ios do_everything 55 | ``` 56 | Provision, take screenshots, build and upload to App Store 57 | 58 | ---- 59 | 60 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 61 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 62 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 63 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AD_Demo 4 | // 5 | // https://github.com/mythkiven/AD_Fastlane 6 | 7 | import UIKit 8 | 9 | 10 | @UIApplicationMain 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | 18 | // let app = XCUIApplication() 19 | // setupSnapshot(app) 20 | // app.launch() 21 | 22 | return true 23 | } 24 | 25 | func applicationWillResignActive(_ application: UIApplication) { 26 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 27 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 28 | } 29 | 30 | func applicationDidEnterBackground(_ application: UIApplication) { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | func applicationWillEnterForeground(_ application: UIApplication) { 36 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 37 | } 38 | 39 | func applicationDidBecomeActive(_ application: UIApplication) { 40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 41 | } 42 | 43 | func applicationWillTerminate(_ application: UIApplication) { 44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 45 | } 46 | 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "AppIcon-129x29@2x.png", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "AppIcon-129x29@3x.png", 23 | "scale" : "3x" 24 | }, 25 | { 26 | "size" : "40x40", 27 | "idiom" : "iphone", 28 | "filename" : "AppIcon-140x40@2x.png", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "AppIcon-140x40@3x.png", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "size" : "60x60", 39 | "idiom" : "iphone", 40 | "filename" : "AppIcon-160x60@2x.png", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "AppIcon-160x60@3x.png", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ipad", 51 | "size" : "20x20", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "idiom" : "ipad", 56 | "size" : "20x20", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "idiom" : "ipad", 61 | "size" : "29x29", 62 | "scale" : "1x" 63 | }, 64 | { 65 | "size" : "29x29", 66 | "idiom" : "ipad", 67 | "filename" : "AppIcon-129x29@2x~ipad.png", 68 | "scale" : "2x" 69 | }, 70 | { 71 | "size" : "40x40", 72 | "idiom" : "ipad", 73 | "filename" : "AppIcon-140x40~ipad.png", 74 | "scale" : "1x" 75 | }, 76 | { 77 | "size" : "40x40", 78 | "idiom" : "ipad", 79 | "filename" : "AppIcon-140x40@2x~ipad.png", 80 | "scale" : "2x" 81 | }, 82 | { 83 | "size" : "76x76", 84 | "idiom" : "ipad", 85 | "filename" : "AppIcon-176x76~ipad.png", 86 | "scale" : "1x" 87 | }, 88 | { 89 | "size" : "76x76", 90 | "idiom" : "ipad", 91 | "filename" : "AppIcon-176x76@2x~ipad.png", 92 | "scale" : "2x" 93 | }, 94 | { 95 | "size" : "83.5x83.5", 96 | "idiom" : "ipad", 97 | "filename" : "AppIcon-160x60@3x-1.png", 98 | "scale" : "2x" 99 | } 100 | ], 101 | "info" : { 102 | "version" : 1, 103 | "author" : "xcode" 104 | } 105 | } -------------------------------------------------------------------------------- /AD_Demo/fastlane/Deliverfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #######################----by https://github.com/mythkiven-####################### 5 | #######################----by https://github.com/mythkiven-####################### 6 | 7 | # 本文件的设置,可以参考官方文档 8 | # 官方文档:https://github.com/fastlane/fastlane/blob/master/deliver/Deliverfile.md 9 | # 官方文档:https://github.com/fastlane/fastlane/blob/master/spaceship/docs/iTunesConnect.md 10 | 11 | #######################----by https://github.com/mythkiven-####################### 12 | #######################----by https://github.com/mythkiven-####################### 13 | 14 | 15 | ############################# 基本信息 #################################### 16 | 17 | 18 | # 1 app_identifier 19 | app_identifier "com.3code.ADDemo" 20 | 21 | # 2 用户名,Apple ID电子邮件地址 22 | username "Apple ID电子邮件地址" 23 | 24 | 25 | # 3 copyright 26 | copyright "#{Time.now.year} 3code" 27 | 28 | # 4 支持语言 29 | supportedLanguages = { 30 | "cmn-Hans" => "zh-Hans" 31 | } 32 | 33 | # 5 app 名称 34 | name({ 35 | 'zh-Hans' => "ADDemo" 36 | }) 37 | 38 | # 6 本地化 39 | description({ 40 | 'zh-Hans' => "简体中文版" 41 | }) 42 | 43 | 44 | 45 | # AppStore 信息设置 46 | # 也可以使用 txt 文本的形式 47 | 48 | ################################### 类别配置 ################################### 49 | 50 | # 类别列表设置参见 https://github.com/fastlane/fastlane/blob/master/deliver/Reference.md 51 | # 设置 App 的类别.这里可以设置一个主要类别,一个次要类别. 52 | 53 | # 主要类别 54 | primary_category "Games" 55 | 56 | # 主要类别第一个子类别,游戏会有 57 | primary_first_sub_category "Card" 58 | # 主要类别第二个子类别,游戏会有 59 | primary_second_sub_category "Casino" 60 | 61 | # 要设置的次要类别 无 62 | # secondary_category 63 | # 设置的次要第一个子类别 无 64 | # secondary_first_sub_category 65 | # 设置的次要第二个子类别 无 66 | # secondary_second_sub_category 67 | 68 | 69 | 70 | ################################## 关键字\描述等信息 ################################### 71 | 72 | # 1 设置 app 检索关键字 73 | keywords( 74 | "zh-Hans" => "mythkiven,mythkiven2" 75 | ) 76 | 77 | # 2 网址设置 78 | support_url({ 79 | 'zh-Hans' => "https://github.com/mythkiven" 80 | }) 81 | marketing_url({ 82 | 'zh-Hans' => "https://github.com/mythkiven" 83 | }) 84 | privacy_url({ 85 | 'zh-Hans' => "https://github.com/mythkiven" 86 | }) 87 | 88 | # 3 版本描述 89 | release_notes({ 90 | 'zh-Hans' => "这是第一个版本哦" 91 | }) 92 | 93 | # 4 app 描述 94 | description({ 95 | 'zh-Hans' => "这是一个测试 App" 96 | }) 97 | 98 | 99 | 100 | 101 | ################################## 分级 ######################################## 102 | 103 | app_rating_config_path "./fastlane/metadata/itunes_rating_config.json" 104 | 105 | 106 | ################################# 提交信息等 ######################################### 107 | 108 | # 1 提交审核信息:加密, idfa 等 109 | submission_information({ 110 | export_compliance_encryption_updated: false, 111 | export_compliance_uses_encryption: false, 112 | content_rights_contains_third_party_content: false, 113 | add_id_info_uses_idfa: false 114 | }) 115 | 116 | # 2 应用审核小组的联系信息 app 审核信息 117 | app_review_information( 118 | first_name: "myth", 119 | last_name: "kiven", 120 | phone_number: "手机号", 121 | email_address: "mythkiven@qq.com", 122 | demo_user: "测试账号", 123 | demo_password: "测试密码", 124 | notes: "No demo account needed" 125 | ) 126 | 127 | ####################################### 其他信息 ################################### 128 | 129 | # 1 自动发布 app: false,则需要手动发布 130 | automatic_release false 131 | 132 | # 2 价格 133 | price_tier 0 134 | 135 | # 3 图标 136 | app_icon './fastlane/metadata/AppIcon.png' 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/xcuserdata/gyjrong.xcuserdatad/xcschemes/AD_Demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AD_Demo/AD_DemoUITests/SnapshotHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapshotHelper.swift 3 | // Example 4 | // 5 | // Created by Felix Krause on 10/8/15. 6 | // Copyright © 2015 Felix Krause. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | var deviceLanguage = "" 13 | var locale = "" 14 | 15 | @available(*, deprecated, message: "use setupSnapshot: instead") 16 | func setLanguage(_ app: XCUIApplication) { 17 | setupSnapshot(app) 18 | } 19 | 20 | func setupSnapshot(_ app: XCUIApplication) { 21 | Snapshot.setupSnapshot(app) 22 | } 23 | 24 | func snapshot(_ name: String, waitForLoadingIndicator: Bool = true) { 25 | Snapshot.snapshot(name, waitForLoadingIndicator: waitForLoadingIndicator) 26 | } 27 | 28 | open class Snapshot: NSObject { 29 | 30 | open class func setupSnapshot(_ app: XCUIApplication) { 31 | setLanguage(app) 32 | setLocale(app) 33 | setLaunchArguments(app) 34 | } 35 | 36 | class func setLanguage(_ app: XCUIApplication) { 37 | guard let prefix = pathPrefix() else { 38 | return 39 | } 40 | 41 | let path = prefix.appendingPathComponent("language.txt") 42 | 43 | do { 44 | let trimCharacterSet = CharacterSet.whitespacesAndNewlines 45 | deviceLanguage = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue).trimmingCharacters(in: trimCharacterSet) as String 46 | app.launchArguments += ["-AppleLanguages", "(\(deviceLanguage))"] 47 | } catch { 48 | print("Couldn't detect/set language...") 49 | } 50 | } 51 | 52 | class func setLocale(_ app: XCUIApplication) { 53 | guard let prefix = pathPrefix() else { 54 | return 55 | } 56 | 57 | let path = prefix.appendingPathComponent("locale.txt") 58 | 59 | do { 60 | let trimCharacterSet = CharacterSet.whitespacesAndNewlines 61 | locale = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue).trimmingCharacters(in: trimCharacterSet) as String 62 | } catch { 63 | print("Couldn't detect/set locale...") 64 | } 65 | if locale.isEmpty { 66 | locale = Locale(identifier: deviceLanguage).identifier 67 | } 68 | app.launchArguments += ["-AppleLocale", "\"\(locale)\""] 69 | } 70 | 71 | class func setLaunchArguments(_ app: XCUIApplication) { 72 | guard let prefix = pathPrefix() else { 73 | return 74 | } 75 | 76 | let path = prefix.appendingPathComponent("snapshot-launch_arguments.txt") 77 | app.launchArguments += ["-FASTLANE_SNAPSHOT", "YES", "-ui_testing"] 78 | 79 | do { 80 | let launchArguments = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) as String 81 | let regex = try NSRegularExpression(pattern: "(\\\".+?\\\"|\\S+)", options: []) 82 | let matches = regex.matches(in: launchArguments, options: [], range: NSRange(location:0, length:launchArguments.characters.count)) 83 | let results = matches.map { result -> String in 84 | (launchArguments as NSString).substring(with: result.range) 85 | } 86 | app.launchArguments += results 87 | } catch { 88 | print("Couldn't detect/set launch_arguments...") 89 | } 90 | } 91 | 92 | open class func snapshot(_ name: String, waitForLoadingIndicator: Bool = true) { 93 | if waitForLoadingIndicator { 94 | waitForLoadingIndicatorToDisappear() 95 | } 96 | 97 | print("snapshot: \(name)") // more information about this, check out https://github.com/fastlane/fastlane/tree/master/snapshot#how-does-it-work 98 | 99 | sleep(1) // Waiting for the animation to be finished (kind of) 100 | 101 | #if os(tvOS) 102 | XCUIApplication().childrenMatchingType(.Browser).count 103 | #else 104 | XCUIDevice.shared().orientation = .unknown 105 | #endif 106 | } 107 | 108 | class func waitForLoadingIndicatorToDisappear() { 109 | #if os(tvOS) 110 | return 111 | #endif 112 | 113 | let query = XCUIApplication().statusBars.children(matching: .other).element(boundBy: 1).children(matching: .other) 114 | 115 | while (0.. NSString? { 122 | if let path = ProcessInfo().environment["SIMULATOR_HOST_HOME"] as NSString? { 123 | return path.appendingPathComponent("Library/Caches/tools.fastlane") as NSString? 124 | } 125 | print("Couldn't find Snapshot configuration files at ~/Library/Caches/tools.fastlane") 126 | return nil 127 | } 128 | } 129 | 130 | extension XCUIElement { 131 | var isLoadingIndicator: Bool { 132 | return self.frame.size == CGSize(width: 10, height: 20) 133 | } 134 | } 135 | 136 | // Please don't remove the lines below 137 | // They are used to detect outdated configuration files 138 | // SnapshotHelperVersion [1.2] 139 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/SnapshotHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapshotHelper.swift 3 | // Example 4 | // 5 | // Created by Felix Krause on 10/8/15. 6 | // Copyright © 2015 Felix Krause. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | var deviceLanguage = "" 13 | var locale = "" 14 | 15 | @available(*, deprecated, message: "use setupSnapshot: instead") 16 | func setLanguage(_ app: XCUIApplication) { 17 | setupSnapshot(app) 18 | } 19 | 20 | func setupSnapshot(_ app: XCUIApplication) { 21 | Snapshot.setupSnapshot(app) 22 | } 23 | 24 | func snapshot(_ name: String, waitForLoadingIndicator: Bool = true) { 25 | Snapshot.snapshot(name, waitForLoadingIndicator: waitForLoadingIndicator) 26 | } 27 | 28 | open class Snapshot: NSObject { 29 | 30 | open class func setupSnapshot(_ app: XCUIApplication) { 31 | setLanguage(app) 32 | setLocale(app) 33 | setLaunchArguments(app) 34 | } 35 | 36 | class func setLanguage(_ app: XCUIApplication) { 37 | guard let prefix = pathPrefix() else { 38 | return 39 | } 40 | 41 | let path = prefix.appendingPathComponent("language.txt") 42 | 43 | do { 44 | let trimCharacterSet = CharacterSet.whitespacesAndNewlines 45 | deviceLanguage = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue).trimmingCharacters(in: trimCharacterSet) as String 46 | app.launchArguments += ["-AppleLanguages", "(\(deviceLanguage))"] 47 | } catch { 48 | print("Couldn't detect/set language...") 49 | } 50 | } 51 | 52 | class func setLocale(_ app: XCUIApplication) { 53 | guard let prefix = pathPrefix() else { 54 | return 55 | } 56 | 57 | let path = prefix.appendingPathComponent("locale.txt") 58 | 59 | do { 60 | let trimCharacterSet = CharacterSet.whitespacesAndNewlines 61 | locale = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue).trimmingCharacters(in: trimCharacterSet) as String 62 | } catch { 63 | print("Couldn't detect/set locale...") 64 | } 65 | if locale.isEmpty { 66 | locale = Locale(identifier: deviceLanguage).identifier 67 | } 68 | app.launchArguments += ["-AppleLocale", "\"\(locale)\""] 69 | } 70 | 71 | class func setLaunchArguments(_ app: XCUIApplication) { 72 | guard let prefix = pathPrefix() else { 73 | return 74 | } 75 | 76 | let path = prefix.appendingPathComponent("snapshot-launch_arguments.txt") 77 | app.launchArguments += ["-FASTLANE_SNAPSHOT", "YES", "-ui_testing"] 78 | 79 | do { 80 | let launchArguments = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) as String 81 | let regex = try NSRegularExpression(pattern: "(\\\".+?\\\"|\\S+)", options: []) 82 | let matches = regex.matches(in: launchArguments, options: [], range: NSRange(location:0, length:launchArguments.characters.count)) 83 | let results = matches.map { result -> String in 84 | (launchArguments as NSString).substring(with: result.range) 85 | } 86 | app.launchArguments += results 87 | } catch { 88 | print("Couldn't detect/set launch_arguments...") 89 | } 90 | } 91 | 92 | open class func snapshot(_ name: String, waitForLoadingIndicator: Bool = true) { 93 | if waitForLoadingIndicator { 94 | waitForLoadingIndicatorToDisappear() 95 | } 96 | 97 | print("snapshot: \(name)") // more information about this, check out https://github.com/fastlane/fastlane/tree/master/snapshot#how-does-it-work 98 | 99 | sleep(1) // Waiting for the animation to be finished (kind of) 100 | 101 | #if os(tvOS) 102 | XCUIApplication().childrenMatchingType(.Browser).count 103 | #else 104 | XCUIDevice.shared().orientation = .unknown 105 | #endif 106 | } 107 | 108 | class func waitForLoadingIndicatorToDisappear() { 109 | #if os(tvOS) 110 | return 111 | #endif 112 | 113 | let query = XCUIApplication().statusBars.children(matching: .other).element(boundBy: 1).children(matching: .other) 114 | 115 | while (0.. NSString? { 122 | if let path = ProcessInfo().environment["SIMULATOR_HOST_HOME"] as NSString? { 123 | return path.appendingPathComponent("Library/Caches/tools.fastlane") as NSString? 124 | } 125 | print("Couldn't find Snapshot configuration files at ~/Library/Caches/tools.fastlane") 126 | return nil 127 | } 128 | } 129 | 130 | extension XCUIElement { 131 | var isLoadingIndicator: Bool { 132 | let whiteListedLoaders = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"] 133 | if whiteListedLoaders.contains(self.identifier) { 134 | return false 135 | } 136 | return self.frame.size == CGSize(width: 10, height: 20) 137 | } 138 | } 139 | 140 | // Please don't remove the lines below 141 | // They are used to detect outdated configuration files 142 | // SnapshotHelperVersion [1.2] 143 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/SnapshotHelper2-3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapshotHelper.swift 3 | // Example 4 | // 5 | // Created by Felix Krause on 10/8/15. 6 | // Copyright © 2015 Felix Krause. All rights reserved. 7 | // 8 | 9 | // This file should be used if your UI Tests are written in Swift 2.3 10 | 11 | import Foundation 12 | import XCTest 13 | 14 | var deviceLanguage = "" 15 | var locale = "" 16 | 17 | @available(*, deprecated, message="use setupSnapshot: instead") 18 | func setLanguage(app: XCUIApplication) { 19 | setupSnapshot(app) 20 | } 21 | 22 | func setupSnapshot(app: XCUIApplication) { 23 | Snapshot.setupSnapshot(app) 24 | } 25 | 26 | func snapshot(name: String, waitForLoadingIndicator: Bool = true) { 27 | Snapshot.snapshot(name, waitForLoadingIndicator: waitForLoadingIndicator) 28 | } 29 | 30 | public class Snapshot: NSObject { 31 | 32 | public class func setupSnapshot(app: XCUIApplication) { 33 | setLanguage(app) 34 | setLocale(app) 35 | setLaunchArguments(app) 36 | } 37 | 38 | class func setLanguage(app: XCUIApplication) { 39 | guard let prefix = pathPrefix() else { 40 | return 41 | } 42 | 43 | let path = prefix.stringByAppendingPathComponent("language.txt") 44 | 45 | do { 46 | let trimCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet() 47 | deviceLanguage = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding).stringByTrimmingCharactersInSet(trimCharacterSet) as String 48 | app.launchArguments += ["-AppleLanguages", "(\(deviceLanguage))"] 49 | } catch { 50 | print("Couldn't detect/set language...") 51 | } 52 | } 53 | 54 | class func setLocale(app: XCUIApplication) { 55 | guard let prefix = pathPrefix() else { 56 | return 57 | } 58 | 59 | let path = prefix.stringByAppendingPathComponent("locale.txt") 60 | 61 | do { 62 | let trimCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet() 63 | locale = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding).stringByTrimmingCharactersInSet(trimCharacterSet) as String 64 | } catch { 65 | print("Couldn't detect/set locale...") 66 | } 67 | if locale.isEmpty { 68 | locale = NSLocale(localeIdentifier: deviceLanguage).localeIdentifier 69 | } 70 | app.launchArguments += ["-AppleLocale", "\"\(locale)\""] 71 | } 72 | 73 | class func setLaunchArguments(app: XCUIApplication) { 74 | guard let prefix = pathPrefix() else { 75 | return 76 | } 77 | 78 | let path = prefix.stringByAppendingPathComponent("snapshot-launch_arguments.txt") 79 | app.launchArguments += ["-FASTLANE_SNAPSHOT", "YES", "-ui_testing"] 80 | 81 | do { 82 | let launchArguments = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String 83 | let regex = try NSRegularExpression(pattern: "(\\\".+?\\\"|\\S+)", options: []) 84 | let matches = regex.matchesInString(launchArguments, options: [], range: NSRange(location:0, length:launchArguments.characters.count)) 85 | let results = matches.map { result -> String in 86 | (launchArguments as NSString).substringWithRange(result.range) 87 | } 88 | app.launchArguments += results 89 | } catch { 90 | print("Couldn't detect/set launch_arguments...") 91 | } 92 | } 93 | 94 | public class func snapshot(name: String, waitForLoadingIndicator: Bool = true) { 95 | if waitForLoadingIndicator { 96 | waitForLoadingIndicatorToDisappear() 97 | } 98 | 99 | print("snapshot: \(name)") // more information about this, check out https://github.com/fastlane/fastlane/tree/master/snapshot#how-does-it-work 100 | 101 | sleep(1) // Waiting for the animation to be finished (kind of) 102 | 103 | #if os(tvOS) 104 | XCUIApplication().childrenMatchingType(.Browser).count 105 | #else 106 | XCUIDevice.sharedDevice().orientation = .Unknown 107 | #endif 108 | } 109 | 110 | class func waitForLoadingIndicatorToDisappear() { 111 | #if os(tvOS) 112 | return 113 | #endif 114 | 115 | let query = XCUIApplication().statusBars.childrenMatchingType(.Other).elementBoundByIndex(1).childrenMatchingType(.Other) 116 | 117 | while (0.. NSString? { 124 | if let path = NSProcessInfo().environment["SIMULATOR_HOST_HOME"] as NSString? { 125 | return path.stringByAppendingPathComponent("Library/Caches/tools.fastlane") 126 | } 127 | print("Couldn't find Snapshot configuration files at ~/Library/Caches/tools.fastlane") 128 | return nil 129 | } 130 | } 131 | 132 | extension XCUIElement { 133 | var isLoadingIndicator: Bool { 134 | let whiteListedLoaders = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"] 135 | if whiteListedLoaders.contains(self.identifier) { 136 | return false 137 | } 138 | return self.frame.size == CGSize(width: 10, height: 20) 139 | } 140 | } 141 | 142 | // Please don't remove the lines below 143 | // They are used to detect outdated configuration files 144 | // SnapshotHelperVersion [1.2] 145 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /AD_Demo/fastlane/screenshots/screenshots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fastlane/snapshot 5 | 6 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |

en-US

75 |
76 | 77 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 97 | 98 | 99 | 110 | 111 | 112 | 113 | 114 | 117 | 118 | 119 | 120 | 121 | 132 | 133 | 134 | 145 | 146 | 147 | 148 | 149 | 152 | 153 | 154 | 155 | 156 | 167 | 168 | 169 | 180 | 181 | 182 | 183 |
80 | iPhone5 (4-Inch) 81 |
87 | 88 | 89 | 90 | en-US iPhone5 (4-Inch) 95 | 96 | 100 | 101 | 102 | 103 | en-US iPhone5 (4-Inch) 108 | 109 |
115 | iPhone6 (4.7-Inch) 116 |
122 | 123 | 124 | 125 | en-US iPhone6 (4.7-Inch) 130 | 131 | 135 | 136 | 137 | 138 | en-US iPhone6 (4.7-Inch) 143 | 144 |
150 | iPhone6Plus (5.5-Inch) 151 |
157 | 158 | 159 | 160 | en-US iPhone6Plus (5.5-Inch) 165 | 166 | 170 | 171 | 172 | 173 | en-US iPhone6Plus (5.5-Inch) 178 | 179 |
184 | 185 |
186 | 187 |
188 |
189 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Fastlane 入门实战教程 3 | 4 | >有关神器 Fastlane 持续集成\部署的文章网上挺多,本文定位是入门教程,针对 iOS 应用的持续部署,**只需一条命令就可实现从 Xcode 项目到 编译\打包\构建\提交审核** 5 | > 6 | >文章稍微有点长,涵盖内容为:fastlane 简介\安装\配置 + Snapshot 截图 + XCTest + 一键上传App Store 7 | > 8 | >说明:本文将 Apple Dev Center 简称为 ADC; iTunes Connect 简称为 ITC 9 | > 10 | 11 | 先放图看 fastlane 实现自动上传功能: 12 | 13 | 提交进度: 14 | 15 | ![](https://ooo.0o0.ooo/2017/02/08/589a9ef7823dc.png) 16 | 17 | 提交成功,等待审核 18 | ![](https://ooo.0o0.ooo/2017/02/08/589aaed07d991.png) 19 | 20 | 21 | ## Fastlane 简介 22 | 23 | fastlane 是一个完全开源的项目,包含一组 Ruby 实现的工具集,能完成 iOS 和 Android 工程 的自动化构建\测试和发布等功能,[现被Twitter收购,是Fabric的一部分](https://krausefx.com/blog/fastlane-is-now-part-of-fabric).fastlane 强大之处就在于其提供的工具全,基本可以覆盖打包测试发布的所有流程,如下图: 24 | 25 | ![](https://ooo.0o0.ooo/2017/02/08/589ace59a6210.png) 26 | 27 | 28 | fastlane 的每一个工具都对应一个 Ruby 脚本,用来执行某一特定的任务,而最妙的是可以通过配置文件将不同的工具灵活的结合在一起,从而形成一个完整的自动化流程,实现一键上传 ITC,从而缩短用于构建发布的时间. 29 | 30 | 31 | ##### 1.主要使用场: 32 | 33 | - 提交时执行测试(包括单元测试和集成测试) 34 | - 构建并分发内部测试\公开测试版本 35 | - 构建生产版本并上传至 ITC(包括更新配置文件,创建新的屏幕截图,上传应用并提交审核) 36 | - ... 37 | 38 | ##### 2.工具集 39 | 40 | fastlane 将如下的工具套件有机地结合起来,从管理证书到单元测试,从编译打包到上传发布,都能通过命令行轻松完成.该套件支持与 Jenkins 和 CocoaPods,xctools 等其他第三方工具的集成,并且能够定义多个通道(lanes)以支持不同的部署目标. 41 | 42 | - deliver: 将应用在 ITC 上所需数据提交至 ITC (包括:截图,配置文件,ipa包) 43 | - snapshot: 依靠 UI Test 完成截图 44 | - frameit: 快速地把应用截图放入设备框里 45 | - pem: 可以自动化地生成和更新应用推送通知描述文件 46 | - sigh: 创建\更新\下载和修复 provisioning profiles,支持App Store, Ad Hoc, Development和企业profiles 47 | - gym: 编译\打包iOS app,生成签名的ipa文件 48 | - ... 49 | 50 | ##### 3.常见命令 51 | 52 | fastlane 命令中,个人觉得下面两个较为常用: 53 | 54 | - 列出所有的 fastlane 的 actions: 55 | 56 | ``` 57 | $ fastlane actions 58 | ``` 59 | 60 | - fastlane action [action_name]: 显示某一个 action 的详细配置 61 | 62 | ``` 63 | $ fastlane action match 64 | ``` 65 | 66 | 67 | ## fastlane 入门实战 68 | 69 | 70 | ### 1.安装 fastlane 71 | 72 | ##### 1.1 创建App ID\描述文件 73 | 74 | - 本教程目标是上传 ITC ,因此需要提前在 ADC 和 ITC 中创建 App ID\描述文件\App 75 | - 这里使用的项目是 AD Demo,代码见 [GitHub](https://github.com/mythkiven/AD_Fastlane) 76 | 77 | ![](https://ooo.0o0.ooo/2017/02/06/589845eaa299d.png) 78 | ![](https://ooo.0o0.ooo/2017/02/06/589847204b77a.png) 79 | 80 | ##### 1.2 安装 81 | 82 | 查看 Ruby 版本,低于2.0最好升级 83 | 84 | ``` 85 | $ ruby -v 86 | ``` 87 | 88 | 检查 Xcode CLT 是否安装 89 | 90 | ``` 91 | $ xcode-select --install 92 | ``` 93 | 94 | 安装 fastlane 95 | 96 | ``` 97 | $ sudo gem install -n /usr/local/bin fastlane 98 | ``` 99 | 100 | 检查版本 fastlane 101 | 102 | ``` 103 | $ fastlane --version 104 | fastlane installation at path: 105 | /Library/Ruby/Gems/2.0.0/gems/fastlane-2.14.2/bin/fastlane 106 | ----------------------------- 107 | fastlane 2.14.2 108 | ``` 109 | 110 | OK,安装完成 111 | 112 | ##### 1.3 为项目配置 fastlane 113 | 114 | ``` 115 | $ cd 项目目录 116 | $ fastlane init 117 | ``` 118 | 119 | 如果期间报错 `Connection reset by peer - SSL_Connect`,就需要执行: 120 | 121 | ``` 122 | $ brew update && brew install ruby 123 | // 重装 124 | $ sudo gem install -n /usr/local/bin fastlane 125 | ``` 126 | 127 | 然后重新执行 128 | ``` 129 | $ fastlane init 130 | ``` 131 | 132 | - 期间会让你输入 Apple ID 账号密码(这个信息会存在钥匙串中,后续使用无需再输入密码) 133 | - 会检测当前的 app identifier 是否在 ADC 中 134 | - 会检测当前 app 是否在 ITC 中 135 | - 如果已经在 ADC 和 ITC 中创建相应的信息,那么过程会很顺利,如下图: 136 | 137 | ![](https://ooo.0o0.ooo/2017/02/07/58992aea708c6.png) 138 | 139 | 并在 Xcode 项目目录中生成如下文件: 140 | 141 | ![](https://ooo.0o0.ooo/2017/02/07/58992b1016443.png) 142 | 143 | 注意:如果没有在 ITC 中创建 App ,也就不会创建上述两个文件夹;当然也可以后续创建,执行如下操作即可: 144 | 145 | ``` 146 | $ fastlane produce init 147 | ``` 148 | 149 | ### 2.fastlane 文件配置 150 | 151 | fastlane 的各文件解释如下: 152 | 153 | - Appfile:用于存储应用程序标识符和Apple ID 等信息 154 | - Fastfile:配置管理 lane 155 | - Deliverfile:将应用在 ITC 中的信息,统一配置在一个Deliverfile文件中,详见2.1 156 | - metadata:功能同上也是配置应用在ITC中的信息,只不过是独立文本的形式配置的 157 | - screenshots:包含截图数据 158 | 159 | 需要注意的是,metadata 和 Deliverfile,都可以配置 ITC 的数据,但后者优先级高.正如下图: 160 | 161 | ![](https://ooo.0o0.ooo/2017/02/08/589aba7c0b998.png) 162 | 163 | ![](https://ooo.0o0.ooo/2017/02/08/589aba7c1d252.png) 164 | 165 | 下文先在 metadata 文件夹中进行配置用于演示,在文末会删除 metadata 中的配置文本,全部配置在 Deliverfile 中. 166 | 167 | ##### 2.1 配置 metadata 文件夹 168 | 169 | 修改 App 描述: 170 | 171 | ``` 172 | $ cd metadata 173 | $ cd zh-Hans 174 | $ vim description.txt 175 | ``` 176 | 177 | 修改关键字: 178 | 179 | ``` 180 | $ vim keywords.txt 181 | ``` 182 | 183 | 修改 support_url: 184 | 185 | ``` 186 | $ vim support_url.txt 187 | ``` 188 | 189 | 修改 copyright: 190 | 191 | ``` 192 | $ vim copyright.txt 193 | ``` 194 | 195 | 等等,其他信息的修改类似. 196 | 197 | 然后创建分级文件:itunes_rating_config.json 198 | 199 | ``` json 200 | {"CARTOON_FANTASY_VIOLENCE": 0, 201 | "REALISTIC_VIOLENCE": 0, 202 | "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0, 203 | "PROFANITY_CRUDE_HUMOR": 0, 204 | "MATURE_SUGGESTIVE": 0, 205 | "HORROR": 2, 206 | "MEDICAL_TREATMENT_INFO": 0, 207 | "ALCOHOL_TOBACCO_DRUGS": 0, 208 | "GAMBLING": 0, 209 | "SEXUAL_CONTENT_NUDITY": 0, 210 | "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0, 211 | "UNRESTRICTED_WEB_ACCESS": 0, 212 | "GAMBLING_CONTESTS": 0 213 | } 214 | ``` 215 | 216 | 此处配置参见[官方文档](https://github.com/fastlane/fastlane/blob/master/deliver/Reference.md) 217 | 218 | 然后将 App 图标添加至文件夹中,接下来要创建证书: 219 | 220 | ##### 2.2 配置证书 221 | 222 | 修改 Fastfile: 223 | 224 | ``` 225 | $ vim Fastfile 226 | ``` 227 | 228 | 修改内容如下: 229 | 230 | ``` 231 | fastlane_version "2.14.2" 232 | 233 | default_platform :ios 234 | 235 | platform :ios do 236 | 237 | # 当前任务的描述 238 | desc "Creating a code signing certificate and provisioning profile" 239 | # 任务名称 240 | lane :provision do 241 | # 创建 ITC 中的 App 信息 242 | produce( 243 | app_name: 'AD_Demo', 244 | language: 'zh-Hans', 245 | app_version: '1.0', 246 | sku: 'com.3code.ADDemo.Test' 247 | ) 248 | # 使用证书创建私钥及签名 249 | cert 250 | # 每次运行时创建新的配置文件 251 | sigh(force: true) 252 | end 253 | 254 | error do |lane, exception| 255 | 256 | end 257 | 258 | end 259 | ``` 260 | 261 | 如果想创建 ad hoc 配置文件,需要指定sigh(adhoc: true).更多的信息参见: 262 | 263 | - [官方文档](https://github.com/fastlane/fastlane/tree/master/fastlane/docs) 264 | - [fastlane actions](https://docs.fastlane.tools/actions/) 265 | 266 | ##### 2.3 将 fastlane 本地配置上传至 ITC 267 | 268 | 重新进入项目目录,执行如下操作: 269 | 270 | ``` 271 | $ fastlane provision 272 | ``` 273 | 274 | 等待一小会儿,终端提示成功创建证书配置: 275 | 276 | ``` 277 | fastlane.tools finished successfully 🎉 278 | ``` 279 | 280 | 打开 ITC 网页,会发现本地的配置,已经成功上传. 281 | 282 | ### 3.Xcode 配置 283 | 284 | xcode 配置也简单,只需要将项目修改至生产状态即可(描述文件).其它像构建版本号之类的不用理会, fastlane 会处理的. 285 | 286 | ### 4.Snapshot 截图和 XCTest 287 | 288 | snapshot 需要和 XCTest 配合使用,关于 XCTest,我的博客中[有一篇文章](www.3code.info/2017/01/23/AD-XCTest/)做了简单介绍. 289 | 290 | ``` 291 | $ fastlane snapshot init 292 | ``` 293 | 294 | 目录中会生成一个 Snapfile 文件,用于配置截图信息,修改内容如下: 295 | 296 | ``` 297 | # 图片尺寸 298 | devices([ 299 | "iPhone 5", 300 | "iPhone 6", 301 | "iPhone 6 Plus" 302 | ]) 303 | 304 | # 支持语言 305 | languages([ 306 | 'zh-Hans' 307 | ]) 308 | 309 | # 储存位置 310 | output_directory "./fastlane/screenshots" 311 | 312 | # 删除之前图片 313 | clear_previous_screenshots true 314 | ``` 315 | 316 | 然后打开 Xcode 工程,添加截图设置(需要增加 UI Test, 因为截图是在 UI Test 时截取的): 317 | 318 | ``` 319 | \\ 1)在项目添加UI测试,已经添加略过 320 | \\ 2)将./fastlane/SnapshotHelper.swift 添加到UI测试中 321 | \\ 3)打开 AD_DemoUITests.swift ,删除setUp和tearDown方法,然后在其中添加以下代码testExample: 322 | 323 | let app = XCUIApplication() 324 | setupSnapshot(app) 325 | app.launch() 326 | 327 | app.buttons["next"].tap() 328 | snapshot("01firstPage") // 此处截图 329 | 330 | app.buttons["back"].tap() 331 | snapshot("02secondPage") // 此处截图 332 | 333 | ``` 334 | 335 | 打开 Fastfile ,并添加如下信息,用于配置截图 336 | 337 | ``` 338 | desc "Take screenshots" 339 | lane :screenshot do 340 | snapshot 341 | end 342 | ``` 343 | 344 | 执行 `$ fastlane screenshot`, fastlane 会自动调用模拟器,执行测试并生成快照,可能会由于模拟器启动慢而导致时间稍微有点长. 345 | 346 | 成功截图的提示: 347 | 348 | ![](https://ooo.0o0.ooo/2017/02/07/58995745a83cd.png) 349 | 350 | ### 5.创建 IPA 文件 351 | 352 | 打开 fastfile,加入如下代码,配置创建 ipa 353 | 354 | ``` 355 | desc "Create ipa" 356 | lane :build do 357 | increment_build_number 358 | gym 359 | end 360 | ``` 361 | 362 | 保存并执行如下操作,将自动创建 IPA 包 363 | 364 | ``` 365 | $ fastlane build 366 | ``` 367 | 368 | 369 | 如果出现错误: `There does not seem to be a CURRENT_PROJECT_VERSION key set for this project. Add this key to your target's expert build settings.` 370 | [请查阅此处](https://developer.apple.com/library/content/qa/qa1827/_index.html) 371 | 372 | 这是一个自动增加构建版本号的设置,需要手动修改. 373 | 374 | ### 6.上传 IPA 文件到 ITC 375 | 376 | 打开 Fastfile ,添加如下代码: 377 | 378 | ``` 379 | desc "Upload to App Store" 380 | lane :upload do 381 | deliver 382 | end 383 | ``` 384 | 385 | 然后执行命令,上传到 ITC : 386 | 387 | ``` 388 | $ fastlane upload 389 | ``` 390 | 391 | 期间,会创建一个 html 形式的预览文件,确认没问题输入 y; 392 | 393 | 当然最有可能的错误就是网络链接的问题: `Please use diagnostic mode to check connectivity. You need to have outbound access to TCP port 443.` 重新配置代理即可. 394 | 395 | ### 7.配置 Deliverfile 396 | 397 | 其实上传 ITC 最主要的文件是 Deliverfile,配置好 Deliverfile 后,可以删除 metadata 文件夹中的文本配置.最终配置如下图: 398 | 399 | ![](https://ooo.0o0.ooo/2017/02/08/589ac0ac8d172.png) 400 | 401 | 以下是主要的配置,更多更详细的[请戳文件](https://github.com/mythkiven/AD_Fastlane/blob/master/AD_Demo/fastlane/Deliverfile),里面有详细的注释,拿来即可使用 402 | 403 | ``` 404 | 405 | # 1 app_identifier 406 | app_identifier "com.3code.ADDemo" 407 | 408 | # 2 用户名,Apple ID电子邮件地址 409 | username "Apple ID电子邮件地址" 410 | 411 | # 3 支持语言 412 | supportedLanguages = { 413 | "cmn-Hans" => "zh-Hans" 414 | } 415 | 416 | # 4 app 名称 417 | name({ 418 | 'zh-Hans' => "ADDemo" 419 | }) 420 | 421 | # 5 描述 422 | description({ 423 | 'zh-Hans' => "简体中文版" 424 | }) 425 | 426 | # 6 提交审核信息 427 | submission_information({ 428 | export_compliance_encryption_updated: false, 429 | export_compliance_uses_encryption: false, 430 | content_rights_contains_third_party_content: false, 431 | add_id_info_uses_idfa: false 432 | }) 433 | 434 | # 7 应用审核小组的联系信息 app 审核信息 435 | app_review_information( 436 | first_name: "name", 437 | last_name: "name", 438 | phone_number: "手机号", 439 | email_address: "email", 440 | demo_user: "测试账号用户名", 441 | demo_password: "测试账号密码", 442 | notes: "noting" 443 | ) 444 | 445 | # 8 copyright 446 | copyright "#{Time.now.year} 3code" 447 | 448 | # 449 | ``` 450 | 451 | 452 | ### 8.提交 AppStore 审核 453 | 454 | 继续打开 Fastfile,修改如下代码: 455 | 456 | ``` 457 | desc "Upload to App Store and submit for review" 458 | lane :upload do 459 | deliver( 460 | submit_for_review: true 461 | ) 462 | end 463 | ``` 464 | 465 | 然后执行命令,提交审核 : 466 | 467 | ``` 468 | $ fastlane upload 469 | ``` 470 | 471 | 472 | ### 9.使用一键命令 473 | 474 | 添加如下的代码,可以一步搞定所有的操作: 475 | 476 | ``` 477 | desc "Provision, take screenshots, build and upload to App Store" 478 | lane :do_everything do 479 | provision 480 | screenshot 481 | build 482 | upload 483 | end 484 | ``` 485 | 486 | 对应的命令是: 487 | 488 | ``` 489 | $ fastlane do_everything 490 | ``` 491 | 492 | - 代码下载之后是不能直接执行一键上传 ITC ,需要自行在 ADC 配置 App ID\证书\描述文件,ITC 增加 App, 然后方可一键上传 App 493 | 494 | - 本文只是简单的介绍了 fastlane 的使用,更多的资料还请参考文末的链接 495 | 496 | - 如果你对 ITC 不了解,或者很少发布 App ,建议看看官方文档,要知道发布 App 也有[官方指南哦](https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide_SCh/Appendices/Properties.html) 497 | 498 | - 本文是系列文章,后续文章会陆续在这里以及我的[博客](http://3code.info)中发布,喜欢请给个✨吧 499 | 500 | ### 10.参考 501 | 502 | 503 | - [官网](https://fastlane.tools/) 504 | - [github](https://github.com/fastlane/fastlane) 505 | - [文档](https://docs.fastlane.tools/getting-started/ios/setup/) 506 | 507 | 最后给点小建议:如果遇到错误首选就是查 issues,你遇到的问题,基本前人都遇到过了.我能在2天里快速入门 fastlane 全靠看 issues 😁😁 508 | 509 | 510 | 511 | -------------------------------------------------------------------------------- /AD_Demo/AD_Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D28E87A61E495B7E00EE86E6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E87A51E495B7E00EE86E6 /* AppDelegate.swift */; }; 11 | D28E87A81E495B7E00EE86E6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E87A71E495B7E00EE86E6 /* ViewController.swift */; }; 12 | D28E87AB1E495B7E00EE86E6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D28E87A91E495B7E00EE86E6 /* Main.storyboard */; }; 13 | D28E87B01E495B7E00EE86E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D28E87AE1E495B7E00EE86E6 /* LaunchScreen.storyboard */; }; 14 | D28E87C61E495B7E00EE86E6 /* AD_DemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E87C51E495B7E00EE86E6 /* AD_DemoUITests.swift */; }; 15 | D28E87DD1E4971D200EE86E6 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E87DB1E4971D200EE86E6 /* SnapshotHelper.swift */; }; 16 | D28E87E01E49763D00EE86E6 /* ViewControllerSecond.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E87DF1E49763D00EE86E6 /* ViewControllerSecond.swift */; }; 17 | D28E87E21E49957100EE86E6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D28E87E11E49957100EE86E6 /* Assets.xcassets */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | D28E87C21E495B7E00EE86E6 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = D28E879A1E495B7E00EE86E6 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = D28E87A11E495B7E00EE86E6; 26 | remoteInfo = AD_Demo; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | D28E87A21E495B7E00EE86E6 /* AD_Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AD_Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | D28E87A51E495B7E00EE86E6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33 | D28E87A71E495B7E00EE86E6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 34 | D28E87AA1E495B7E00EE86E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 35 | D28E87AF1E495B7E00EE86E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 36 | D28E87B11E495B7E00EE86E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | D28E87C11E495B7E00EE86E6 /* AD_DemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AD_DemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | D28E87C51E495B7E00EE86E6 /* AD_DemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AD_DemoUITests.swift; sourceTree = ""; }; 39 | D28E87C71E495B7E00EE86E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | D28E87DB1E4971D200EE86E6 /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; 41 | D28E87DF1E49763D00EE86E6 /* ViewControllerSecond.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewControllerSecond.swift; sourceTree = ""; }; 42 | D28E87E11E49957100EE86E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | D28E879F1E495B7E00EE86E6 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | D28E87BE1E495B7E00EE86E6 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | D28E87991E495B7E00EE86E6 = { 64 | isa = PBXGroup; 65 | children = ( 66 | D28E87A41E495B7E00EE86E6 /* AD_Demo */, 67 | D28E87C41E495B7E00EE86E6 /* AD_DemoUITests */, 68 | D28E87A31E495B7E00EE86E6 /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | D28E87A31E495B7E00EE86E6 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | D28E87A21E495B7E00EE86E6 /* AD_Demo.app */, 76 | D28E87C11E495B7E00EE86E6 /* AD_DemoUITests.xctest */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | D28E87A41E495B7E00EE86E6 /* AD_Demo */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | D28E87A51E495B7E00EE86E6 /* AppDelegate.swift */, 85 | D28E87A71E495B7E00EE86E6 /* ViewController.swift */, 86 | D28E87DF1E49763D00EE86E6 /* ViewControllerSecond.swift */, 87 | D28E87E11E49957100EE86E6 /* Assets.xcassets */, 88 | D28E87A91E495B7E00EE86E6 /* Main.storyboard */, 89 | D28E87AE1E495B7E00EE86E6 /* LaunchScreen.storyboard */, 90 | D28E87B11E495B7E00EE86E6 /* Info.plist */, 91 | ); 92 | path = AD_Demo; 93 | sourceTree = ""; 94 | }; 95 | D28E87C41E495B7E00EE86E6 /* AD_DemoUITests */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | D28E87DB1E4971D200EE86E6 /* SnapshotHelper.swift */, 99 | D28E87C51E495B7E00EE86E6 /* AD_DemoUITests.swift */, 100 | D28E87C71E495B7E00EE86E6 /* Info.plist */, 101 | ); 102 | path = AD_DemoUITests; 103 | sourceTree = ""; 104 | }; 105 | /* End PBXGroup section */ 106 | 107 | /* Begin PBXNativeTarget section */ 108 | D28E87A11E495B7E00EE86E6 /* AD_Demo */ = { 109 | isa = PBXNativeTarget; 110 | buildConfigurationList = D28E87CA1E495B7E00EE86E6 /* Build configuration list for PBXNativeTarget "AD_Demo" */; 111 | buildPhases = ( 112 | D28E879E1E495B7E00EE86E6 /* Sources */, 113 | D28E879F1E495B7E00EE86E6 /* Frameworks */, 114 | D28E87A01E495B7E00EE86E6 /* Resources */, 115 | ); 116 | buildRules = ( 117 | ); 118 | dependencies = ( 119 | ); 120 | name = AD_Demo; 121 | productName = AD_Demo; 122 | productReference = D28E87A21E495B7E00EE86E6 /* AD_Demo.app */; 123 | productType = "com.apple.product-type.application"; 124 | }; 125 | D28E87C01E495B7E00EE86E6 /* AD_DemoUITests */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = D28E87D01E495B7E00EE86E6 /* Build configuration list for PBXNativeTarget "AD_DemoUITests" */; 128 | buildPhases = ( 129 | D28E87BD1E495B7E00EE86E6 /* Sources */, 130 | D28E87BE1E495B7E00EE86E6 /* Frameworks */, 131 | D28E87BF1E495B7E00EE86E6 /* Resources */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | D28E87C31E495B7E00EE86E6 /* PBXTargetDependency */, 137 | ); 138 | name = AD_DemoUITests; 139 | productName = AD_DemoUITests; 140 | productReference = D28E87C11E495B7E00EE86E6 /* AD_DemoUITests.xctest */; 141 | productType = "com.apple.product-type.bundle.ui-testing"; 142 | }; 143 | /* End PBXNativeTarget section */ 144 | 145 | /* Begin PBXProject section */ 146 | D28E879A1E495B7E00EE86E6 /* Project object */ = { 147 | isa = PBXProject; 148 | attributes = { 149 | LastSwiftUpdateCheck = 0820; 150 | LastUpgradeCheck = 0820; 151 | ORGANIZATIONNAME = mythkiven; 152 | TargetAttributes = { 153 | D28E87A11E495B7E00EE86E6 = { 154 | CreatedOnToolsVersion = 8.2.1; 155 | DevelopmentTeam = 28W82NWSCE; 156 | ProvisioningStyle = Manual; 157 | }; 158 | D28E87C01E495B7E00EE86E6 = { 159 | CreatedOnToolsVersion = 8.2.1; 160 | DevelopmentTeam = 28W82NWSCE; 161 | ProvisioningStyle = Automatic; 162 | TestTargetID = D28E87A11E495B7E00EE86E6; 163 | }; 164 | }; 165 | }; 166 | buildConfigurationList = D28E879D1E495B7E00EE86E6 /* Build configuration list for PBXProject "AD_Demo" */; 167 | compatibilityVersion = "Xcode 3.2"; 168 | developmentRegion = English; 169 | hasScannedForEncodings = 0; 170 | knownRegions = ( 171 | en, 172 | Base, 173 | ); 174 | mainGroup = D28E87991E495B7E00EE86E6; 175 | productRefGroup = D28E87A31E495B7E00EE86E6 /* Products */; 176 | projectDirPath = ""; 177 | projectRoot = ""; 178 | targets = ( 179 | D28E87A11E495B7E00EE86E6 /* AD_Demo */, 180 | D28E87C01E495B7E00EE86E6 /* AD_DemoUITests */, 181 | ); 182 | }; 183 | /* End PBXProject section */ 184 | 185 | /* Begin PBXResourcesBuildPhase section */ 186 | D28E87A01E495B7E00EE86E6 /* Resources */ = { 187 | isa = PBXResourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | D28E87B01E495B7E00EE86E6 /* LaunchScreen.storyboard in Resources */, 191 | D28E87E21E49957100EE86E6 /* Assets.xcassets in Resources */, 192 | D28E87AB1E495B7E00EE86E6 /* Main.storyboard in Resources */, 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | }; 196 | D28E87BF1E495B7E00EE86E6 /* Resources */ = { 197 | isa = PBXResourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | }; 203 | /* End PBXResourcesBuildPhase section */ 204 | 205 | /* Begin PBXSourcesBuildPhase section */ 206 | D28E879E1E495B7E00EE86E6 /* Sources */ = { 207 | isa = PBXSourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | D28E87A81E495B7E00EE86E6 /* ViewController.swift in Sources */, 211 | D28E87E01E49763D00EE86E6 /* ViewControllerSecond.swift in Sources */, 212 | D28E87A61E495B7E00EE86E6 /* AppDelegate.swift in Sources */, 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | D28E87BD1E495B7E00EE86E6 /* Sources */ = { 217 | isa = PBXSourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | D28E87C61E495B7E00EE86E6 /* AD_DemoUITests.swift in Sources */, 221 | D28E87DD1E4971D200EE86E6 /* SnapshotHelper.swift in Sources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | /* End PBXSourcesBuildPhase section */ 226 | 227 | /* Begin PBXTargetDependency section */ 228 | D28E87C31E495B7E00EE86E6 /* PBXTargetDependency */ = { 229 | isa = PBXTargetDependency; 230 | target = D28E87A11E495B7E00EE86E6 /* AD_Demo */; 231 | targetProxy = D28E87C21E495B7E00EE86E6 /* PBXContainerItemProxy */; 232 | }; 233 | /* End PBXTargetDependency section */ 234 | 235 | /* Begin PBXVariantGroup section */ 236 | D28E87A91E495B7E00EE86E6 /* Main.storyboard */ = { 237 | isa = PBXVariantGroup; 238 | children = ( 239 | D28E87AA1E495B7E00EE86E6 /* Base */, 240 | ); 241 | name = Main.storyboard; 242 | sourceTree = ""; 243 | }; 244 | D28E87AE1E495B7E00EE86E6 /* LaunchScreen.storyboard */ = { 245 | isa = PBXVariantGroup; 246 | children = ( 247 | D28E87AF1E495B7E00EE86E6 /* Base */, 248 | ); 249 | name = LaunchScreen.storyboard; 250 | sourceTree = ""; 251 | }; 252 | /* End PBXVariantGroup section */ 253 | 254 | /* Begin XCBuildConfiguration section */ 255 | D28E87C81E495B7E00EE86E6 /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_ANALYZER_NONNULL = YES; 260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 261 | CLANG_CXX_LIBRARY = "libc++"; 262 | CLANG_ENABLE_MODULES = YES; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN_BOOL_CONVERSION = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 267 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 268 | CLANG_WARN_EMPTY_BODY = YES; 269 | CLANG_WARN_ENUM_CONVERSION = YES; 270 | CLANG_WARN_INFINITE_RECURSION = YES; 271 | CLANG_WARN_INT_CONVERSION = YES; 272 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 273 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 277 | COPY_PHASE_STRIP = NO; 278 | DEBUG_INFORMATION_FORMAT = dwarf; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | ENABLE_TESTABILITY = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu99; 282 | GCC_DYNAMIC_NO_PIC = NO; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_OPTIMIZATION_LEVEL = 0; 285 | GCC_PREPROCESSOR_DEFINITIONS = ( 286 | "DEBUG=1", 287 | "$(inherited)", 288 | ); 289 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 290 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 291 | GCC_WARN_UNDECLARED_SELECTOR = YES; 292 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 293 | GCC_WARN_UNUSED_FUNCTION = YES; 294 | GCC_WARN_UNUSED_VARIABLE = YES; 295 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 296 | MTL_ENABLE_DEBUG_INFO = YES; 297 | ONLY_ACTIVE_ARCH = YES; 298 | SDKROOT = iphoneos; 299 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 300 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 301 | TARGETED_DEVICE_FAMILY = "1,2"; 302 | }; 303 | name = Debug; 304 | }; 305 | D28E87C91E495B7E00EE86E6 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BOOL_CONVERSION = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 318 | CLANG_WARN_EMPTY_BODY = YES; 319 | CLANG_WARN_ENUM_CONVERSION = YES; 320 | CLANG_WARN_INFINITE_RECURSION = YES; 321 | CLANG_WARN_INT_CONVERSION = YES; 322 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 323 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 324 | CLANG_WARN_UNREACHABLE_CODE = YES; 325 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 326 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 327 | COPY_PHASE_STRIP = NO; 328 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 329 | ENABLE_NS_ASSERTIONS = NO; 330 | ENABLE_STRICT_OBJC_MSGSEND = YES; 331 | GCC_C_LANGUAGE_STANDARD = gnu99; 332 | GCC_NO_COMMON_BLOCKS = YES; 333 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 334 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 335 | GCC_WARN_UNDECLARED_SELECTOR = YES; 336 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 337 | GCC_WARN_UNUSED_FUNCTION = YES; 338 | GCC_WARN_UNUSED_VARIABLE = YES; 339 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 340 | MTL_ENABLE_DEBUG_INFO = NO; 341 | SDKROOT = iphoneos; 342 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 343 | TARGETED_DEVICE_FAMILY = "1,2"; 344 | VALIDATE_PRODUCT = YES; 345 | }; 346 | name = Release; 347 | }; 348 | D28E87CB1E495B7E00EE86E6 /* Debug */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 352 | CODE_SIGN_IDENTITY = "iPhone Distribution: Shanghai TanNuo Information Technology Co., Ltd. (28W82NWSCE)"; 353 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Shanghai TanNuo Information Technology Co., Ltd. (28W82NWSCE)"; 354 | CURRENT_PROJECT_VERSION = 11; 355 | DEVELOPMENT_TEAM = 28W82NWSCE; 356 | INFOPLIST_FILE = AD_Demo/Info.plist; 357 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 358 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 359 | PRODUCT_BUNDLE_IDENTIFIER = com.3code.ADDemo; 360 | PRODUCT_NAME = "$(TARGET_NAME)"; 361 | PROVISIONING_PROFILE = "f0e98cae-f4d5-4b47-8dee-84c52f1f9d1f"; 362 | PROVISIONING_PROFILE_SPECIFIER = "com.3code.ADDemo AppStore"; 363 | SWIFT_VERSION = 3.0; 364 | TARGETED_DEVICE_FAMILY = 1; 365 | VERSIONING_SYSTEM = "apple-generic"; 366 | }; 367 | name = Debug; 368 | }; 369 | D28E87CC1E495B7E00EE86E6 /* Release */ = { 370 | isa = XCBuildConfiguration; 371 | buildSettings = { 372 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 373 | CODE_SIGN_IDENTITY = "iPhone Distribution: Shanghai TanNuo Information Technology Co., Ltd. (28W82NWSCE)"; 374 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Shanghai TanNuo Information Technology Co., Ltd. (28W82NWSCE)"; 375 | CURRENT_PROJECT_VERSION = 11; 376 | DEVELOPMENT_TEAM = 28W82NWSCE; 377 | INFOPLIST_FILE = AD_Demo/Info.plist; 378 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 379 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 380 | PRODUCT_BUNDLE_IDENTIFIER = com.3code.ADDemo; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | PROVISIONING_PROFILE = "f0e98cae-f4d5-4b47-8dee-84c52f1f9d1f"; 383 | PROVISIONING_PROFILE_SPECIFIER = "com.3code.ADDemo AppStore"; 384 | SWIFT_VERSION = 3.0; 385 | TARGETED_DEVICE_FAMILY = 1; 386 | VERSIONING_SYSTEM = "apple-generic"; 387 | }; 388 | name = Release; 389 | }; 390 | D28E87D11E495B7E00EE86E6 /* Debug */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 394 | DEVELOPMENT_TEAM = 28W82NWSCE; 395 | INFOPLIST_FILE = AD_DemoUITests/Info.plist; 396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 397 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.mythkiven.AD-DemoUITests"; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | SWIFT_VERSION = 3.0; 400 | TEST_TARGET_NAME = AD_Demo; 401 | }; 402 | name = Debug; 403 | }; 404 | D28E87D21E495B7E00EE86E6 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 408 | DEVELOPMENT_TEAM = 28W82NWSCE; 409 | INFOPLIST_FILE = AD_DemoUITests/Info.plist; 410 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 411 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.mythkiven.AD-DemoUITests"; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | SWIFT_VERSION = 3.0; 414 | TEST_TARGET_NAME = AD_Demo; 415 | }; 416 | name = Release; 417 | }; 418 | /* End XCBuildConfiguration section */ 419 | 420 | /* Begin XCConfigurationList section */ 421 | D28E879D1E495B7E00EE86E6 /* Build configuration list for PBXProject "AD_Demo" */ = { 422 | isa = XCConfigurationList; 423 | buildConfigurations = ( 424 | D28E87C81E495B7E00EE86E6 /* Debug */, 425 | D28E87C91E495B7E00EE86E6 /* Release */, 426 | ); 427 | defaultConfigurationIsVisible = 0; 428 | defaultConfigurationName = Release; 429 | }; 430 | D28E87CA1E495B7E00EE86E6 /* Build configuration list for PBXNativeTarget "AD_Demo" */ = { 431 | isa = XCConfigurationList; 432 | buildConfigurations = ( 433 | D28E87CB1E495B7E00EE86E6 /* Debug */, 434 | D28E87CC1E495B7E00EE86E6 /* Release */, 435 | ); 436 | defaultConfigurationIsVisible = 0; 437 | defaultConfigurationName = Release; 438 | }; 439 | D28E87D01E495B7E00EE86E6 /* Build configuration list for PBXNativeTarget "AD_DemoUITests" */ = { 440 | isa = XCConfigurationList; 441 | buildConfigurations = ( 442 | D28E87D11E495B7E00EE86E6 /* Debug */, 443 | D28E87D21E495B7E00EE86E6 /* Release */, 444 | ); 445 | defaultConfigurationIsVisible = 0; 446 | defaultConfigurationName = Release; 447 | }; 448 | /* End XCConfigurationList section */ 449 | }; 450 | rootObject = D28E879A1E495B7E00EE86E6 /* Project object */; 451 | } 452 | --------------------------------------------------------------------------------