Perguntas da entrevista BAT iOS

7b38e7b9a795ae7571df7773da4ab36e.webp

Perguntas da entrevista relacionadas ao tempo de execução

1. O que é Runtime?

Como o nome conhece o seu significado, o conceito nada mais é do que "porque Objective-C é uma linguagem dinâmica, então ela precisa de um sistema runtime ... este é o sistema runtime". Para um novato como um blogueiro, o Runtime é, na verdade, um conjunto de funções da linguagem C em desenvolvimento real. Hu Shi disse: "Pesquise mais perguntas e fale menos sobre ideologia". É sempre fácil ficar tonto ao ouvir o conceito de Yunshan Mist. A seguir, vamos diretamente para o mapa mental de tempo de execução para ajudá-lo a esclarecer seu pensamento:

936371a8037ac48c778069b99d64595a.webp

2. O que acontece quando objc envia uma mensagem a um objeto?

Quando objc envia uma mensagem para um objeto, o tempo de execução encontrará a classe à qual o objeto realmente pertence de acordo com o ponteiro isa do objeto e, em seguida, procurará o método a ser executado na lista de métodos da classe e na lista de métodos de sua classe pai, se a classe raiz não tiver Find it, vá para a chamada de interceptação, siga o mecanismo de encaminhamento de mensagem e, uma vez que a encontre, execute sua implementação IMP.

3. O que acontece quando uma mensagem é enviada para um objeto nil em objc?

Se você enviar uma mensagem para um objeto nulo, primeiro o endereço 0 é retornado ao procurar o ponteiro isa do objeto, portanto, nenhum erro ocorrerá. Não entrará em colapso.

4. Qual é a relação entre o envio de uma mensagem para um objeto em objc [obj foo] e a função objc_msgSend ()?

Quando objc é compilado, [obj foo] será convertido em: objc_msgSend (obj, @selector (foo)) ;.

5. Quando a exceção do seletor não reconhecido será relatada?

Quando objc envia uma mensagem para um objeto, a biblioteca de tempo de execução encontrará a classe à qual o objeto realmente pertence de acordo com o ponteiro isa do objeto e, em seguida, procurará o método a ser executado na lista de métodos da classe e na lista de métodos de sua classe pai. Se, na classe superior Se o método correspondente ainda não for encontrado na classe pai, ele entrará no estágio de encaminhamento de mensagem. Se o processo de encaminhamento de mensagem três vezes ainda não for implementado, o programa desligará e lança um seletor de exceção não reconhecido enviado para XXX quando ele é executado.

6. Você pode adicionar variáveis ​​de instância à classe compilada? Posso adicionar variáveis ​​de instância a uma classe criada em tempo de execução? porque?

Não é possível adicionar variáveis ​​de instância à classe compilada;

Capacidade de adicionar variáveis ​​de instância a classes criadas em tempo de execução;

1. Como a classe compilada foi registrada no tempo de execução, a lista vinculada da variável de instância objc_ivar_list na estrutura da classe e o tamanho da memória da variável de instância instance_size foram determinados, e o tempo de execução chamará class_setvarlayout ou class_setWeaklvarLayout para lidar com forte fraco referências. Portanto, não pode existir Adicionar variáveis ​​de instância à classe.
2. A classe criada em tempo de execução pode adicionar variáveis ​​de instância e chamar a função class_addIvar, mas depois de chamar objc_allocateClassPair e antes de objc_registerClassPair, o motivo é o mesmo acima.

7. Depois de adicionar um atributo à classe, quais elementos serão alterados na estrutura da classe?

instance_size: o tamanho da memória da instância; objc_ivar_list * ivars: lista de atributos

8. O que o indicador isa de um objeto objc aponta? qual é o efeito?

Aponte para seu objeto de classe, para que você possa encontrar o método no objeto. A classe (classe) Root é na verdade NSObject, NSObject não tem superclasse, então a superclasse da classe (classe) Root aponta para nil.

Cada classe tem um ponteiro isa para a única classe Meta cla *** oot class (meta) pontos de superclasse para a classe Root (classe), ou seja, NSObject, formando um loop. O ponteiro isa de cada classe Meta aponta para a classe Root (meta).

9. Como o tempo de execução encontra o endereço IMP correspondente por meio do seletor?

Cada objeto de classe tem uma lista de métodos. A lista de métodos registra o nome do método, a implementação do método e o tipo de parâmetro. Na verdade, o seletor é essencialmente o nome do método. Por meio desse nome do método, você pode encontrar a implementação do método correspondente no lista de métodos.

10. O que a função _objc_msgForward faz e o que acontecerá se você chamá-la diretamente?

_objc_msgForward é um tipo de IMP usado para encaminhamento de mensagens: quando uma mensagem é enviada a um objeto, mas não está implementada, _objc_msgForward tentará encaminhar a mensagem.

11. Como o tempo de execução realiza a configuração automática de variáveis ​​fracas para zero? Você conhece o SideTable?

O tempo de execução apresentará as classes registradas e colocará os objetos modificados de maneira fraca em uma tabela hash.

Use o endereço de memória do objeto apontado por fraco como a chave. Quando a contagem de referência deste objeto for 0, ele será desalocado. Se o endereço de memória do objeto apontado por fraco for a, ele usará um como o Pesquise na tabela fraca e encontre todos O objeto fraco com a como chave é, portanto, definido como nulo.

Uma resposta mais detalhada:

1. Inicialização: o  tempo de execução chamará a função objc_initWeak para inicializar um novo ponteiro fraco para o endereço do objeto.

2. Ao adicionar uma referência: A  função objc_initWeak chamará a função objc_storeWeak (). A função de objc_storeWeak () é atualizar o ponteiro para criar a tabela de referência fraca correspondente.
3. Ao liberar, chame a função clearDeallocating.

A função clearDeallocating primeiro obtém uma matriz de todos os endereços de ponteiro fraco de acordo com o endereço do objeto, então atravessa a matriz e define os dados nela como nulo, finalmente exclui a entrada da tabela fraca e finalmente limpa o registro do objeto. A estrutura SideTable é responsável pela tabela de contagem de referência e tabela fraca da classe de gerenciamento,

12. O objeto associado ao método Associate em tempo de execução precisa ser liberado quando o objeto principal é desalocado?

Não é exigido pelo MRC ou ARC. Os objetos associados são liberados muito depois do próprio objeto no ciclo de vida. Eles serão liberados no método object_dispose () chamado por NSObject -dealloc. ** Explicação detalhada: **

1. Liberação de chamada:

      A contagem de referência torna-se zero. O objeto está sendo destruído e seu ciclo de vida está prestes a terminar. Não pode haver novas __ referências fracas fracas, caso contrário, ele apontará para nulo. Chame [auto-desalocação] ** 2. ** A classe pai chama -dealloc O relacionamento mais herdado Herda diretamente a classe pai e, em seguida, chama -dealloc. Se for o código MRC, ele liberará manualmente as variáveis ​​de instância (iVars). Cada classe pai no relacionamento de herança chamará -dealloc ** 3 . ** NSObject ajustar -dealloc apenas fazer uma coisa: chamar o método object_dispose () no tempo de execução Objective-C

4. Chame object_dispose () para as variáveis ​​de instância C ++ (iVars), chame os construtores para as variáveis ​​de instância (iVars) no estado ARC, chame -release, libere todos os objetos associados ao método Associate em tempo de execução, libere todas as referências __weak, chame gratuitamente()

13. O que é método swizzling (comumente conhecido como magia negra)

  Simplificando, significa trocar métodos e chamar um método em Objective-C. Na verdade, é enviar uma mensagem para um objeto. A única base para encontrar uma mensagem é o nome do seletor. 

  Utilizando as características dinâmicas do Objective-C, pode-se perceber que o método correspondente ao seletor pode ser alterado em tempo de execução para atingir o objetivo de enganchar o método. 

  Cada classe tem uma lista de métodos, que armazena o nome do método e a relação de mapeamento entre a implementação do método. A essência do seletor é, na verdade, o nome do método. IMP é um pouco como um ponteiro de função, apontando para uma implementação de Método específica, e o IMP correspondente pode ser encontrado através do seletor. Várias maneiras de alterar o método Use method_exchangeImplementations para trocar a implementação de dois métodos Use class_replaceMethod para substituir a implementação do método Use method_setImplementation para definir diretamente o IMP de um método

Perguntas da entrevista relacionadas a multithreading

Multithreading é um método relativamente leve para implementar vários caminhos de execução de código em um único aplicativo. Do ponto de vista técnico, um thread é uma combinação de estruturas de dados no nível do kernel e no nível do aplicativo que precisam gerenciar a execução do código.

cc20d05623a35eb7bce6a57512ef1526.webp

1. Quais são as características das várias tecnologias multi-threading fornecidas pelo sistema iOS?

GCD 、 NSOperation 、 NSThread。

GCD : Sincronização simples entre threads, incluindo envio de sub-thread, vários cenários de leitura e gravação única.

NSOperation : O framework de terceiros AF e SD envolverá NSOperation.Ele pode controlar o status das tarefas, adicionar dependências e excluir dependências.

NSThread : Realiza o tópico residente.

Perguntas da entrevista relacionadas ao RunLoop

Acredito que a maioria dos desenvolvedores, como o runloop, se confunde com o runloop, a princípio eles só entendem que podem fazer algumas coisas através da notificação de alguns eventos de monitoramento do runloop para otimizar a performance. Para o conhecimento básico do código-fonte do runloop, você pode consultar o seguinte mapa mental:

44b34f283b39c7a59e23dc2963fb95a3.webp

Processo de execução RunLoop

02c6d27a5feff9f9c324bd9f08e32999.webp

没有事情的时候,Runloop处于休眠状态。当外部source将其唤醒后,它会依次处理接收到的timer/source,然后再次进入休眠。

1.Runloop和线程是什么关系?

每条线程都有唯一的一个与之对应的RunLoop对象;

主线程的RunLoop已经自动创建,子线程的RunLoop需要主动创建;

RunLoop在第一次获取时创建,在线程结束时销毁

2.Runloop的mode作用是什么?

指定事件在运行循环中的优先级的,

线程的运行需要不同的模式,去响应各种不同的事件,去处理不同情境模式。(比如可以优化tableview的时候可以设置UITrackingRunLoopMode下不进行一些操作,比如设置图片等。)

3.以+scheduledTimerWithTimeInterval:的方式触发的timer,在滑动页面上的列表时,timer会暂停回调, 为什么?

滑动scrollView时,主线程的RunLoop会切换到UITrackingRunLoopMode这个Mode,执行的也是UITrackingRunLoopMode下的任务(Mode中的item),而timer是添加在NSDefaultRunLoopMode下的,所以timer任务并不会执行,只有当UITrackingRunLoopMode的任务执行完毕,runloop切换到NSDefaultRunLoopMode后,才会继续执行timer。

4.如何解决在滑动页面上的列表时,timer会暂停回调?

将Timer放到NSRunLoopCommonModes中执行即可

5.NSTImer使用时需要注意什么?

注意timer添加到runloop时应该设置为什么mode

注意timer在不需要时,一定要调用invalidate方法使定时器失效,否则得不到释放

设计模式相关面试问题

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

41b42119a72fb072ff10c271edbfde51.webp

架构/框架相关面试问题

“100个读者就有100个哈姆雷特”一样,对于架构的理解不同的软件工程师有不同的看法。架构设计往往是一个权衡的过程,每一个架构设计者都要考虑到各个因素,比如团队成员的技术水平、具体的业务场景、项目的成长阶段和开发周期。下图是小编的一些架构理念,仅供参考:

f3b3dba5c66481f86d4010515dd817f3.webp

1.RAC中使用时线程问题?或者RAC的缺点?

2.RAC中实现多个信号全部执行结束再执行与 多个信号任意一个结束就响应的处理方式?

3.路由跳转的实现方式 ?

算法相关面试问题

6ac8b96325f64b11ca56a30498880785.webp

1.对以下一组数据进行降序排序(冒泡排序)。“24,17,85,13,9,54,76,45,5,63”

int main(int argc, char *argv[]) {int array[10] = {24, 17, 85, 13, 9, 54, 76, 45, 5, 63};int num = sizeof(array)/sizeof(int);for(int i = 0; i < num-1; i++) {for(int j = 0; j < num - 1 - i; j++) {if(array[j] < array[j+1]) {int tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;}}}for(int i = 0; i < num; i++) {printf("%d", array[i]);if(i == num-1) {printf("\n");}else {printf(" ");}}}

2.对以下一组数据进行升序排序(选择排序)。“86, 37, 56, 29, 92, 73, 15, 63, 30, 8”

void sort(int a[],int n){
    int i, j, index;
    for(i = 0; i < n - 1; i++) {
        index = i;
        for(j = i + 1; j < n; j++) {
            if(a[index] > a[j]) {
                index = j;
            }
        }
        if(index != i) {
            int temp = a[i];
            a[i] = a[index];
            a[index] = temp;
        }
    }}int main(int argc, const char * argv[]) {
    int numArr[10] = {86, 37, 56, 29, 92, 73, 15, 63, 30, 8};
    sort(numArr, 10);
    for (int i = 0; i < 10; i++) {
        printf("%d, ", numArr[i]);
    }
    printf("\n");
    return 0;}

3.实现二分查找算法(编程语言不限)

int bsearchWithoutRecursion(int array[],int low,int high,int target) {while(low <= high) {int mid = (low + high) / 2;if(array[mid] > target)high = mid - 1;else if(array[mid] < target)low = mid + 1;else  //findthetargetreturn mid;}//the array does not contain the targetreturn -1;}----------------------------------------递归实现int binary_search(const int arr[],int low,int high,int key){int mid=low + (high - low) / 2;if(low > high)return -1;else{if(arr[mid] == key)return mid;else if(arr[mid] > key)return binary_search(arr, low, mid-1, key);elsereturn binary_search(arr, mid+1, high, key);}}

4.如何实现链表翻转(链表逆序)?

#include <stdio.h>#include <stdlib.h>typedef struct NODE {
    struct NODE *next;
    int num;}node;node *createLinkList(int length) {
    if (length <= 0) {
        return NULL;
    }
    node *head,*p,*q;
    int number = 1;
    head = (node *)malloc(sizeof(node));
    head->num = 1;
    head->next = head;
    p = q = head;
    while (++number <= length) {
        p = (node *)malloc(sizeof(node));
        p->num = number;
        p->next = NULL;
        q->next = p;
        q = p;
    }
    return head;}void printLinkList(node *head) {
    if (head == NULL) {
        return;
    }
    node *p = head;
    while (p) {
        printf("%d ", p->num);
        p = p -> next;
    }
    printf("\n");}node *reverseFunc1(node *head) {
    if (head == NULL) {
        return head;
    }
    node *p,*q;
    p = head;
    q = NULL;
    while (p) {
        node *pNext = p -> next;
        p -> next = q;
        q = p;
        p = pNext;
    }
    return q;}int main(int argc, const char * argv[]) {
    node *head = createLinkList(7);
    if (head) {
        printLinkList(head);
        nó * reHead = reverseFunc1 (cabeça); 
        printLinkList (reHead); 
        livre (reHead); 
    } 
    livre (cabeça); 
    return 0;}

Entrevistas com perguntas relacionadas a bibliotecas de terceiros

bac6acb9d9d1787f7794cb5ab9b7cfc3.webp

Fonte: https://mp.weixin.qq.com/s/LZf1As0RJEksnIynjGUXGw


Acho que você gosta

Origin blog.51cto.com/15010671/2658195
Recomendado
Clasificación