Tutorial de Instalação do CocoaPods

Tutorial de Instalação do CocoaPods

Durante o desenvolvimento de aplicativos para iOS precisamos utilizar uma API ou até mesmo uma simples classe de terceiros para adicionar uma funcionalidade ao projeto. Com ferramentas de repositório de projetos tais como o CocoaPods ou Carthage para iOS e MacOS esta tarefa pode ser bastante simplificada.

Utilizar fontes open source desenvolvidos por terceiros pode ser interessante por se ter a vantagem de já ter sido testado por outros desenvolvedores. Ninguém quer ficar reiventando a roda e caso este projeto não possua todas as funcionalidades que você precisa, será um ponto de partida para não começar do zero. Caso você faça complementos ao fonte para adicionar novas funcionalidade ou melhorar uma funcionalidade já existente, você pode até fazer um pull request para disponibilizar estas melhorias aos fontes originais.

Neste tutorial explicarei como instalar o CocoaPods e como adicionar um pacote ao seu projeto.

Instalando o CocoaPods

Para instalar o CocoaPods digite o código abaixo no terminal.

$ sudo gem install cocoa pods

O CocoaPods foi desenvolvido utilizado a linguagem Ruby e este comando irá instala-lo utilizando a biblioteca Ruby que vem no MacOS. Repare que com o Ruby padrão que vem no MacOS será necessário um usuário que possua acesso de root.

Last login: Wed Feb 17 10:57:27 on ttys001
MacBook-Air-de-Mateus:~ mateusfsilva$ sudo gem install cocoa pods
Password:
Successfully installed cocoapods-0.39.0
Parsing documentation for cocoapods-0.39.0
1 gem installed

Criando um projeto para utilizar o CocoaPods

Agora que o CocoaPods está instalado crie um novo projeto no Xcode.

New Single View Application iOS

Choose options for your project

Navegue até a pasta raiz do projeto e digite o comando pod init para criar o arquivo Podfile onde ficam armazenados os dados dos projetos adicionados.

MacBook-Air-de-Mateus:~ mateusfsilva$ cd desenvolvimento/TutorialCocoaPods/
MacBook-Air-de-Mateus:TutorialCocoaPods mateusfsilva$ pod init
MacBook-Air-de-Mateus:TutorialCocoaPods mateusfsilva$ ls -la
total 8
drwxr-xr-x 6 mateusfsilva staff 204 22 Fev 19:44 .
drwxr-xr-x 36 mateusfsilva staff 1224 22 Fev 19:43 ..
drwxr-xr-x 12 mateusfsilva staff 408 22 Fev 19:44 .git
-rw-r--r-- 1 mateusfsilva staff 189 22 Fev 19:44 Podfile
drwxr-xr-x 7 mateusfsilva staff 238 22 Fev 19:43 TutorialCocoaPods
drwxr-xr-x 5 mateusfsilva staff 170 22 Fev 19:43 TutorialCocoaPods.xcodeproj
MacBook-Air-de-Mateus:TutorialCocoaPods mateusfsilva$

Instalando um pod

Vamos utilizar a biblioteca DeviceKit no nosso tutorial. Esta biblioteca nos da uma informação detalhada de qual device estamos rodando o nosso aplicativo e é um substituto do UIDevice do UIKit.

Você pode pesquisar os pods disponíveis no site cocoapods.org. No site é possível pesquisar filtrando pelo tipo de dispositivo e a linguagem utilizada conforme o print abaixo.

DeviceKit on cocoa pods.org

Consultando pelo nome DeviceKit encontramos o pod desejado disponível na versão 0.3.1. Abra o arquivo Podfile em um editor de texto e adicione a Biblioteca DeviceKit conforme o exemplo abaixo.

# Uncomment this line to define a global platform for your project
platform :ios, '9.0'
# Uncomment this line if you're using Swift
use_frameworks!

target 'TutorialCocoaPods' do
  pod 'DeviceKit', '~> 0.3.1'
end

Observe que o comentário da linha platform :ios, '9.0' foi excluido e desta forma definimos que a plataforma utilizada será o iOS versão 9.0.
Como estou utilizando a linguagem Swift também exclui o comentário da linha “use_frameworks!”.

No arquivo Podfile devemos definir os pods que iremos instalar dentro de um bloco que será criado para cada projeto. Exemplo:

target 'MeuProjeto'  do
  pod 'Pod1', '~> x.x'
  pod 'Pod2', '~> x.x.x'
end

Salve o arquivo Podfile e digite o comando pod install no diretório raiz do projeto para baixar os pacotes desejados.

MacBook-Air-de-Mateus:TutorialCocoaPods mateusfsilva$ pod install
Updating local specs repositories

CocoaPods 1.0.0.beta.3 is available.
To update use: `gem install cocoapods --pre`
[!] This is a test version we'd love you to try.

For more information see https://blog.cocoapods.org
and the CHANGELOG for this version http://git.io/BaH8pQ.

Analyzing dependencies
Downloading dependencies
Installing DeviceKit (0.3.1)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `TutorialCocoaPods.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
MacBook-Air-de-Mateus:TutorialCocoaPods mateusfsilva$ 

O comando pod install irá instalar todos os pods adicionados ao arquivo Podfile desde a última vez que o comando foi utilizado, então, você poderá adicionar mais pods ao projeto e executar o pod install que os novos pods serão instalados sem alterar os que já foram instalados previamente. Caso algum pod adicionado tenha um outro pod como dependência este também será instalado.
O gerenciamento dos pods que já foram instalados é feito através do arquivo Podfile.lock.

PODS:
  - DeviceKit (0.3.1)

DEPENDENCIES:
  - DeviceKit (~> 0.3.1)

SPEC CHECKSUMS:
  DeviceKit: eb8909d941cee4dc7f6cc5b1b40a41da523a197d

PODFILE CHECKSUM: bdd969b20450f88374e0fe9d62207a016d4a961a

COCOAPODS: 1.0.0.beta.2

Sempre que o comando pod install é executado o CocoaPods irá verificar quais pods estão no arquivo Podfile mas que ainda não estão no arquivo Podfile.lock e irá baixa-los dos respectivos repositórios. Caso o pod conste no Podfile.lock mas não esteja no diretório pods, ele será baixado na versão específica que estiver no Podfile.lock. Então, é interessante que você acrescente estes dois arquivos ao controle de versão para que todos os integrantes da equipe que forem utilizar o projeto instalem as mesmas versões dos pods.

O comando pod update irá atualizar todos os pods instalados anteriormente para a versão mais recente disponível no specs do CocoaPods. Cuidado com este comando pois ele pode quebrar a compilação do seu projeto dependendo da alteração realizada no pacote.

O comando pod install irá realizar as seguintes tarefas no seu projeto.

No Xcode, através do fonte ruby:

  1. Criará ou atualizará o workspace.
  2. Adicionará o seu projeto ao workspace se necessário.
  3. Adicionará o projeto da biblioteca statica do CocoaPods ao workspace se necessário.
  4. Adicionará libPods.a a: targets => build phases => link with libraries.
  5. Adicionará o CocoaPods arquivo de configuração do Xcode ao projeto do seu aplicativo.
  6. Alterará o target configurations do seu aplicativo para ser baseado no CocoaPods.
  7. Adicionará à faze de build para copiar os recursos de todos os pods que você adicionou ao seu projeto, ou seja, uma ‘Script build phase’ após todas as outras fases de build com o seguinte:
    • Shell: /bin/sh
    • Script: ${SRCROOT}/Pods/PodsResources.sh

Feche o projeto criado anteriormente e abra o workspace criado pelo CocoaPods.

Workspace in project folder

Note que além dos arquivos Podfile e Podfile.lock foi criado um workspace (.xcworspace) do projeto. Utilizaremos este arquivo para abrir o projeto a partir de agora.

Na pasta Pods ficam todos os pods adicionados no Podfile.

Pods Project

Note que foi criado um projeto Pods com os pods utilizados no projeto.

xconfig file

Linked Frameworks and Libraries

Linked Frameworks and Libraries

Build Phases

No projeto TutorialCocoaPods foram adicionados os arquivos xconfig com os dados utilizados pelo CocoaPods, a referência ao projeto Pods e as configurações de build incluindo o arquivo Pods-TutorialCocoaPods-resource.sh citado anteriormente. Ele irá adicionar todos os resources dos projetos dos pods à build do nosso projeto.

#!/bin/sh
set -e

mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"

RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"

XCASSET_FILES=()

realpath() {
  DIRECTORY="$(cd "${1%/*}" && pwd)"
  FILENAME="${1##*/}"
  echo "$DIRECTORY/$FILENAME"
}

install_resource()
{
  if [[ "$1" = /* ]] ; then
    RESOURCE_PATH="$1"
  else
    RESOURCE_PATH="${PODS_ROOT}/$1"
  fi
  if [[ ! -e "$RESOURCE_PATH" ]] ; then
    cat <> "$RESOURCES_TO_COPY"
      ;;
  esac
}

mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
  mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
  rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"

if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
  case "${TARGETED_DEVICE_FAMILY}" in
    1,2)
      TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
      ;;
    1)
      TARGET_DEVICE_ARGS="--target-device iphone"
      ;;
    2)
      TARGET_DEVICE_ARGS="--target-device ipad"
      ;;
    *)
      TARGET_DEVICE_ARGS="--target-device mac"
      ;;
  esac

  # Find all other xcassets (this unfortunately includes those of path pods and other targets).
  OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
  while read line; do
    if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
      XCASSET_FILES+=("$line")
    fi
  done <<<"$OTHER_XCASSETS"

  printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi

Utilizando o Devicekit

Vamos alterar o nosso projeto para utilizar as funcionalidades da biblioteca DeviceKit. Altere o arquivo ViewController.swift conforme o código abaixo.

import UIKit
import DeviceKit

class ViewController: UIViewController
{
   override func viewDidLoad()
   {
      super.viewDidLoad()

      let device = Device()

      print("Rodando no " + String(device))
   }
}

Adicionamos a referencia ao DeviceKit importando a biblioteca.

import DeviceKit

Depois instanciamos um objeto da classe Device.

let device = Device()

E por fim enviamos para o console o device que estamos utilizando.

print("Rodando no " + String(device))

Vamos rodar o projeto simulando com o iPhone 6S.

Run with iPhone 6S Simulator

Agora rodando no iPhone 6.

Run with iPhone 6

Agora que descobrimos como utilizar a biblioteca no nosso projeto, vamos altera-lo para mostrar o modelo do device utilizado com uma imagem do mesmo, e o estado da sua bateria. Altere o fonte ViewController.swift conforme o código abaixo.

//
//  ViewController.swift
//  TutorialCocoaPods
//
//  Created by Mateus Gustavo de Freitas e Silva on 22/02/16.
//  Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved.
//

import UIKit
import DeviceKit

class ViewController: UIViewController
{
   @IBOutlet weak var imageImageView: UIImageView!
   @IBOutlet weak var modelLabel: UILabel!
   @IBOutlet weak var batteryStateLabel: UILabel!

   func getImage(byURL link: String) -> UIImage?
   {
      if let url = NSURL(string: link),
         let data = NSData(contentsOfURL: url),
         let image = UIImage(data: data) {
            return image
      }

      return nil
   }

   override func viewDidLoad()
   {
      super.viewDidLoad()

      let device = Device()

      switch (device) {
         case .iPodTouch5, .Simulator(.iPodTouch5):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP657/sp657_ipod-touch_size.jpg") {
               imageImageView.image = image
            }
         case .iPodTouch6, .Simulator(.iPodTouch6):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP720/SP720-ipod-touch-specs-color-sg-2015.jpg") {
               imageImageView.image = image
            }
         case .iPhone4, .Simulator(.iPhone4):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg") {
               imageImageView.image = image
            }
         case .iPhone4s, .Simulator(.iPhone4s):
            if let image = getImage(byURL: "https://support.apple.com/library/content/dam/edam/applecare/images/en_US/iphone/iphone5s/iphone_4s.png") {
               imageImageView.image = image
            }
         case .iPhone5, .Simulator(.iPhone5):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP655/sp655_iphone5_color.jpg") {
               imageImageView.image = image
            }
         case .iPhone5c, .Simulator(.iPhone5c):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP684/SP684-color_yellow.jpg") {
               imageImageView.image = image
            }
         case .iPhone5s, .Simulator(.iPhone5s):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP685/SP685-color_black.jpg") {
               imageImageView.image = image
            }
         case .iPhone6, .Simulator(.iPhone6):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP705/SP705-iphone_6-mul.png") {
               imageImageView.image = image
            }
         case .iPhone6Plus, .Simulator(.iPhone6Plus):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP706/SP706-iphone_6_plus-mul.png") {
               imageImageView.image = image
            }
         case .iPhone6s, .Simulator(.iPhone6s):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP726/SP726-iphone6s-gray-select-2015.png") {
               imageImageView.image = image
            }
         case .iPhone6sPlus, .Simulator(.iPhone6sPlus):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP727/SP727-iphone6s-plus-gray-select-2015.png") {
               imageImageView.image = image
            }
         case .iPad2, .Simulator(.iPad2):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png") {
               imageImageView.image = image
            }
         case .iPad3, .Simulator(.iPad3):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg") {
               imageImageView.image = image
            }
         case .iPad4, .Simulator(.iPad4):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg") {
               imageImageView.image = image
            }
         case .iPadAir, .Simulator(.iPadAir):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP692/SP692-specs_color-mul.png") {
               imageImageView.image = image
            }
         case .iPadAir2, .Simulator(.iPadAir2):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP708/SP708-space_gray.jpeg") {
               imageImageView.image = image
            }
         case .iPadMini, .Simulator(.iPadMini):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP661/sp661_ipad_mini_color.jpg") {
               imageImageView.image = image
            }
         case .iPadMini2, .Simulator(.iPadMini2):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP693/SP693-   specs_color-mul.png") {
               imageImageView.image = image
            }
         case .iPadMini3, .Simulator(.iPadMini3):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP709/SP709-space_gray.jpeg") {
               imageImageView.image = image
            }
         case .iPadMini4, .Simulator(.iPadMini4):
            if let image = getImage(byURL: "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP725/SP725ipad-mini-4.png") {
               imageImageView.image = image
            }
         case .iPadPro, .Simulator(.iPadPro):
            if let image = getImage(byURL: "http://images.apple.com/v/ipad-pro/c/images/overview/bigger_app_adobe_photoshop_fix_large.jpg") {
               imageImageView.image = image
            }
         default:
            break
      }

      modelLabel.text = String(device)
      batteryStateLabel.text = String(device.batteryState)

      print("Rodando no " + String(device))
      print("Estado da bateria: " + String(device.batteryState))
   }
}

No Main.storyboard adicione dois labels e um imageView. Link os componentes com os outlets do ViewController.swift.

Main.storyboard

Rode o projeto em diferentes emuladores e em um device real.

Como pudemos ver neste tutorial, utilizar o CocoaPods para gerenciar bibliotecas de terceiros em nossos projetos é bastante fácil. Podemos atualizar estas bibliotecas sempre que necessário bastando apenas executar o comando pod update no diretório raiz do projeto. O CocoaPods adiciona todas as referências necessárias para que o projeto compile e as bibliotecas ficam na pasta pods separadas dos fontes locais.

Espero que tenham gostado do tutorial. Deixe seu comentário abaixo sobre o conteúdo do post e sobre sugestões de posts futuros.

Deixe um comentário