[Legacy] Sử dụng cơ bản Cocoapods và Carthage

Posted on April 7th, 2019

Trong lập trình, việc sử dụng các thư viện third-party là rất thường xảy ra cho phép phát triển ứng dụng rất nhanh chóng bằng cách dùng lại những phần code mà người khác đã viết trước đó. Hầu hết những ngôn ngữ lập trình hiện nay đều có các công cụ hỗ trợ quản lý các thư viện này một cách tập trung và hiệu quả, được gọi là các dependency manager hay package manager. Khi làm việc với ngôn ngữ Swift, có 2 dependency manager cần xem xét là Cocoapods và Carthage. Phần còn lại sẽ nói về cách dùng 2 công cụ này trong một Swift project.

Note: Ngoài ra còn có Swift package manager, tuy nhiên cá nhân chưa có cơ hội sử dụng nên sẽ đề cập ở một bài khác khi có thể.

Giả định đã tạo sẵn một iOS project sử dụng Swift và cần dùng thư viện Google PromiseKit cho một mục đích nào đó, không quan trọng, điều cần chú ý là các bước để dùng một thư viện trong project.

ToDo: Tạo mới một project đặt tên tùy ý, chẳng hạn SwiftDemo, sử dụng template iOS > Single View App

Xcode create ios project

 ~/Desktop/SwiftDemo  ls
SwiftDemo           SwiftDemo.xcodeproj

Cocoapods

Giới thiệu

Cocoapods là công cụ quản lý các thư viện phụ thuộc trong Xcode project. Những thư viện phụ thuộc này được khai báo trong một file text tên là Podfile. Cocoapods sẽ giải quyết các vấn đề liên quan tới phụ thuộc thư viện, fetch source code và sau đó link chúng lại với nhau trong một file Xcode workspace.

Cài đặt Cocoapods

Cocoapods được phân phối như một package của gem do đó có thể dễ dàng được cài đặt trên macOS bằng command sudo gem install cocoapods như dưới đây:

 ~/Desktop/SwiftDemo  sudo gem install cocoapods
Successfully installed cocoapods-1.6.1
Parsing documentation for cocoapods-1.6.1
Done installing documentation for cocoapods after 1 seconds
1 gem installed

Khởi tạo

Chạy lệnh pod init trong thư mục dự án, Cocoapods sẽ tự tạo ra một file mới tên là Podfile

 ~/Desktop/SwiftDemo  pod init
 ~/Desktop/SwiftDemo  ls
Podfile             SwiftDemo           SwiftDemo.xcodeproj
 ~/Desktop/SwiftDemo  cat Podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'SwiftDemo' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SwiftDemo

end

Update Podfile

Thay đổi nội dung của Podfile ở 2 chỗ:

  • Uncomment dòng khai báo platform và thay đổi thành platform :ios, '11.4'
  • Thêm tên thư viện cần dùng trong project vào dưới dòng # Pods for SwiftDemo

Như sau:

 ~/Desktop/SwiftDemo  nano Podfile
 ~/Desktop/SwiftDemo  cat Podfile
# Uncomment the next line to define a global platform for your project
platform :ios, '11.4'

target 'SwiftDemo' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SwiftDemo
  pod 'PromisesSwift', '~> 1.2.7'
end

Cài đặt dependency

Podfile đang thao tác ở trên là một file chứa các thông tin cần thiết nhằm hướng dẫn Cocoapods các việc nó cần làm. Tuy nhiên, đó chỉ mới là bước khai báo, sau command dưới đây Cocoapods sẽ thực sự thực hiện các công việc gồm nhiều bước nhằm giúp chúng ta có thể dùng được PromiseKit

 ~/Desktop/SwiftDemo  pod install
Analyzing dependencies
Downloading dependencies
Using PromisesObjC (1.2.7)
Using PromisesSwift (1.2.7)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 2 total pods installed.

Giờ thì thư mục dự án sẽ có thêm: Podfile.lock, Pods, SwiftDemo.xcworkspace

 ~/Desktop/SwiftDemo  ls
Podfile               Podfile.lock          Pods                  SwiftDemo             SwiftDemo.xcodeproj   SwiftDemo.xcworkspace

Mở file SwiftDemo.xcworkspace để vào Xcode project, chúng ta sẽ thấy Cocoapods thực hiện những thay đổi trong đó có ở Build Phases của project, trong section [CP] Embeded Pods Frameworks như hình dưới đây:

Xcode embeded pods

Đến đây, thư viện Promises đã có thể được import vào project và bắt đầu sử dụng.

Notes:

  • Podfile.lock là file được tự động tạo ra sau khi pod install lần đầu tiên nhằm track lại version của những Pod đã cài đặt trong project. Bằng cách này, khi làm việc nhóm chúng ta được đảm bảo thống nhất version của Pod mà mỗi member install trên máy mình. Ý tưởng tương tự như yarn.lock trong các project Javascript dùng Yarn.
  • pod install: cài đặt mới các pods vào project kể cả khi đã có Podfile và run pod install trước đó.
  • pod update [podname]: chỉ sử dụng khi cần nâng version cho pods đã được cài đặt trong project.

Carthage

Giới thiệu

Carthage ra đời với mong muốn cung cấp cho cộng đồng một giải pháp đơn giản nhất để add các framework vào ứng dụng Cocoa. Nó sẽ build các dependencies và cung cấp cho chúng ta những file .framework, trong khi không làm thay đổi quá nhiều cấu trúc project và build settings.

Cài đặt Carthage

Có vài cách cài đặt Carthage nhưng đơn giản nhất là thông qua Homebrew dành cho macOS bằng command brew install carthage

 ~  brew install carthage
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
No changes to formulae.

==> Downloading https://homebrew.bintray.com/bottles/carthage-0.33.0.high_sierra.bottle.tar.gz
Already downloaded: /Users/v001132/Library/Caches/Homebrew/downloads/1fcd423830ab46ddf13abecb3e8c412f8bdf9ba1a2da2fe6356953748a558310--carthage-0.33.0.high_sierra.bottle.tar.gz
==> Pouring carthage-0.33.0.high_sierra.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/carthage/0.33.0: 8 files, 21.3MB
==> `brew cleanup` has not been run in 30 days, running now...
Pruned 3 symbolic links and 11 directories from /usr/local

Sau đó, cẩn thận kiểm tra lại cài đặt đã thành công hay chưa.

 ~  which carthage
/usr/local/bin/carthage

Khởi tạo

Tương tự như phần ví dụ trên dùng Cocoapods, phần này cũng sẽ thao tác trên Xcode project iOS tên là SwiftDemo. Và cũng sẽ dùng Google PromiseKit.

 ~/Desktop/SwiftDemo  ls
SwiftDemo           SwiftDemo.xcodeproj

Khởi tạo một file mới tên là Cartfile không có phần mở rộng và thêm vào nội dung github "google/promises" như sau:

 ~/Desktop/SwiftDemo  touch Cartfile
 ~/Desktop/SwiftDemo  nano Cartfile
 ~/Desktop/SwiftDemo  cat Cartfile
github "google/promises"

Cartfile cũng tương tự như Podfile là file chứa những thông tin khai báo cho Carthage làm việc. Tuy nhiên dễ thấy rằng nội dung của một Cartfile là đơn giản hơn nhiều so với Podfile.

Cài đặt dependency

Sau khi đã khai báo thư viện cần dùng trong Cartfile, phần còn lại khá đơn giản chỉ với một command carthage update như bên dưới và Carthage sẽ lo phần còn lại.

 ~/Desktop/SwiftDemo  carthage update
*** Fetching promises
*** Checking out promises at "1.2.7"
*** xcodebuild output can be found in /var/folders/t5/38qvxf0s3nd2mrdk_m9dj4700000gn/T/carthage-xcodebuild.CovWCc.log
*** Building scheme "Promises" in Promises.xcworkspace
*** Building scheme "FBLPromises" in Promises.xcworkspace
 ~/Desktop/SwiftDemo  ls
Cartfile            Cartfile.resolved   Carthage            SwiftDemo           SwiftDemo.xcodeproj
 ~/Desktop/SwiftDemo  cat Cartfile.resolved
github "google/promises" "1.2.7"
 ~/Desktop/SwiftDemo  ls Carthage/Build/iOS
3065AAE7-90DF-3210-86C4-F0A0607CF71A.bcsymbolmap F5D0C819-8C48-3136-BF0E-AD561C7FB02C.bcsymbolmap Promises.framework
84827DDD-3C93-3C9F-8B47-5462307FBA9F.bcsymbolmap FBLPromises.framework                            Promises.framework.dSYM
C5AD052C-DE5C-3C92-AC73-40F6C90C8ACD.bcsymbolmap FBLPromises.framework.dSYM

Có thể thấy trong đoạn log trên, sau khi run command carthage udpate trong thư mục dự án sẽ được tạo thêm:

  • File Cartfile.resolved
  • Thư mục Carthage

    • Thư mục con Checkouts: là thư mục chứa source của Promise được clone về từ Github
    • Thư mục con Build: chứa những build output tương ứng với từng platform. Ở đây, trong trường hợp chỉ cần dùng cho iOS, ta có thể thêm option vào command ở trên carthage udpate --platform iOS. Khi đó sẽ chỉ có thư mục iOS được build ra.

Khi Carthage đã build xong các dependency, output là những file có extension .framework. Phần còn lại chỉ cần mở Xcode project và link chúng vào trong Build Phases như hình sau.

Xcode link framework

Như vậy ta đã add một dependency vào trong Xcode project bằng Carthage và chúng ta có thể sử dụng nó trong code từ giờ.

Kết luận

Bài post này đã đi qua những bước cơ bản để có thể sử dụng một dependency trong Xcode project bằng cả CocoapodsCarthage. Có những chỗ khác nhau giữa 2 công cụ này nhưng dễ nhận thấy rằng Carthage đơn giản hơn trong cách dùng. Cũng chính vì vậy mà mặc dù ra đời sau, nhưng Carthage nhanh chóng được đón nhận và sử dụng ngày càng nhiều.