Что должен знать objc разработчик на уровень middle/senior?
К сожалению, четкой черты на вертикальное развитие нет. Парадокс, но чтобы знать что изучить, нужно знать что ты не знаешь.
Я постарался вспомнить самые интересные вопросы, которые мне задавали самому на различных собеседованиях, а так же расширил их множеством вопросов(тем же уровнем) от себя.
Здесь нет общих вопросов вроде: IoC, design patterns, S.O.L.I.D. и т.п.

ВНИМАНИЕ!!!
Помимо вертикального развития немаловажно и горизонтальное

ВНИМАНИЕ!!! (2)
Не пишите в комментарии ответы на вопросы, это дает возможность людям самостоятельно разобраться.
Однако, если у вас имеются интересные вопросы по теме, я с радостью добавлю их в список.

Конечно, это не заменит живого общения, однако позволит неплохо подготовиться к собеседованиям.


Начинаем



что такое void *?
а что означает просто void?

в чем разница между void * и id?

что такое id?
как определен id?
можно ли создать структуру и привести к id?

id vs instancetype

что значит root класс?
можно ли создать свой root класс?
какие есть еще root классы кроме NSObject и NSProxy?

можно ли использовать NSObject вместо NSProxy?
если ответ «да», то зачем тогда нужен NSProxy?

как происходит выравнивание указателей на объекты в objc?
с чем это связано?
какие оптимизации с этим связаны при хранении данных?
почему нельзя делать свою реализацию?

что такое bridge и зачем это нужно?

все эти методы допустимы? если нет то какие и почему?
- (instancetype)initMyObj {
    self = nil;
    return self;
}

- (instancetype)initmyObj {
    self = nil;
    return self;
}

- (instancetype)myObj {
    self = nil;
    return self;
}


что такое мета-класс?

objc_msgSend, что это за функция?
как это связано с [obj foo]? какие еще есть связанные функции?

что такое dispatch table?

как происходит отправка сообщения?
всегда ли сообщения отправляются с одинаковой скоростью?

что будет если метод не найден в dispatch table?

есть ли в objc приватные методы?
как протестировать метод, не объявленный в публичном интерфейсе

exception отправки сообщения, кто выбрасывает?
что такое NSInvocation. Привести пример использования

что такое swizzling?

можно ли сделать private ivar как property, через категорию?
какие проблемы могут быть?
как в категории сделать свою property?

target-action, передается селектор, как сделать так, чтобы по селектору был вызван не метод, а блок?

что такое селектор?

что такое блок?
какие типы блоков бывают?
от какого класса наследуются?

всегда ли использование self внутри блока означает retain cycle?

почему внутри блока используется неявное const?

как работает __block?

как происходит вызов блока?

внутри блока используется assert, какие проблемы возникают?
как их устранить без выделения в отдельный метод?

что такое assert и когда использовать?

что такое __autoreleasing?

что такое autorelease pool?

что такое run loop?

как связаны NSTimer и run loop?
как запустить таймер на отдельном потоке?
что будет если запустить таймер и держать UIScrollView?
как это исправить?

как связаны run loop и autorelease pool?

почему в этом коде утечка памяти и как устранить?
        NSString *str;
        while (YES) {
            str = [NSString stringWithFormat:@"hello world"];
        }

какие типы управления памятью есть в objc?

garbage collection vs reference counting?

отличия ARC от MRC?
как работает ARC? магически определяет когда удалять объект?
напишите реализацию сеттера на MRC

чем отличается weak от strong и почему так много runtime функций для этого?

почему weak невозможно использовать на некоторых классах?
на каких именно?
как быть в этом случае?

ARC, как работает dealloc?
когда расставляются release сообщения для ivar?

причина выполнения true ветки? причина выполнения false ветки? от чего зависит результат?
        BOOL b = 1024;
        if (b) {
            NSLog(@"true");
        } else {
            NSLog(@"false");
        }

одинаковую ли память занимают эти структуры и почему так?
struct StructA {
    int32_t a;
    char b;
    char c;
};

struct StructB {
    char b;
    int32_t a;
    char c;
};

что такое union?

а сколько памяти занимают эти структура и что это вообще такое?
struct Value1 {
    int32_t foo:12;
    int32_t foo1:4;
    int32_t foo2:6;
    int32_t foo3:10;
};

struct Value2 {
    int32_t foo;
    int32_t foo1;
    int32_t foo2;
    int32_t foo3;
};


что такое volatile?

что такое inline функции?

в чем отличие потока от процесса?

NSThread vs pthread

сокет, как это связано с вопросами выше?
tcp, udp когда что применять?

гонка потоков, методы синхронизации, защита критической секции, семафор, мьютекс, барьер, что это и зачем нужно?
что такое OSSpinLock?

как передавать данные между NSOperation?
когда операция отправленная в NSOperationQueue начинает выполняться, можно ли отложить выполнение?

как тестировать асинхронные методы?
как написать синхронную обертку для асинхронного метода?

что такое стек вызовов и как это работает?
в чем отличие стека от кучи?
int8_t matrix[2048][2024], допустимо ли?

рекурсивные функции и хвостовая рекурсия, любая ли рекурсия может быть хвостовой?

что происходит со счетчиком ссылок когда объект добавляется в array, dictionary, set?
если нужно другое поведение, что использовать?
можно ли узнать, какой объект сколько раз был добавлен в set? (bag)

как использовать свой класс как ключ?

в чем плюсы использования immutable?
в чем минусы?
зачем нужен атрибут copy для property и какую проблему решает?

почему и как работает KVC?
key-path, хаки для коллекций

зачем нужен NSMapTable, какие отличия от NSHashTable

проблемы при работе с KVO и как это все работает

frame, bounds, center, как все это между собой связано?
как изменятся свойства, если применить поворот на 45??
как передвинуть все subviews на 3 pt вверх и влево?

отличие view от layer?

responder принцип работы
как отправить сообщение по responder chain?

как работают категории?
в какой момент происходит влияние на классы?
что будет если категории пересекутся?
зачем у категории есть имя?

зачем нужен NSCache? В чем от реализации кэша на NSDictionary?
поддерживает ли NSURLConnection протокол HTTP/2?

какая типизация у objc? Сильная/слабая, явная/не явная, статическая/динамическая?
в чем отличие QoS User-interactive и user-initiated?
в чем отличие nil/Nil/NULL/NSNull?
________

Еще раз, не пишите ответы на вопросы в комментариях. Статья не для того, чтобы люди просто прочитали вопрос-ответ, а нашли ответ самостоятельно и попутно разобрались.

Статья написана совместно с complexityclass

Комментарии (21)


  1. dirtyHabrBobr
    01.01.2016 02:38

    Кто сделает (challenge) аналог для Swift?


  1. IrinaInina
    01.01.2016 09:55
    +3

    Здесь ещё подборка: habrahabr.ru/post/198612
    И на гитхабе: gist.github.com/arthurigberdin/3a078212ee3f347a4ff5
    И немного заданий от Яндекса: yandex.ru/jobs/vacancies/dev/mobile_objc_dev
    И ещё чудесный пост, в которых лейтмотивом идёт первый вопрос по первой ссылке: megamozg.ru/post/7256


  1. kostyl
    01.01.2016 23:59
    +5

    Прикол в том, что тысячи людей пишут успешные приложения, приносящие кучу денег, и не знают большинства ответов на эти вопросы, и никогда не будут разбираться в этих вопросах, будут сидеть и пить мартини в своём личном бунгало где-нибудь на острове и ничего не делать… а другие будут изучать это всё и так и пойдут на пенсию…


    1. PapaBubaDiop
      02.01.2016 00:33
      +5

      Будут изучать этот бред и потеряют время. Вce равно, что водителя раллийных гонок спросить — сколько кулачков и эксцентриков на распредвале? Или чему равно g(же) на Земле?

      Мне больше по душе подход Шерлока Холмса, который стирал из памяти любые факты и знания, мешающие решению задачи.

      Что до вопросов на собеседовании, да прошел я давеча собеседование. Мне задали один вопрос
      -Вы пишете на Swift?
      -Нет.
      -Why?
      -It is not stable.
      -Sure. — согласился интервьювер и через месяц я получил оффер. Вот сижу теперь, раздумываю…


      1. Krypt
        02.01.2016 18:10

        У меня складывается такое впечатление, что смысле не в правильном ответе на эти вопросы, а в том, КАК человек на них ответит.
        Например, в фирме, где я сейчас работаю, в тестовые задания ошибки вставляют специально.


    1. DmitrySpb79
      02.01.2016 20:19
      +1

      Прикол в том, что _принято_ спрашивать подобные вопросы на собеседованиях, так что просто надо быть готовым и да, «изучать этот бред». Да, это часть игры, но если возьмут не Вас а «другого парня», Вам от этого легче не будет.

      Если же программист в состоянии создать собственный проект, достаточный для личного бунгало на личном острове, то ему и собеседования не нужны, но я лично таких не знаю.


  1. zip_zero
    02.01.2016 01:16

    Давайте тогда нагуглим (и выдадим) ответы на каждый вопрос, раз это так просто и насущно.


  1. Krypt
    02.01.2016 18:01
    +2

    > почему в этом коде утечка памяти и как устранить?
    Здесь используется arc?
    Если да, то утечки памяти здесь нет.

    В общем часть вопросов выглядят так, как будто они пришли из времён iPhone OS 3.0


    1. ajjnix
      02.01.2016 18:08

      утечка все таки в этом случае не самое подходящее слово, но память будет забиваться (да, здесь используется arc)
      prntscr.com/9l89py


      1. Krypt
        02.01.2016 18:15

        Да, пожалуй, потом я тоже подумал о том, что здесь могут возникнуть проблемы c работой ARC из-за того, что поток никогда не будет освобождён. Точного механизма его работы я не знаю, только общие принципы.
        Но расход памяти здесь — далеко не самая главная проблема :)


        1. ajjnix
          02.01.2016 18:55

          не спорю, код не боевой :D
          но проблема может быть устранена если знать причину и даже с бесконечным циклом
          p.s. если цикл завершиться, то память будет освобождена, но не сразу


          1. creker
            02.01.2016 19:07

            Я бы сказал, что как раз боевой. В больших циклах, где много работы с памятью, этот пример очень важен для понимания. Иначе можно стать заложником out of memory. До ARC эта проблема была очевиднее, поэтому взял за правило оборачивать особо критичные места в свой autorelease pool.

            Еще более насущные примеры, когда приложение реализовано через бесконечно цикл, которые работает на всем протяжении жизни приложения, что редко, но все таки бывает.


            1. ajjnix
              02.01.2016 19:13

              речь о «не боевом» именно о этом куске кода
              остальные вопросы не пиши только ответы) а то не удобно будет перед людьми, которые будут такие вопросы задавать
              одно дело когда люди прочитают, загорятся и найдут и еще многое по ходу поиска изучат, а другое дело за пару минут прочитают именно как сам ответ и забьют


              1. creker
                02.01.2016 19:22

                Извиняюсь. Вроде внизу все в спойлеры обернул, а тут проскользнуло


        1. creker
          02.01.2016 19:06
          +1

          Если кто не хочет, то но читайте

          ответ
          Проблема тут в том, что ARC это не что-то новое, а это те самые release/retain. В буквально смысле они. Если открыть в дизассемблере бинарник, то там будут вставлены эти самые вызовы как если бы их вставил программист. И суть проблемы в том, что ARC никак не устраняет механизма autorelease pool и вообще это две не связанные между собой вещи. Конструктор
          stringWithFormat
          добавляет объект в этот пул как это обычно делается в таких случаях, поэтому в этом цикле память не будет освобождаться и будет бесконечно расти. Понятное дело почему — объекты в пуле освобождаются только в момент освобождения пула. Если тело цикла обернуть в
          @autoreleasepool

          то проблема будет решена. Точно так же, как это было до ARC, потому что механизм работы с памятью никак не поменялся с тех пор. Опять же, открыть в дизассемблере ARC код и там будут почти теже самые autorelease pool.

          Проблема так же будет решена, если использовать связку alloc и init методов. В этом случае пул не используется, а значит ARC вставит вызовы для освобождения памяти внутри тела цикла.

          Поэтому ARC и полностью совместим со старым кодом — он не меняет правила игры.


          1. Krypt
            02.01.2016 19:11
            -1

            Ну, тут вопрос в том, как именно ARC расставит вызовы. Если бы он релизил объекты при присваивании (как это делалось в setter'ах в non-arc) — то утечки памяти всё равно не было бы.


            1. creker
              02.01.2016 19:19
              +1

              Заголовок спойлера
              ARC тут никак не поможет. Он скорее всего в теле цикла все вставляет правильно — ref count + 1 при объявлении переменной, ref count -1 в конце цикла. Но пул то свою ссылку держит и никуда не отдаст, пока его не освободишь, а значит объект будет жив. Если ты переменной присваиваешь иное значение (nil, чтобы намеренно освободить объект), то ARC тоже вставляет release — не освобождает, а понижает счетчик ссылок. И до ARC все работало точно так же. Ничего абсолютно не поменялось в механизмах работы с памятью. Единственное реальное новшество это weak переменные разве что.


              1. Krypt
                02.01.2016 19:23

                Не совсем согласен
                В non-arc объект уничтожается незамедлительно после того, как referenceCount становится равным нулю. То есть, если бы вместо autorelease вызывался бы release — autorelease pool бы не использовался и утечки бы не было бы.


                1. creker
                  02.01.2016 19:41
                  +1

                  Заголовок спойлера
                  А как в ARC работает? Точно так же — когда счетчик до нуля доходит, тогда и освобождается объект. Но в примере то он не доходит до нуля и все из-за пула. Мне не понятно уже, с чем вы не согласны. ARC работает так же, как работает программист, когда использует старую модель. Ровно ноль отличий. Раньше советовали же осторожно работать с autorelease переменными — они копятся и не освобождаются, память может кончиться. Есть только два решения — не использовать пул или обернуть код в еще один пул, который бы освобождался на каждой итерации. Все это справедливо и сейчас, пулы никуда не делись. По идее, их можно было бы вообще убрать, не будь у нас старого кода, который от них зависит.

                  То есть, если бы вместо autorelease вызывался бы release — autorelease pool бы не использовался и утечки бы не было бы.

                  Вы видимо хотели что-то другое сказать. В примере autorelease вызывается ровно один раз — внутри конструктора. Вызов на этом месте release привел бы к нехорошим последствиям.

                  Вообще, единственный случай, который я знаю, когда именно ARC вставляет autorelease вызовы, это при работе с указателями на указатель. В ином случае все происходит детерминировано и так, как вы описали — дошел счетчик до нуля и тут же освободилось все.


                  1. Krypt
                    02.01.2016 20:07

                    Невнимательность - наше всё...
                    Прочитал код как [[NSString alloc] initWithString@«hello world»];
                    Ну а дальше я предполагал, что ARC оперирует областями видимости. Как только объект выходит из области видимости — у него вызывается release.

                    Вот так:

                    NSString *str;
                    while (YES) {
                    [string release];
                    str = [[NSString alloc] initWithFormat:@«hello world»];
                    }

                    Кстати, надо бы проверить, как ARC поведёт себя в случае с [[NSObject alloc] init]. К сожалению, сейчас нет Мака под рукой.


  1. Krypt
    02.01.2016 18:26

    Вообще — неплохой чеклист по знаниям. Надо бы почитать про работу ARC с блоками что-нибудь, остальное не критично.