Quais habilidades são necessárias para criar um aplicativo iOS? Relatório Yandex

Um desenvolvedor móvel precisa ter um conjunto claro de habilidades. Você precisa falar sobre eles no contexto de tarefas específicas que surgem durante a criação e publicação do aplicativo. Arthur Antonov trabalha como desenvolvedor iOS no departamento de tradução automática Yandex. Em seu relatório para estudantes e iniciantes, Arthur explicou o que um desenvolvedor deve ser capaz de fazer para criar um software móvel moderno.


- Existem dois aplicativos móveis em nosso departamento: Yandex.Translate e Yandex.Keyboard. No Translator, temos muitas tecnologias sofisticadas, como entrada de voz, reconhecimento de texto por foto, tradução de texto usando redes neurais. Um desafio separado é manter essa funcionalidade offline. Ou seja, essa funcionalidade funcionará para você mesmo sem a Internet.



O teclado é uma classe separada de aplicativos; existem requisitos separados para a velocidade e a qualidade do próprio aplicativo. A correção automática em russo funciona para nós: ajuda o usuário, mas não o incomoda. Entrada de voz, entrada de furto.





Um recurso interessante separado é a grade dinâmica: tenta prever a próxima letra e, dependendo disso, altera o tabson. Ou seja, é mais fácil entrar em uma carta mais provável.



Na escola, eu estava envolvido em programação esportiva. Mas quando entrei na universidade, parecia-me um pouco chato, queria desenvolver programas para pessoas comuns e é desejável que estejam disponíveis sempre e em qualquer lugar. Então, eu decidi escolher o desenvolvimento móvel. Mas os aplicativos móveis são multifacetados, e a maior questão que surgiu diante de mim é por onde começar.

A Internet agora está cheia de cursos on-line, tutoriais, livros sobre vários tópicos, e a cabeça simplesmente explode. Não está claro por onde começar. Portanto, no meu relatório, gostaria de ajudá-lo a criar seu caminho de aprendizado para se tornar um desenvolvedor de dispositivos móveis. O que vale a pena estudar no início, o estudo do que pode ser adiado.



Depois de analisar meu trabalho ao longo de vários anos, identifiquei várias habilidades essenciais necessárias para resolver a maioria dos problemas. Essas são habilidades fundamentais e as chamadas habilidades da caixa de ferramentas. Eles não são necessários no desenvolvimento de aplicativos móveis, mas se você os possui, sua vida se tornará mais fácil e a qualidade de seus aplicativos será muito melhor.

Como uma teoria sem prática está morta, estudaremos as habilidades usando o exemplo de uma versão simplificada do Yandex.Translator. Quando você termina o projeto, tudo o que vê é uma tela branca.

Vamos reviver nosso aplicativo usando a interface do usuário.





Existem duas maneiras clássicas de criar uma interface - um editor gráfico e um código. Este é um dos tópicos de hollywood no desenvolvimento móvel. Existem adeptos do desenvolvimento em um editor gráfico e alguém não reconhece nada, exceto o código. Mas eu aconselho você a experimentar os dois métodos. Você certamente os encontrará e, além disso, ninguém o proíbe de combinar abordagens, por exemplo, coisas simples para fazer em um editor gráfico e outras já complexas no código.



E, recentemente, os desenvolvedores do iOS têm uma nova estrutura SwiftUI que está tentando combinar essas duas abordagens. Ou seja, ao alterar em um editor gráfico, seu código muda e vice-versa. Talvez quando essa estrutura se espalhe, todas as disputas entrem no esquecimento.

Infelizmente, o SwiftUI está disponível apenas a partir do iOS 13, portanto não pode ser usado em grandes projetos até o momento.



O editor gráfico possui uma interface muito simples. Pegamos componentes prontos, arrastamos para uma tela virtual e vemos imediatamente o que obtemos. Por esse motivo, é muito rápido criar componentes simples da interface do usuário. Também podemos redimensionar a tela virtual para diferentes dispositivos e testar nossa interface sem iniciar o aplicativo.





Por outro lado, temos um design de interface no código. Ao desenvolver uma interface em seu código, a biblioteca UIKit será útil e você usará pequenos blocos de construção chamados UIView. Os objetos UIView correspondem aproximadamente aos componentes que você exibiu na tela. E, assim como em um editor gráfico, você tem subclasses prontas para componentes comumente usados, como botões e texto.

Ao desenvolver no código, é muito importante entender que outros UIViews podem criar UIView dentro de si mesmos, ou seja, você pode criar interfaces de qualquer complexidade. Como resultado, você obtém a chamada árvore. É mais fácil modificar a partir do código. Ou seja, se você possui uma interface de usuário muito dinâmica, pode valer a pena escrevê-la no código e será mais fácil modificá-la posteriormente.



Vamos ver qual código pode ser escrito para o nosso tradutor.

Primeiro, definimos a cor de fundo como amarela. Em seguida, adicionamos um campo de entrada onde o usuário digita o texto em inglês. Em seguida, adicionamos um separador de beleza e, finalmente, adicionamos um campo de saída, proibindo o usuário de editá-lo.

Temos uma interface de usuário pronta, mas o aplicativo ainda é bastante inútil. Não resolve a principal tarefa do usuário - tradução do texto.

Vamos adicionar essa funcionalidade. Os recursos da plataforma SDK nos ajudarão.



Os SDKs da plataforma são um conjunto de ferramentas e bibliotecas para a criação de aplicativos móveis que a Apple e a Google nos fornecem para a Apple.

Atualmente, o SDK possui muitas bibliotecas de baixo nível para interagir com o sistema operacional, e você pode implementar praticamente qualquer idéia de aplicativo móvel sem muito esforço.

Quais bibliotecas você usará depende das especificidades do seu aplicativo. Por exemplo, se quisermos fazer uma câmera, provavelmente você precisará de duas bibliotecas: AVFoundation para trabalhar com a câmera e CoreImage para processamento de imagens.

Portanto, nesta fase, não é necessário memorizar todas as bibliotecas, é simplesmente impossível. Mais importante é a capacidade de encontrar as ferramentas certas. E, infelizmente, a documentação oficial nem sempre documenta totalmente os recursos. Às vezes, você encontra algumas coisas interessantes, por exemplo, em um blog ou no twitter de outro desenvolvedor. Vale a pena seguir o campo de informações.

Então, o que precisamos do SDK para o nosso tradutor?



Nosso tradutor é um aplicativo cliente-servidor clássico: solicitamos ao servidor e obtemos uma resposta. Então, de alguma forma, transformamos e mostramos ao usuário. A estrutura da Fundação nos ajudará nessa tarefa. Ele contém abstrações convenientes para resolver tarefas diárias.

Vamos extrair a classe URLSession, essa é a classe para trabalhar com o servidor usando o protocolo http e JSONSerialization, essa é a classe que nos ajuda a converter objetos do formato JSON.



Então, vamos ver o código que precisamos escrever para essa funcionalidade. À esquerda, há um método que é executado sempre que a entrada do usuário é alterada. Primeiro, criamos um URL com o endereço do servidor do tradutor e fazemos uma solicitação. Além disso, depois que recebemos a resposta, a analisamos no formato JSON, obtemos o texto desejado, ou seja, o texto da tradução. E o último passo - dizemos que no campo de entrada você precisa definir a resposta recebida.

Vamos ver o que temos. O usuário digita olá e "olá" é exibido:



Mas "olá" apareceu de alguma forma por um longo tempo, não pareceu ser uma falha na rede. Para maior confiabilidade, vamos comparar com o irmão mais velho:

Abrir GIF

Nos dois aplicativos, inserimos o texto hello e vemos que a tradução já apareceu várias vezes no tradutor real. No nosso tradutor, a tradução aparece com um grande efeito.

Para corrigir esse problema, precisamos nos familiarizar com o modelo de multithreading em aplicativos móveis.



Assim como na área de trabalho, os aplicativos móveis são executados em um ambiente multithread. Mas há uma limitação importante. Um aplicativo móvel possui um thread principal ou o chamado thread da interface do usuário. E qualquer operação com a interface do usuário, qualquer alteração na interface do usuário deve ocorrer neste encadeamento principal. Se você deseja alterar a cor do botão ou movê-lo - tudo deve estar no fluxo da interface do usuário.

Por outro lado, todas as interações do usuário também chegam até nós no segmento principal. Ou seja, o usuário clicou em um botão - recebemos uma mensagem no thread principal. O texto foi alterado, como no nosso caso - também o conseguimos no tópico principal. Como existe apenas um fluxo e todas as ações com a interface do usuário ocorrem nele, é muito importante cuidar dele e fazer o mínimo possível de computação, caso contrário, você corre o risco de estar em uma situação em que está processando uma ação do usuário por um longo tempo e tem uma fila de outras ações do usuário. Então tudo começa a congelar.

Por esse motivo, muitas bibliotecas do sistema, por padrão, são executadas em um fluxo em segundo plano. Por exemplo, uma viagem à rede leva em média de 100 a 500 milissegundos. Como é uma operação bastante cara para o fluxo principal, toda a interação com a rede ocorre no fluxo em segundo plano.

E, novamente, isso cria problemas para nós, porque, se inadvertidamente usarmos o resultado obtido do servidor imediatamente para alterar a interface do usuário, isso poderá levar a uma falha ou travamentos.

Lembre-se da nossa última linha:

self.textOutputView.text = translation

Nele, pegamos o resultado do servidor e o definimos no campo de saída. Assim, violamos a primeira regra - alteramos a interface do usuário e não do segmento principal. A biblioteca padrão Grand Central Dispatch ajudará a corrigir isso. Facilmente nos ajuda a mudar para o thread principal e executar esta ação no thread principal.

DispatchQueue.main.async {
  self.textOutputView.text = translation
}

Vamos ver o que conseguimos com o aplicativo no final.



O usuário digita o texto e vemos que a tradução ocorre quase instantaneamente. Viva! Nós derrotamos esse problema. Mas, antes de liberar o aplicativo, vamos falar sobre outro tópico importante - arquitetura.

Infelizmente, no projeto atual, não poderei demonstrar a importância da arquitetura para você, ainda é muito pequena.



Mas, asseguro-lhe, a arquitetura não surgiu de uma vida melhor, nem do fato de que os desenvolvedores não têm nada para fazer e escrevem abstrações para não serem demitidas. Arquitetura é a resposta para os desafios do desenvolvimento móvel.

O principal desses problemas é a escalabilidade. Quando seu aplicativo fica grande demais e possui uma funcionalidade diferente, é importante que seja fácil entender, expandir e depurar. Caso contrário, qualquer adição de recursos mudará todos os antigos. E o risco de termos bugs aumenta.

Não espere até o aplicativo crescer. Já no estágio inicial, você pode aprender as práticas básicas de criação de software que também funcionam para aplicativos móveis, como o SOLID, padrões de quadrilha de quatro.

A arquitetura dos aplicativos móveis tem suas próprias especificidades: seus componentes globais ou grandes são construídos de acordo com padrões arquitetônicos que dizem em alto nível quais objetos devem pertencer a qual camada. Os mais populares são MVC, MVP e MVVM.

E não vamos esquecer que, na realidade, a arquitetura não é uma bala de prata. É necessário levar em consideração as especificidades do projeto. Se você está colocando algum tipo de arquitetura em seu projeto com lágrimas nos olhos, talvez algo tenha dado errado.

Quando você estuda teoria, isso parecerá terrivelmente complicado para você. Mas, de fato, quando você trabalha em um projeto com boa arquitetura, ficará feliz porque ficou mais fácil escrever código. Você sabe o que e onde adicionar para ter um recurso. Portanto, nesta fase, para conhecer bem a arquitetura, aconselho que você trabalhe ou faça estágio em um grande projeto. Se você não tem essa oportunidade, agora muitas empresas colocam seus projetos em código aberto: Wikipedia, Firefox. E ninguém proíbe que você vá ao GitHub e veja lá.

Então, nosso aplicativo está pronto. Vamos colocá-lo em domínio público para que os usuários possam baixá-lo.



Na maioria dos casos, os usuários obtêm aplicativos do Google Play e da App Store. Mas antes de adicionar o aplicativo à loja, devemos assiná-lo. Isso ocorre porque os sistemas operacionais executam aplicativos apenas de desenvolvedores confiáveis. Assim, nas plataformas móveis, temos muito menos aplicativos e vírus maliciosos, porque apenas desenvolvedores confiáveis ​​têm acesso ao trabalho em dispositivos móveis.

Para fazer isso, você precisa emitir um certificado de desenvolvedor. Esta é realmente uma pequena burocracia e, felizmente, é automatizada nas últimas versões do Xcode.

Além disso, você precisa fazer capturas de tela para seu aplicativo e descrição. As duas últimas etapas não devem ser negligenciadas, porque a página do seu aplicativo é seu anúncio. Se não estiver claro, provavelmente todo o nosso desenvolvimento foi em vão, porque ninguém fará o download do aplicativo.

O aplicativo foi carregado. Agora, vamos falar sobre algumas habilidades adicionais que podem simplificar sua vida e melhorar a qualidade dos aplicativos.

A habilidade que você usará com mais frequência é a depuração.



O principal método de depuração é o bom e velho console.log ou printf. Tem muitos nomes, mas o significado é o mesmo. Quando algo dá errado, adicionamos log e imprimimos variáveis. Infelizmente, esse método também apresenta desvantagens críticas.

A primeira das desvantagens é alterar o código fonte. Há erros que desaparecem quando você adiciona printf. E você remove printf - surge novamente. Esses erros ainda têm um nome separado - heisenbug.

A segunda consequência é que você precisa recompilar seu aplicativo e executá-lo novamente. Em projetos grandes, isso pode levar alguns minutos e, se você precisar esperar um minuto ao adicionar cada novo log, você gastará muito tempo no total.

E a última e mais crítica desvantagem do printf - infelizmente, não ajuda em todos os erros.

Um exemplo da prática pessoal. Ao desenvolver a integração do teclado, aconteceu o seguinte:



No teclado do sistema abaixo, em vez dos ícones do globo e do microfone do sistema, alguns identificadores apareceram. Depurando esse bug, me senti assim:



Como um aplicativo pode quebrar um teclado do sistema ?! Acabou que podia.



Ao investigar o bug, o conhecimento do depurador me ajudou muito. Em particular, definir o ponto de interrupção para chamar determinadas funções. Veja o Depurador, onde podemos examinar nossa interface de usuário e ver quem tem qual classe e qual estado.

Quando tirei proveito desses dois primeiros pontos, constatou-se que o problema estava na biblioteca do UIKit. Os desenvolvedores do iOS estão familiarizados com isso e sabem que ele não possui código-fonte aberto. Mas quando você conhece o assembler, qualquer biblioteca torna-se de código aberto para você, portanto, pequenos princípios básicos do assembler podem ser úteis.

Existe também a chamada habilidade de engenharia reversa. Às vezes, pode ser bastante chato, às vezes interessante - uma história de detetive onde você investiga como um componente está conectado a outro, como tudo é feito dentro da biblioteca. Como resultado, verificou-se que o problema estava no tempo de execução da linguagem Objective-C.

A próxima habilidade importante é otimizar nossos aplicativos.



Os dispositivos móveis têm recursos limitados, portanto, geralmente há um problema de desempenho. Ao desenvolver, precisamos pensar em coisas como consumo de CPU. Na maioria das vezes, essa é a complexidade do código que você escreve. Velocidade de renderização, memória e tráfego de rede, porque a maioria dos usuários tem maior probabilidade de usar seu aplicativo no tráfego móvel. Vamos respeitar os usuários e talvez seja mútuo.

O quinto ponto é a bateria, segue dos quatro primeiros.

O mais importante ao otimizar aplicativos é identificar áreas problemáticas. Se você confiar apenas em suas suposições, é provável que perca muito tempo e não obtenha muito lucro. Isso ajudará as ferramentas da plataforma. Eles incluem um criador de perfil - um programa que mostra onde em seu código o programa passa mais tempo. Ou seja, você verá o método no qual seu programa trava com mais frequência e provavelmente encontrará o motivo do congelamento.

Conhecer os algoritmos e as estruturas de dados o ajudará a encontrar uma solução mais eficiente. Além disso, o conhecimento multithreading pode ajudar aqui. Atualmente, existem processadores com vários núcleos em dispositivos móveis e, paralelizando o problema em vários segmentos, você obtém um leve aumento de n vezes no desempenho.

Às vezes acontece que os dois primeiros pontos, infelizmente, não ajudam. Você será ajudado a entender como o sistema operacional funciona e o conhecimento de chamadas do sistema, como mapa de memória (mmap). No nosso caso, os teclados iOS de terceiros têm uma limitação no consumo de RAM - 52 megabytes. Ou seja, queremos adicionar recursos, criar uma interface de usuário bonita, mas limitados a 52 megabytes. O que fazer com isso não está claro.

Ao adicionar outro recurso, isso aconteceu. Muitas vezes começamos a exceder esse limite e não sabíamos o que fazer com ele. Como resultado, a chamada do sistema de mapa de memória foi resgatada. Pegamos um arquivo com um dicionário, de onde obtivemos todas as dicas e começamos a chamar o mapa da memória. Assim, trabalhamos com parte do arquivo sem carregá-lo completamente na RAM.

O último problema frequentemente encontrado é o horário de início. Aqui eu posso aconselhá-lo a ler o que acontece antes que seu código comece a funcionar. Em particular, sobre links estáticos e dinâmicos.



A última habilidade útil é a integração contínua ou a automação de tarefas chatas.

Ninguém gosta de fazer tarefas chatas, então apenas as automatizamos. Na maioria das vezes, a coisa mais simples é criar o aplicativo para cada confirmação que você fizer e, quanto mais você criar o aplicativo, mais rápido poderá encontrar o problema. Se você tiver testes, execute-os também.

Como eu disse, a publicação está associada a uma pequena burocracia, por isso também é muito automatizada, e você pode liberar o assembly no armazenamento beta para cada solicitação de pool, para que os testadores possam testá-la. Você também pode automatizar a geração de capturas de tela para a App Store, para não fazê-las manualmente.

Para todas as habilidades listadas, coletei materiais úteis.isso ajudará no estudo deles. Ele também contém o código fonte de uma versão simplificada do tradutor. Obrigado por sua atenção, espero que você tenha um pouco mais claro do que estudar para começar sua jornada.

Source: https://habr.com/ru/post/undefined/


All Articles