最全CocoaPods使用教程

喬明發表於2018-08-23

CocoaPods 常⽤用法

1.下載升級 CocoaPods 。

sudo gem install cocoapods
複製程式碼

檢視當前 cocoapods 版本

pod --version
複製程式碼

升級 cocoapods

sudo gem install -n /usr/local/bin cocoapods --pre
複製程式碼

檢視當前 gem 源

gem sources -l
複製程式碼

刪除 gem 源 ruby.taobao.org/

gem sources --remove https://ruby.taobao.org/
複製程式碼

修改 gem 源為 gems.ruby-china.org

gem sources -a https://gems.ruby-china.org

/usr/local/bin : gem 安裝路路徑。
複製程式碼

2.使⽤用 CocoaPods 。

初始化 Podfile

pod init
複製程式碼

搜尋庫 AFNetworking

pod search AFNetworking
複製程式碼

根據 Podfile,安裝 pod,建立 workspace

pod install
複製程式碼

根據 Podfile,更更新安裝

pod update
複製程式碼

更更新索引庫。存放 spec ⽂檔案的倉庫。

pod repo udpate
複製程式碼

列出本地所有 spec 倉庫

pod repo list
複製程式碼

3.配置 CocoaPods 的 Podfile 。

指定本地下載源

pod 'MCFramwork', :path => '../'
複製程式碼

指定庫 git 源

pod 'AFNetworking', :git => 'https://github.com/AFNetworking/AFNetworking.git'
複製程式碼

指定索引庫

pod 'AFNetworking', :source => 'https://github.com/CocoaPods/Specs.git'
複製程式碼

指定索引庫

source 'https://github.com/CocoaPods/Specs.git'

source 'https://github.com/Artsy/Specs.git'
複製程式碼

4.CocoaPods 常⽤用路路徑。

~/.cocoapods :本地 spec 庫(索引庫)。 

( ~/.cocoapods/repos/master 是 origin https://github.com/CocoaPods/Specs.git )

~/Library/Caches/CocoaPods :本地庫快取。
複製程式碼

CocoaPods 私有庫

1.CocoaPods 私有庫建立

需要建立的倉庫分為兩個: spec repository 和 code repository (這⾥裡裡建立的 倉庫都是 git 倉庫)。

spec repository 是索引庫(配置倉庫),這個倉庫只⽤用來存放 spec ⽂檔案,不不 存放程式碼。 spec ⽂檔案是按照版本存放,每⼀一個 spec ⽂檔案對應⼀一個版本的程式碼。 版本號就是程式碼庫的 tag 號。每⼀一個 spec ⽂檔案包含對應版本程式碼庫的資訊(包 括:倉庫名、程式碼庫的遠端地址、版本號、依賴庫、庫⽂檔案等等)。 repos 下⾯面⽂文 件⽬目錄: repos/<repos_name>/<sdk_name>/<version_num>/<name.podspec> 。

code repository 是程式碼倉庫,把包程式碼或包⼆二進位制⽂檔案上傳到這個倉庫。

~/.cocoapods 索引庫存放在本地的⽬目錄。 ~/.cocoapods/repos/master 的 origin 是 github.com/CocoaPods/S… ,就是 CocoaPods 官⽅方 的索引庫。

執⾏行行 pod setup 時,會從 github 上拉取 master 源。

執⾏行行 pod install 時,會把 Podfile 中所有的私有庫索引源對應的索引庫
拉取下來。

執⾏行行 pod update 時,會更更新本地所有的索引庫。

執⾏行行 pod repo udpate 時,更更新本地所有索引庫。
複製程式碼

建立私有庫:

在 git 遠端建立索引倉庫。

在 git 遠端建立程式碼倉庫。所有程式碼倉庫共⽤用⼀一個索引庫。

clone 程式碼庫到本地,建立⼯工程。⼀一般包含: LICENSE (開源許可 證)、 README.md 、 name.podspec (CocoaPods 的索引描述⽂檔案)、代 碼(程式碼 & ⼆二進位制⽂檔案 & 資源⽂檔案)、 Example (Demo⼯工程)。
複製程式碼

第⼀一次搜尋庫的時候或者刪除電腦快取,會出現:

pod search AFN
Creating search index for spec repo 'master'..
複製程式碼

是在建立 search_index.json ⽂檔案。所以 pod search 搜尋是通過⼀一個 search_index.json 快取⽂檔案搜尋的,這個快取⽂檔案路路徑是 ~/Library/Caches/CocoaPods/search_index.json 。

  1. spec ⽂檔案

建立 spec ⽂檔案。

建立 spec ⽂檔案,名字為 spec_name

pod spec create spec_name
複製程式碼

spec ⽂檔案欄位含義。

Pod::Spec.new do |s|
s.name = 'MYFramwork' # 項⽬目名稱
s.version = '1.0.0' # 版本號 與 你倉庫的 標籤號 對應 
s.license = 'MIT' # 開源證書
s.summary = '項⽬目簡介'
s.homepage = '程式碼倉庫地址'
s.author ={"MC"=>"作者郵箱"}
s.social_media_url = "個⼈人主⻚頁地址"
# 倉庫地址,不不能⽤用 SSH 地址
s.source = { :git => '程式碼倉庫地址', ::tag => '#{s.version}' } '#{s.version}' } 
s.requires_arc = true # 是否啟⽤用 ARC
s.platform = :ios, '8.0' # 平臺及⽀支援的最低版本
# 程式碼的位置, MCLib/*.{h,m} 表示 MCLib ⽂資料夾下所有的 .h 和 .m ⽂檔案 
s.source_files = "MCLib/*.{h,m}"
# s.resource = "pod/classes/TestViewController.xib" s.resources = ['*.bundle', '*.strings', '*.xib']
# ⽀支援的框架
s.frameworks = 'UIKit', 'Foundation'
# 依賴庫
s.dependency = 'AFNetworking' 
s.dependency 'SDWebImage'
# 配置 Xcode Build Setting s.xcconfig = {
  'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/',
# 配置 Header 搜尋 # 配置 Framwork
'FRAMEWORK_SEARCH_PATHS' => '$(PODS_ROOT)/', 搜尋路路徑
'GCC_PREPROCESSOR_DEFINITIONS' => 'RELEASE COCOAPODS=1' # 配置預 編譯巨集
}
# 配置 pch
s.prefix_header_file = 'MCLib/MCLib.pch'
end
複製程式碼

可以把建立好的 spec ⽂檔案新增到本地索引庫中。

# 新增 spec 到本地指定的索引庫。
# pod repo add [Private Repo Name 本地私有庫名字] [GitHub HTTPS clone URL 私有庫遠端地址]
pod repo add MCRepoLib https://gitee.com/mengcoder/MCSpeclib.git
複製程式碼
  1. push 私有庫索引

推送私有庫索引到私有索引倉庫。⼀一般推送之前會進⾏行行驗證,驗證通過之後,再推送。

驗證:

# 驗證
pod lib lint
pod lib lint --verbose --use-libraries --allow-warnings -- sources='私有倉庫repo地址,https://github.com/CocoaPods/Specs'
pod spec lint
pod spec lint --verbose --use-libraries --allow-warnings -- sources='私有倉庫repo地址,https://github.com/CocoaPods/Specs'
複製程式碼

CocoaPods 強制要求所有的 Pods 依賴庫都必須有 license ⽂檔案,否則驗證不不會 通過。

推送:

# 先驗證 .podspec ⽂檔案,驗證通過,再把 .podspec ⽂檔案推送到 spec 源。
# push 到遠端倉庫
# pod repo push 本地repo名 本地podspec名
pod repo push MCLib MCAppKit.podspec --verbose --use-libraries -- allow-warnings
# spec ⽂檔案轉換成 .json
pod ipc spec <filename.podspec>
複製程式碼

常⻅見問題

  1. 安裝 Podfile

     [!] Unable to find a specification for MCLib
    複製程式碼

    本地沒有 MCLib 的索引 spec 。更更新 MCLib 對應的本地 repos ,本地 repos 倉庫快取⽬目錄: ~/.cocoapods/repos/ 。

     更更新本地 repo pod repo udpate
     [!] Unable to find a specification for FMDB depended upon by MCLib
     # podfile 在私有庫後⾯面配置了了 source ,導致私有庫 QMAppUIKit 依賴的庫 QMAppFoundation(QMAppFoundation依賴FMDB) 在設定的source中找不不到 FMDB。
     pod 'QMAppUIKit' , '0.0.1' , :source => 'git@10.2.250.21:QMApp/specRepo_iOS.git' 
     # QMAppUIKit
    複製程式碼
  2. 推送 spec ⽂檔案

     # CocoaPods 私有庫,靜態 Framework 驗證失敗: The following build commands failed:
       CompileC
       /Users/mengyueping/Library/Developer/Xcode/DerivedData/App-
       fbdglhmiocesdxeuqlwfuuhbmtht/Build/Intermediates.noindex/Pods.build
       /Release-iphonesimulator/MCLib.build/Objects-
       normal/i386/openssl_wrapper.o
       MCLib/MCLib/Lib/Util/openssl_wrapper.m normal i386 objective-c
       com.apple.compilers.llvm.clang.1_0.compiler
           (1 failure)
          Testing with `xcodebuild`.
        -> MCLib (0.0.1)
           - ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code.
    複製程式碼

指定私有庫的源,驗證 .podspec ⽂檔案時,出現私有庫找不不到。

推送 spec 到 Cocoapods 官⽅方庫

開源 Pod 庫,要註冊⼀一個 CocoaPods 賬號。使⽤用終端註冊。

pod trunk register 447497298@qq.com 'qiaoming' --verbose
opening connection to trunk.cocoapods.org:443... opened
starting SSL for trunk.cocoapods.org:443...
SSL established
  <- "POST /api/v1/sessions HTTP/1.1\r\nContent-Type:
  application/json; charset=utf-8\r\nAccept: application/json;
  charset=utf-8\r\nUser-Agent: CocoaPods/1.3.1\r\nAccept-Encoding:
  gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nHost:
  trunk.cocoapods.org\r\nContent-Length: 67\r\n\r\n"
  <- "
  {\"email\":\"1134471523@qq.com\",\"name\":\"CoderMeng\",\"descripti
  on\":null}"
  -> "HTTP/1.1 201 Created\r\n"
  -> "Date: Thu, 03 May 2018 03:03:11 GMT\r\n"
  -> "Connection: keep-alive\r\n"
  -> "Strict-Transport-Security: max-age=31536000\r\n"
  -> "Content-Type: application/json\r\n"
  -> "Content-Length: 193\r\n"
  -> "X-Content-Type-Options: nosniff\r\n"
  -> "Server: thin 1.6.2 codename Doc Brown\r\n"
  -> "Via: 1.1 vegur\r\n"
  -> "\r\n"
  reading 193 bytes...
  -> "{\"created_at\":\"2018-05-03 03:03:11
  UTC\",\"valid_until\":\"2018-09-08 03:03:11
  UTC\",\"verified\":false,\"created_from_ip\":\"210.12.48.132\",\"de
  scription\":null,\"token\":\"682a8eca7a76ff7e1b1b8334b6d566f6\"}"
  read 193 bytes
  Conn keep-alive
[!] Please verify the session by clicking the link in the verification email that has been sent to 1134471523@qq.com
# 看到上⾯面提示,去郵箱驗證確認。
# pod trunk register < you_email > 'user_name' --verbose

 # 終端確認 pod trunk me
  - Name:qiaoming
  - Email:447497298@qq.com
  - Since:
  - Pods:
  - Sessions:
  - May 2nd, 21:03 - September 7th, 21:26. IP: 210.12.48.132
複製程式碼

Cocoapods 使⽤用 pod trunk 釋出程式

pod trunk push xxx.podspec

pod repo add --help
Usage:
    $ pod repo add NAME URL [BRANCH]
Clones `URL` in the local spec-repos directory at `~/.cocoapods/repos/`. The
      remote can later be referred to by `NAME`.
Options:
CoderMeng
1134471523@qq.com
May 2nd, 21:03
None
      --progress
--silent
--verbose
--no-ansi
--help
Show the progress of cloning the spec repository
Show nothing
Show more debugging information
Show output without ANSI codes
Show help banner of specified command
複製程式碼

Include of non-modular header inside framework module 或者:fatal error: could not build module 'xxxxx'

# 私有庫的 .h ⽂檔案中引⼊入了了依賴的原始碼庫的 .h ⽂檔案,導致根據的私有庫的 module.modulemap 找不不到該頭⽂檔案,導致錯誤。
# 解決:設定 BuildSetting -》 Allow Non-modular Includes In Framework Modules YES

spec.user_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' }。
# lint 命令只剩下 warning。
# user_target_xcconfig 和 pod_target_xcconfig 的區別:
# user_target_xcconfig 是對於編譯⼯工程中所有 pod 的設定,
# ⽽而 pod_target_xcconfig 只是針對當前 pod 的。
# 所以如果多個 pod 的 podspec 中對 user_target_xcconfig 同⼀一個值進⾏行行了了設 置,那麼就可能存在衝突問題。
# 但因為 CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES 在 pod_target_xcconfig 不不起作⽤用,只能按現在的配置來處理理。
複製程式碼

Cloning into ‘/var/folders/rg/f1ycrs553dq2z2dq7mt0mbh80000gn/T/d20160921-12602- 1bx4f8v’... remote: Not Found fatal: repository ‘http://192.168.110.114/xxxxxx.git/’ not found

pod spec lint 命令,校驗 pod 的程式碼和配置時是從 git 上拉取的程式碼進⾏行行編 譯;沒有建立git,報錯。
複製程式碼

Cloning into ‘/var/folders/rg/f1ycrs553dq2z2dq7mt0mbh80000gn/T/d20160921-12686- 1o6vj1q’... fatal: Remote branch 0.1.0 not found in upstream origin

沒有在 git 上增加對應的 tag 值,報錯。
複製程式碼

[!] Found multiple specifications

將私有倉庫拉到本地時可能會存在兩個。
因為 git 存在兩個地址,分別是 git 和 http/https,所以有時候可能會在本地 repos 下出現兩個基於同⼀一個 git 的倉庫,倉庫名字不不同。
因為⼀一開始 Lint 的時候是指定了了倉庫名的,所以能通過,但 pod repo push 的 時候雖然指定了了 push 的倉庫名,但因為沒有指定校驗的倉庫名,⼀一旦你的 pod 依 賴了了私有倉庫中的某個 pod ,校驗時會出現類似 [!] Found multiple specifications xxxxLibrary :的錯誤。此時需要刪除掉⼀一個私有倉庫,然後重
新 push 才⾏行行。
複製程式碼

pod Libraries should not include the extension

⼯工程中導⼊入了了第三⽅方 SDK ,包含有⼆二進位制⽂檔案,沒有在 spec ⽂檔案中配置。 需要
配置⼀一下路路徑,保證 push repo 的時候,不不丟失⼆二進位制⽂檔案:
s.vendored_libraries = ['Class/SobotSDK/SobotLib/libSobotLib.a']
# :execution_position 選項有 [:before_compile, :after_compile, :any] 
s.script_phase = { :name => "Script Name", :script => "echo 'Hello World'", :execution_position => :any , :shell_path => "/bin/sh"}
複製程式碼

#ifdef DEBUG #define kAppKey @“123456789” #endif #ifdef RELEASE #define kAppKey @“987654321” #endif

編譯時,找不不到巨集定義 kAppKey ,需要設定檢視: Project -> Build Settings -> Preprocessor Macros -> Debug DEBUG=1 Release RELEASE
對應 Spec ⽂檔案設定: s.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "RELEASE COCOAPODS=1" }
複製程式碼

Shell Script Invocation Error Group sent 31754831 bytes received 54674 bytes 21206336.67 bytes/sec total size is 36763600 speedup is 1.16 /* com.apple.actool.errors / : error: There are multiple stickers icon set or app icon set instances named "AppIcon". / com.apple.actool.compilation-results */ /Users/mengyueping/Library/Developer/Xcode/DerivedData/Example- fdeuhzzwrdwyjrfsdeusamwbippd/Build/Products/Debug- iphonesimulator/Example.app/Assets.car /Users/mengyueping/Library/Developer/Xcode/DerivedData/Example- fdeuhzzwrdwyjrfsdeusamwbippd/Build/Intermediates.noindex/Example.build/De bug- iphonesimulator/Example.build/assetcatalog_generated_info_cocoapods.plist Command /bin/sh failed with exit code 1

Pod 資源拷⻉貝指令碼運⾏行行錯誤,⼤大致可能是不不同 Bundle 有同名資源或其他,在⾃自⼰己 ⼯工程 Build Phases -> Copy Pods Resources
去除 shell 指令碼。
資源拷⻉貝指令碼: "${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods- Example-resources.sh"
複製程式碼

duplicate symbol OBJC_IVAR$_ViewController._lastIndex in: /Users/mengyueping/Library/Developer/Xcode/DerivedData/Example- fdeuhzzwrdwyjrfsdeusamwbippd/Build/Products/Debug- iphonesimulator/libMain.a(ViewController.o)

duplicate symbol 重複符號,有可能是重複類,也有可能是在某個⽂檔案中引⼊入了了 .m ⽂檔案。 #import "ViewController.m"
複製程式碼

Unable to run command 'StripNIB TableViewListCell.nib' - this target might include its own product.

xib⽂檔案沒有指定路路徑,pod 的時候不不會下載 xib,xib⽂檔案算是資源⽂檔案的,需要另 外新增 s.resource 引⼊入。
s.source_files = "pod/classes/*/.{h,m}" s.resource = "pod/classes/TestViewController.xib"
或者把 xib 拷⻉貝到 bundle 中,直接指定資源⽂檔案路路徑為 bundle 。 
s.resources = ['.bundle', '.strings']
複製程式碼

Analyzing dependencies Fetching podspec for MyProject from ../ [!] Unable to find a specification for BaseSDK (= 1.0.2) depended upon by MyProject source 'git@10.2.24.2oMengCode/Specs.git' source

'https://github.com/CocoaPods/Specs.git' 沒有配置私有庫的索引庫地址。
複製程式碼

ld: '/Users/mengyueping/XesAppModule/XesAppUIKit/XesAppUIKitCode/Example/P ods/UMengUShare/UShareSDK/SocialLibraries/LaiWang/libLWApiSDK.a(LWApiRe quest.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Users/mengyueping/XesAppModule/XesAppUIKit/XesAppUIKitCode/Example/P ods/UMengUShare/UShareSDK/SocialLibraries/LaiWang/libLWApiSDK.a' for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

Build Settings -> Enable Bitcode -> NO
複製程式碼

在頭⽂檔案中,引⼊入了了第三⽅方pod管理理的庫的頭⽂檔案

Could not build module 'XesAppFoundation'

  • ERROR | xcodebuild: XesAppFoundationLib/XesAppFoundation/XesAppFoundation.framework/Hea ders/XesAppRefreshBackNormalFooter.h:9:9: error: include of non- modular header inside framework module 'XesAppFoundation.XesAppRefreshBackNormalFooter': 'Headers/Public/MJRefresh/MJRefreshBackNormalFooter.h' [-Werror,- Wnon-modular-include-in-framework-module]

  • NOTE | xcodebuild: Headers/Public/XesAppKit/XesAppSavaDataManager.h:11o9: fatal error: could not build module 'XesAppFoundation'

      s.user_target_xcconfig = { "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES" }
    複製程式碼

為了了讓⾃自⼰己的Pod被導⼊入時顯示出良好的⽂檔案層劃分,subspec是必須的。 若subspec要依賴其它的subspec,則subspec的dependency後⾯面接的不不是⽬目錄路路徑,⽽而是specA/specB這種spec關係

在私有庫引⽤用了了私有庫的情況下,在驗證和推送私有庫的情況都要加上所有的資 源地址,不不然pod會預設從官⽅方repo查詢。pod spec lint --sources='私有倉庫repo地址,github.com/CocoaPods/S…' pod repo push 本地repo名 podspec名 --sources='私有倉庫repo地址,github.com/CocoaPods/S…'

引⽤用⾃自⼰己或第三⽅方的framework或.a⽂檔案時在podsepc中應該這樣寫: s.ios.vendored_frameworks = "xxx//.framework"s.ios.vendored_libraries = "xxx//.a”

就是講Podfile中的pod '庫名', :path =>'本地路路徑'即可。這樣在通常的修改程式碼中是不不需要執⾏行行pod update的,但是對於如果修改了了⽬目錄結構(新增、刪除或者移動 ⽂檔案⽂檔案)或者是修改了了Podspec⽂檔案的配置的話,最好是運⾏行行⼀一下pod update的命令。普通修改程式碼的情況下就不不需要運⾏行行pod update命令和打tag了了。 pod 'iOS- Test', :path =>'../iOS-Test’

spec.resources = ["Images/.png", "Sounds/"] 但是這些資源會在打包的時候直接拷 ⻉貝的app的Bundle中,這樣說不不定會和其它資源產⽣生命名衝突

spec.resource = "Resources/MYLibrary.bundle" 把資源都放在bundle中,然後打包時候這個bundle會直接拷⻉貝進app的mainBundle中。使⽤用的時候在mainBundle中查詢這個bundle然後再搜尋具體資源 NSURL *bundleURL = [[NSBundle mainBundle] URLForResource:@"JZShare" withExtension:@"bundle"]; NSBundle *bundle = [NSBundle bundleWithURL:bundleURL]; UIImage *img = [UIImage imageNamed:icon inBundle:bundle compatibleWithTraitCollection:nil];

spec.resource_bundles = { 'MyLibrary' => ['Resources/.png'], 'OtherResources' => ['OtherResources/.png'] } 這種⽅方法利利⽤用 framework 的名稱空間,有效防⽌止了了資 源衝突。 使⽤用⽅方法是先拿到最外⾯面的bundle,然後再去找下⾯面指定名字 的 bundle 物件,再搜尋具體資源NSBundle *bundle = [NSBundle bundleForClass:[MYSomeClass class]]; NSURL *bundleURL = [bundle URLForResource:@"MyLibrary" withExtension:@"bundle"]; NSBundle *resourceBundle = [NSBundle bundleWithURL: bundleURL]; UIImage *img = [UIImage imageNamed:icon inBundle:bundle compatibleWithTraitCollection:nil];

如果私有庫新增了了靜態庫或者dependency⽤用了了靜態庫 那麼執⾏行行pod lib lint還有pod spec lint時候需要加上—user-libraries選項 否則會出現'The 'Pods' target has transitive dependencies錯誤

http://blog.xianqu.org/2015/08/pod-resources/
複製程式碼

包含有 MRC ⽂檔案類 方法⼀:

s.requires_arc = false s.source_files = "XesAppFoundation//.{h,m}" s.requires_arc = "XesAppFoundation/CommonComponent//.{h,m}"
複製程式碼

方法二: 子 subspec

Pod::Spec.new do |s|
s.name = "AppFoundation" 
s.version ="0.1.3.3"
s.summary = "App基礎 原始碼倉庫." 
s.description = <<-DESC App項⽬目組封裝了了⼀一些基礎的⼯工具,僅限 App項⽬目組內使⽤用 DESC 
s.homepage = "http://10.2.250.21/App" 
s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "raomeng" => "XXXX.com" } s.ios.deployment_target = "8.0" 
s.source = { :git => 'git@10.2.250.21AppModuleiOS/AppFoundationCode.git', :tag => s.version}
s.default_subspec = 'AppFoundationARC' 
non_arc_files = 'AppFoundation/MRC/*.{h,m}'
s.subspec 'AppFoundationARC' do |arc| arc.requires_arc = true 
arc.source_files ="AppFoundation/CommonComponent/*/.{h,m}" 
arc.exclude_files = non_arc_files
end
s.subspec 'AppFoundationNonARC' do |non_arc| non_arc.requires_arc = false 
non_arc.source_files = non_arc_files 
non_arc.dependency 'AppFoundation/AppFoundationARC' 
end
s.dependency 'FMDB' 
s.dependency 'MJRefresh' 
end複製程式碼

相關文章