你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 給iOS 模擬器“安裝”app文件

給iOS 模擬器“安裝”app文件

編輯:IOS開發基礎

1194012-aa54e17eb79b1ce4.jpeg

前言

剛剛接觸iOS的時候,我就一直很好奇,模擬器上面能不能直接安裝app呢?如果可以,我們就直接在模擬器上面聊QQ和微信了。直到昨天和朋友們聊到了這個話題,沒有想到還真的可以給模擬器“安裝”app!

一.應用場景

先來談談是什麼情況下,會有在模擬器上安裝app的需求。

在一個大公司裡,對源碼的管理有嚴格的制度,非開發人員是沒有權限接觸到源碼的。對蘋果的開發證書管理也非常嚴格,甚至連開發人員也沒有發布證書,證書只在持續集成環境或者Appstore產線裡面,或者只在最後打包上架的人手上。

那麼現在就有這樣的需求,開發人員搭建好UI以後,要把開發完成的Alapha版給到UI設計師那邊去評審,看看是否完全達到要求,達不到要求就需要打回來重做。

一般做法就是直接拿手機去安裝一遍了。直接真機看效果。不過要是設計師和開發不在同一個地方的公司,一個在北京一個在上海,這種就沒法安裝了。源碼又無法導出給設計師,讓他運行一下Xcode跑一下模擬器。打release的ipa通過掃碼安裝,如果公司大了,UDID全部都用完了,也沒法安裝。這個時候就比較麻煩了。(一般也沒人遇到這麼蛋疼的事情吧)

那麼現在就有給模擬器安裝app的需求了,那開發人員如何能把開發版的app給打包出來給其他模擬器安裝呢?

二.解決辦法

解決思路,想要別人的模擬器運行起我們開發的app,最簡單的辦法就是把我們DerivedData的數據直接拷貝到別人模擬器上面,就可以了。當然還要考慮到設計師也許並不會一些命令行命令,我們的操作越傻瓜越好。

1.拷貝本地的DerivedData裡面的debug包

Mac的拷貝命令有cp和ditto,建議用ditto進行拷貝工作。

Usage: ditto [  ] src [ ... src ] dst

     are any of:
    -h                         print full usage
    -v                         print a line of status for each source copied
    -V                         print a line of status for every file copied
    -X                         do not descend into directories with a different device ID

    -c                         create an archive at dst (by default CPIO format)
    -x                         src(s) are archives
    -z                         gzip compress CPIO archive
    -j                         bzip2 compress CPIO archive
    -k                         archives are PKZip
    --keepParent               parent directory name src is embedded in dst_archive
    --arch archVal             fat files will be thinned to archVal
                               multiple -arch options can be specified
                               archVal should be one of "ppc", "i386", etc
    --bom bomFile              only objects present in bomFile are copied
    --norsrc                   don't preserve resource data
    --noextattr                don't preserve extended attributes
    --noqtn                    don't preserve quarantine information
    --noacl                    don't preserve ACLs
    --sequesterRsrc            copy resources via polite directory (PKZip only)
    --nocache                  don't use filesystem cache for reads/writes
    --hfsCompression           compress files at destination if appropriate
    --nopreserveHFSCompression don't preserve HFS+ compression when copying files
    --zlibCompressionLevel num use compression level 'num' when creating a PKZip archive
    --password                 request password for reading from encrypted PKZip archive

Ditto比cp命令更好的地方在於:

  1. 它在復制過程中不僅能保留源文件或者文件夾的屬性與權限,還能保留源文件的資源分支結構和文件夾的源結構。

  2. 此命令能確保文件或者文件夾被如實復制。

  3. 如果目標文件或者文件夾不存在,ditto將直接復制過去或創建新的文件和文件夾,相反,對於已經存在的文件,命令將與目標文件(夾)合並。

  4. ditto還能提供完整符號鏈接。

那麼我們就拷貝出本地的debug包

ditto -ck --sequesterRsrc --keepParent `ls -1 -d -t ~/Library/Developer/Xcode/DerivedData/*/Build/Products/*-iphonesimulator/*.app | head -n 1` /Users/YDZ/Desktop/app.zip

有幾點需要說明的:

  1. 上面命令最後一個路徑(/Users/YDZ/Desktop/app.zip),這個是自定義的,我這裡舉的例子是直接放在桌面。除了這裡改一下路徑,前面的都不需要改,包括 * 也都不用改。

  2. 再來說一下命令裡面的 * 的問題。當我們打開自己本地的~/Library/Developer/Xcode/DerivedData/ ,這個路徑下,會發現裡面裝的都是在我們本地模擬器上運行過的app程序。前面是app的Bundle Identifier,橫線後面是一堆字符串。上面的ditto裡面帶 * 的那個路徑是為了動態匹配一個地址的,* 在這裡也是一個通配符。後面的head說明了匹配的規則。head其實是找出最近一次我們運行模擬器的app的路徑。

為了保證我們打包是正確的,建議先運行一下我們要打包的app,一般我們Scheme裡面的Run都是debug product(如果這裡有更改,那就改成對應debug的Scheme),確保是我們要給設計師審核的app,之後再運行這個ditto命令。

2.把debug包拷貝到另一個模擬器中

我們運行完上面的ditto命令會產生一個zip文件,解壓出來,會得到一個app文件,這個就是debug包了。debug包就是我們要給設計師的app包了。

如何能讓設計師傻瓜式的安裝這個app呢?

這裡介紹一個命令行工具,ios-sim命令行工具。

ios-sim 是一個可以在命令控制iOS模擬器的工具。利用這個命令,我們可以啟動一個模擬器,安裝app,啟動app,查詢iOS SDK。它可以使我們像自動化測試一樣不用打開Xcode。

不過 ios-sim 只支持Xcode 6 以後的版本。

安裝ios-sim

    $ npm install ios-sim -g

說明文檔:

    Usage: ios-sim   [--args ...]    Commands:
      showsdks                        List the available iOS SDK versions
      showdevicetypes                 List the available device types
      launch        Launch the application at the specified path on the iOS Simulator
      start                           Launch iOS Simulator without an app
      install       Install the application at the specified path on the iOS Simulator without launching the app    Options:
      --version                       Print the version of ios-sim
      --help                          Show this help text
      --exit                          Exit after startup
      --log            The path where log of the app running in the Simulator will be redirected to
      --devicetypeid     The id of the device type that should be simulated (Xcode6+). Use 'showdevicetypes' to list devices.
                                      e.g "com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone6, 8.0"

    Removed in version 4.x:
      --stdout      The path where stdout of the simulator will be redirected to (defaults to stdout of ios-sim)
      --stderr      The path where stderr of the simulator will be redirected to (defaults to stderr of ios-sim)
      --sdk               The iOS SDK version to run the application on (defaults to the latest)
      --family         The device type that should be simulated (defaults to `iphone')
      --retina                        Start a retina device
      --tall                          In combination with --retina flag, start the tall version of the retina device (e.g. iPhone 5 (4-inch))
      --64bit                         In combination with --retina flag and the --tall flag, start the 64bit version of the tall retina device (e.g. iPhone 5S (4-inch 64bit))

    Unimplemented in this version:
      --verbose                       Set the output level to verbose
      --timeout              The timeout time to wait for a response from the Simulator. Default value: 30 seconds
      --args <...>                    All following arguments will be passed on to the application
      --env    A plist file containing environment key-value pairs that should be set
      --setenv NAME=VALUE             Set an environment variable

用法不難

ios-sim launch /Users/YDZ/Desktop/app.app --devicetypeid iPhone-6s

其中,/Users/YDZ/Desktop/app.app這個是設計師收到app之後的路徑。--devicetypeid參數後面是給定一個模擬器的版本。

只需要把上面的命令發給設計師,無腦粘貼到命令行,裝好app的模擬器就會自動啟動,打開app了。

三.額外的嘗試

好奇的同學肯定不會滿足只給模擬器安裝debug包吧,既然可以不用代碼就可以給模擬器安裝app,那我們能安裝release包麼?我好奇的嘗試了一下。

先從Appstore上面下載最新的微信,把ipa後綴改成zip,解壓,把Payload文件夾裡面的“WeChat”取出來,然後運行ios-sim命令。

結果微信確實是安裝到了模擬器了。不過一點擊app,看見了月亮界面就退出了。控制台打印了一堆信息。

An error was encountered processing the command (domain=FBSOpenApplicationErrorDomain, code=1):
The operation couldn’t be completed. (FBSOpenApplicationErrorDomain error 1.)
Aug 18 16:29:17 YDZdeMacBook-Pro nsurlsessiond[19213]: Task 1 for client {contents = "com.apple.mobileassetd"} completed with error - code: -999Aug 18 16:29:17 YDZdeMacBook-Pro com.apple.CoreSimulator.SimDevice.D6BD3967-9BC4-4A8D-9AD0-23176B22B12A.launchd_sim[19096] (UIKitApplication:com.tencent.xin[0xdf6d][19774]): Program specified by service does not contain one of the requested architectures:
Aug 18 16:29:17 YDZdeMacBook-Pro SpringBoard[19181]: Unable to get pid for 'UIKitApplication:com.tencent.xin[0xdf6d]': No such process (err 3)
Aug 18 16:29:17 YDZdeMacBook-Pro SpringBoard[19181]: Bootstrapping failed for 
Aug 18 16:29:17 YDZdeMacBook-Pro SpringBoard[19181]: Unable to delete job with label UIKitApplication:com.tencent.xin[0xdf6d]. Error: Operation now in progress
Aug 18 16:29:17 YDZdeMacBook-Pro SpringBoard[19181]: Application 'UIKitApplication:com.tencent.xin[0xdf6d]' exited for an unknown reason.
Aug 18 16:29:17 YDZdeMacBook-Pro com.apple.CoreSimulator.SimDevice.D6BD3967-9BC4-4A8D-9AD0-23176B22B12A.launchd_sim[19096] (UIKitApplication:com.tencent.xin[0xdf6d][19774]): Trampoline was terminated before jumping to service: Killed: 9Aug 18 16:29:18 YDZdeMacBook-Pro fileproviderd[19169]: (Note ) FileProvider: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/FileProvider.framework/Support/fileproviderd starting.
Aug 18 16:29:20 YDZdeMacBook-Pro pkd[19238]: assigning plug-in com.apple.ServerDocuments.ServerFileProvider(1.0) to plugin sandbox
Aug 18 16:29:20 YDZdeMacBook-Pro pkd[19238]: enabling pid=19169 for plug-in com.apple.ServerDocuments.ServerFileProvider(1.0) D12B6280-6DF1-434C-9BAA-BD9B0D0FB756 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/Applications/ServerDocuments.app/PlugIns/ServerFileProvider.appex
Aug 18 16:29:22 YDZdeMacBook-Pro SpringBoard[19181]: Weekly asset update check did fire (force=NO)
Aug 18 16:29:22 YDZdeMacBook-Pro SpringBoard[19181]: Beginning check for asset updates (force: 0Aug 18 16:29:22 YDZdeMacBook-Pro SpringBoard[19181]: Did not complete check for asset updates (force: 0, isVoiceOverRunning: 0Aug 18 16:29:23 YDZdeMacBook-Pro mstreamd[19171]: (Note ) mstreamd: mstreamd starting up.
Aug 18 16:29:23 YDZdeMacBook-Pro DTServiceHub[19191]: DTServiceHub(19191) [error]: 'mach_msg_send' failed: (ipc/send) invalid destination port (268435459)
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: iTunes Store environment is: MR22
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: Normal message received by listener connection. Ignoring.
Aug 18 16:29:25 --- last message repeated 1 time ---
Aug 18 16:29:25 YDZdeMacBook-Pro mstreamd[19171]: (Note ) PS: The subscription plugin class does not support push notification refreshing.
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: libMobileGestalt MGIOKitSupport.c:387: value for udid-version property of IODeviceTree:/product is invalid ((null))
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: Normal message received by listener connection. Ignoring.
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: libMobileGestalt MGBasebandSupport.c:60: _CTServerConnectionCopyMobileEquipmentInfo: CommCenter error: 1:45 (Operation not supported)
Aug 18 16:29:25 YDZdeMacBook-Pro itunesstored[19744]: libMobileGestalt MGBasebandSupport.c:189: No CT mobile equipment info dictionary while fetching kCTMobileEquipmentInfoIMEI
Aug 18 16:29:26 YDZdeMacBook-Pro mstreamd[19171]: (Note ) PS: Media stream daemon starting...
Aug 18 16:29:27 YDZdeMacBook-Pro itunesstored[19744]: UpdateAssetsOperation: Error downloading manifest from URL https://apps.itunes.com/files/ios-music-app/: Error Domain=SSErrorDomain Code=109 "無法連接到 iTunes Store" UserInfo={NSLocalizedDescription=無法連接到 iTunes Store, SSErrorHTTPStatusCodeKey=503}Aug 18 16:29:31 YDZdeMacBook-Pro healthd[19174]: (Error) MC: MobileContainerManager gave us a path we weren't expecting; file a radar against them
           Expected: /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
           Actual: /Users/YDZ/Library/Developer/CoreSimulator/Devices/D6BD3967-9BC4-4A8D-9AD0-23176B22B12A/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
           Overriding MCM with the one true path
Aug 18 16:29:31 YDZdeMacBook-Pro healthd[19174]: PairedSync, Debugging at level 0 for console and level 0 for log files
Aug 18 16:29:31 YDZdeMacBook-Pro healthd[19174]: Error: Could not create service from plist at path: file:///Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PairedSyncServices/com.apple.pairedsync.healthd.plist. Returning nil PSYSyncCoordinator for service name com.apple.pairedsync.healthd.  Please check that your plist exists and is in the correct format.Aug 18 16:29:31 YDZdeMacBook-Pro healthd[19174]: Error: failed to load bundle "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Health/Plugins/CompanionHealth.bundle": Error Domain=NSCocoaErrorDomain Code=4 "未能載入軟件包“CompanionHealth.bundle”,因為未能找到其可執行文件的位置。" UserInfo={NSLocalizedFailureReason=未能找到該軟件包可執行文件的位置。, NSLocalizedRecoverySuggestion=請嘗試重新安裝軟件包。, NSBundlePath=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Health/Plugins/CompanionHealth.bundle, NSLocalizedDescription=未能載入軟件包“CompanionHealth.bundle”,因為未能找到其可執行文件的位置。}
Aug 18 16:29:33 YDZdeMacBook-Pro wcd[19180]: libMobileGestalt MobileGestalt.c:2584: Failed to get battery level
Aug 18 16:29:34 --- last message repeated 1 time ---
Aug 18 16:29:34 YDZdeMacBook-Pro assertiond[19185]: assertion failed: 15G31 13E230: assertiond + 15801 [3C808658-78EC-3950-A264-79A64E0E463B]: 0x1Aug 18 16:29:34 --- last message repeated 1 time ---
Aug 18 16:29:34 YDZdeMacBook-Pro SpringBoard[19181]: [MPUSystemMediaControls] Updating supported commands for now playing application.
Aug 18 16:29:34 YDZdeMacBook-Pro assertiond[19185]: assertion failed: 15G31 13E230: assertiond + 15801 [3C808658-78EC-3950-A264-79A64E0E463B]: 0x1Aug 18 16:29:34 --- last message repeated 1 time ---
Aug 18 16:29:34 YDZdeMacBook-Pro fileproviderd[19169]: plugin com.apple.ServerDocuments.ServerFileProvider invalidated
Aug 18 16:29:34 YDZdeMacBook-Pro ServerFileProvider[19775]: host connection  connection from pid 19169 invalidated
Aug 18 16:30:08 YDZdeMacBook-Pro mstreamd[19171]: (Note ) PS: Media stream daemon stopping.
Aug 18 16:30:09 YDZdeMacBook-Pro mstreamd[19171]: (Note ) AS: : Shared Streams daemon has shut down.
Aug 18 16:30:09 YDZdeMacBook-Pro mstreamd[19171]: (Warn ) mstreamd: mstreamd shutting down.
Aug 18 16:30:09 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:09 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:09 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:09 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:10 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:10 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:10 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:10 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:16 YDZdeMacBook-Pro sharingd[19183]: 16:30:16.190 : Failed to send SDURLSessionProxy startup message, error Error Domain=com.apple.identityservices.error Code=23 "Timed out" UserInfo={NSLocalizedDescription=Timed out, NSUnderlyingError=0x7ff088e005a0 {Error Domain=com.apple.ids.idssenderrordomain Code=12 "(null)"}}
Aug 18 16:30:38 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:38 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:38 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans
Aug 18 16:30:38 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: KEYMAP: Failed to determine iOS keyboard layout for language zh-Hans.
Aug 18 16:30:41 YDZdeMacBook-Pro CoreSimulatorBridge[19190]: Switching to keyboard: zh-Hans

仔細看了一下log,根本原因還是因為

com.apple.CoreSimulator.SimDevice.D6BD3967-9BC4-4A8D-9AD0-23176B22B12A.launchd_sim[19096] (UIKitApplication:com.tencent.xin[0xdf6d][19774]): Program specified by service does not contain one of the requested architectures:

Unable to get pid for 'UIKitApplication:com.tencent.xin[0xdf6d]': No such process (err 3)

因為release包裡面architectures打包的時候不包含模擬器的architectures。debug包裡面就有。所以release就沒法安裝到模擬器了。

由於筆者逆向方面的東西沒有研究,所以也無法繼續下去了。不知道逆向技術能不能把release包破殼之後能不能轉成debug包呢?如果能轉成debug包,通過ios-sim命令應該也是可以直接安裝到模擬器的。

至此,ios-sim給模擬器安裝app就嘗試到此了。因為只能給模擬器安裝debug包,所以在題目上額外給安裝加了雙引號,並不是所有的app文件都可以安裝到模擬器。



  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved