um pluguinho
Compartilhando código entre projetos iOS: A solução
No post anterior apresentei o problema sobre o compartilhamento de código entre projetos iOS, falei das soluções mais utilizadas e seus problemas, também falei da solução usando framework, e acabei falando sobre a pegadinha de que o framework só esta disponível para Mac OS X. Na verdade eu menti (era para o seu bem), essa opção só está disponível (oficialmente) para Mac OS X, podemos fazer para iOS, mas como tudo no iOS: com um certo trabalho.
Vamos a solução, primeiro vamos criar um novo projeto no Xcode, este projeto deve ser do tipo “iOS > Framework & Library > Cocoa Touch Static”:

Defina um nome para seu framework:

Obs: atenção a esse nome, no final vamos ter é alguma coisa como: [nome-do-projeto].framework.
Vamos adicionar aqui um código de exemplo:

Uma vez com um código de exemplo ou o código que você queira compartilha adicionado, já podemos compilar e verificar se tudo esta indo bem. Se tudo estiver certo vamos passar ao passo seguinte que é montar o framework. Para isso vamos adicionar um novo target do tipo: “iOS > Other > Aggregate”:

Vou dar o nome de “iOS-Framework”, mas você pode escolher o nome que lhe convier:

Agora precisamos adicionar 3 entradas na aba “Build Settings” desse target:

As entradas são as seguintes:
PRODUCT_NAME = ${PROJECT_NAME}
STATIC_TARGET_NAME = ${PRODUCT_NAME}
FRAMEWORK_DIR = ${PROJECT_DIR}/${PRODUCT_NAME}.framework
Lembra que falei que o resultado final do projeto é algo como [nome-do-projeto].framework? Pois bem, será assim se você seguir os valores que sugeri para essas entradas, evidente que você pode variar de acordo com o que lhe convier.
Na sequência vamos para aba “Build Phases”, e adicionamos duas fases do tipo “Run Scripts” e uma do tipo “Copy Files”, a baixo dou exemplo de nomes que você pode dar a essas fases:

Para primeira fase, no exemplo a fase “Build architecture-specific static libs”, que será responsável por compilar o código nas duas arquiteturas: x386 e ARM, Simulador e Device respectivamente vamos definir o seguinte script:
xcodebuild -project ${PROJECT_NAME}.xcodeproj -sdk iphoneos -target ${STATIC_TARGET_NAME} -configuration ${CONFIGURATION} clean build SYMROOT=${SYMROOT}
Já para segunda fase, a “Build framework package”, que vai montar a pasta do framework usando os arquivos compilados com o script anterior, vamos definir o script:
LIBRARY_NAME_PATH="lib${STATIC_TARGET_NAME}.a" &&
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${LIBRARY_NAME_PATH}" &&
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${LIBRARY_NAME_PATH}" &&
UNIVERSAL_LIBRARY_PATH="${FRAMEWORK_DIR}/Versions/A/${PRODUCT_NAME}"
# Create framework directory structure.
rm -rf "${FRAMEWORK_DIR}" &&
mkdir -p "${FRAMEWORK_DIR}/Versions/A/Headers" &&
mkdir -p "${FRAMEWORK_DIR}/Versions/A/Resources" &&
# Generate universal binary from desktop, device, and simulator builds.
lipo "${SIMULATOR_LIBRARY_PATH}" "${DEVICE_LIBRARY_PATH}" -create -output "${UNIVERSAL_LIBRARY_PATH}" &&
# Move files to appropriate locations in framework paths.
cd "${FRAMEWORK_DIR}/Versions" &&
ln -s "A" "Current" &&
cd "${FRAMEWORK_DIR}" &&
ln -s "Versions/Current/Headers" "Headers" &&
ln -s "Versions/Current/Resources" "Resources" &&
ln -s "Versions/Current/${PRODUCT_NAME}" "${PRODUCT_NAME}"
Escolhendo o target “iOS-Framework” e compilando já devemos obter uma pasta [nome-do-projeto].framework nas pasta do projeto, isso é o suficiente para termos uma framework que pode ser usando em outro projeto, mas apenas bibliotecas estáticas não compõe um framework, um dos pontos principais de um framework são os arquivos de cabeçalho, os famosos .h. Precisamos copiar os arquivos .h para pasta “Headers”, para isso vamos usar a ultima fase que adicionamos ao target:

Neste ponto devemos arrastar os arquivos de cabeçalhos que precisarmos para esta fase. Assim podemos compilar e obter uma pasta .framework que podemos utilizar em qualquer projeto iOS. Mas como usar este framework?
O processo é bem parecido com adicionar um framework oficial, a diferença é que devemos procurar pela pasta .framework no lugar de escolher uma da lista:

Observe que no exemplo eu arrastei o MyFramework.framework para o grupo Frameworks, para uma melhor organização do código. Se você tiver interesse em ver como ficou esse projeto de exemplo pode baixa-lo aqui.
Update: Ficou faltando alguma referência ne?
Referência 1: Eu cheguei a escrever um artigo antes desse falando de um metodo que usava target do tipo “Mac Framework”, mas como não funcionou com o Device, e era bem complexo quando comparado a essa solução, resolvi mudar a abordagem, mas se tiver interesse nessa solução de uma olhada neste post.
Referência 2: A solução que descrevi aqui não veio do nada, na verdade ela é uma simplificação e um roteiro para solução que o pessoal do Pivotal Labs utilizou na criação do Framework Cedar, um framework de testes que vale dar uma olhada, e quem sabe um post
| Print article | This entry was posted by Éverton Antônio on July 12, 2011 at 11:34 pm, and is filed under Desenvolvimento, iOS. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |