DEV Community

Cover image for Evitando conflitos no Xcode
Rafael Leandro
Rafael Leandro

Posted on

Evitando conflitos no Xcode

Introdução

O objetivo desse texto é mostrar como resolvi alguns problemas no meu time utilizando o Tuist para gerar projetos e workspaces do Xcode e que com isso nós evitamos conflitos na hora do merge, resolvemos problemas para gerenciar dependências e também podemos padronizar configurações dos projetos e abrir individualmente o projeto que vai ser alterado (modo foco).

Instalação

A instalação é muito simples, basta executar o comando no terminal:
curl -Ls https://install.tuist.io | bash

Criando um projeto novo

Se for um novo projeto a utilização do Tuist é super simples.
Basta criar uma pasta e executar o tuist init

mkdir MyApp
cd MyApp
tuist init --platform ios
Enter fullscreen mode Exit fullscreen mode

O comando init irá gerar os arquivos base, Info.plist, AppDelegate.swift, arquivos de teste e o Project.swift que contém as configurações do projeto.

Migrando um projeto existente

A migração no meu caso foi tranquila porque o projeto é simples e tenho um Workspace com vários projetos que dependem do Core e uma única dependência externa em um Target de teste.

Comecei migrando o Core, porque precisava definir a dependência dele nos outros projetos, resolvi todas as outras dependências e por último configurei o Workspace.
Na pasta de cada projeto criei o arquivo Project.swift, no diretório raíz o Workspace.swifte a pasta Tuist com o arquivo Dependencies.swift

Configurações do projeto

O Project.swift contém a configuração do projeto. É nesse arquivo onde são definidos nome, organização, targets, schemas, entre outras coisas.

Comecei fazendo o import do framework ProjectDescription esse arquivo deve inicializar uma variável do tipo Project que pode ter qualquer nome, mas a recomendação da documentação é nomear como project mesmo.

Um project precisa obrigatoriamente dos parâmetros: name e targets que é um array do tipo Target.

No Target é especificado o nome, plataforma, tipo do produto, bundle e os arquivos de código.

let target = Target(name: "App",
                    platform: .iOS,
                    product: .app,
                    bundleId: "com.rafa.example",
                    infoPlist: "Info.plist",
                    sources: "Sources/**",
                    dependencies: [])
Enter fullscreen mode Exit fullscreen mode
let project = Project(
    name: "MyProject",
    targets: [target]
)
Enter fullscreen mode Exit fullscreen mode

Dependências externas

A integração com dependências externas ainda está em alpha, como é avisado na documentação

No momento que estou escrevendo esse texto a integração com Cocoapods ainda não é suportada.

Cada projeto pode ter suas dependências configuradas individualmente, basta criar a pasta Tuist com o arquivo Dependencies.swift dentro dela.
No meu caso, fiz isso na pasta raiz do projeto porque tenho uma única dependência externa.

import ProjectDescription

let dependencies = Dependencies(
    carthage: [
        .github(path: "Alamofire/Alamofire", requirement: .exact("5.0.4")),
    ],
    swiftPackageManager: [
        .remote(url: "https://github.com/Alamofire/Alamofire", requirement: .upToNextMajor(from: "5.0.0")),
    ],
    platforms: [.iOS]
)
Enter fullscreen mode Exit fullscreen mode

Feito isso baixe as dependências rodando
tuist dependencies fetch. Uma pasta chamada Dependencies será criada e o código será baixado nela.

De volta ao Project.swift é necessário registrar no Target a dependência baixada.

let target = Target(name: "App",
                    platform: .iOS,
                    product: .app,
                    bundleId: "com.rafa.example",
                    infoPlist: "Info.plist",
                    sources: "Sources/**",
                    dependencies: [
                .external(name: "Alamofire"),
            ])
Enter fullscreen mode Exit fullscreen mode

Configurações do Workspace

Por padrão o tuist generate cria um Workspace com o mesmo nome do projeto e já inclui as dependências.
No meu caso os projetos estão num monorepo, então preciso configurar um Workspace e adicionar todos os projetos nele.

import ProjectDescription

let workspace = Workspace(
    name: "ProjectWorkspace",
    projects: [
        "Project1",
        "Project2",
        "Project3"
    ],
    schemes: []
)
Enter fullscreen mode Exit fullscreen mode

Por padrão os schemas são gerados automaticamente, mas podem ser personalizados para configurar as ações de cada um.

Gerando os arquivos

A configuração é essa, dependendo do tamanho do projeto pode ser um pouco cansativa mas os ganhos são compensatórios.

Depois de tudo configurado, é só rodar o tuist dependencies fetch para baixar as dependências e depois tuist generate para gerar os projetos/workspaces.

Testei outras ferramentas mas resolvi adotar o Tuist por utilizar Swift e não Yaml, possibilidade de fazer cache dos módulos, cache dos testes, screenshot de dependências e por considerar a adoção fácil no projeto em que trabalho.
Finalizei implementando o xcdiff evitando que o .xcodeproj fosse alterado manualmente.

E é isso! :)

Links úteis

Tuist.io
Tuist docs
xcdiff

Discussion (3)

Collapse
francidellamora profile image
Francielle Dellamora

Muito bom o artigo!! entendi nada

Collapse
raafas profile image
Rafael Leandro Author

Ainda vou te transformar em dev iOS, tu vai ver.

Collapse
francidellamora profile image
Francielle Dellamora

quero ver