Компактность против производительности

Тут у меня дилемма возникла: какой МакБук Про лучше подходит для iOS разработки. Итак, в ассортименте:
— 13-дюймовые с Core i5 и 8ГБ RAM на борту.
— 15-дюймовые с Core i7 и 16ГБ RAM.

Невооруженным взглядом можно интуитивно догадаться, что второй вариант определенно производительней. Но при этом более громоздкий. Давайте разберемся стоит ли игра свеч и достаточно ли 13-дюймовых «прошек» для iOS разработки в наши дни.

Немного предыстории: у меня за всю мою деятельность iOS разрабом было две «прошки» и обе 13-дюймовые. Я люблю, когда ноутбук небольшого размера и веса. Удобно брать с собой практически везде. Первый из них уже отправился на покой, а второй живее всех живых. Он хоть и 2015 модельного года, но куплен только два года назад, поэтому довольно свеж и в хорошем состоянии.

Но, где-то с полгода тому назад, мне на работе выдали рабочую 15-дюймовую «прошку». И знаете, она мне прям очень понравилась. Но я хотел знать какой реально прирост производительности я получил вместе с ней. Ведь личные ощущения вроде «все стало быстрее» — крайне субъективны. А мы субъективным оценкам не верим. 🙂

Поэтому я решил взять оба ноутбука и сделать замеры времени компиляции/сборки/запуска тестов на одних и тех же проектах. Что у меня в итоге получилось? Давайте смотреть.

Начнем с исходных данных. У нас два ноутбука, с вот такими характеристиками:

И начнем замеры с какого-нибудь небольшого проекта. У меня как раз оказалось под рукой приложение на один экран и, приблизительно, десятью различными структурами данных (это немного). Для чистоты эксперимента, перед каждым замером я делал «Clean Build Folder». Посмотрим что у нас получилось по времени компиляции на каждом из ноутбуков.

13-дюймовый:

и 15-дюймовый:

Почти в два раза быстрее. Да, это не инкрементальная сборка, а «с нуля», но нам и важны не абсолютные цифры, а их соотношение.

Давайте возьмем проект побольше, и чтоб там юнит-тесты какие-нибудь были. Такой проект у меня тоже в закромах имеется. Сначала замеряем время компиляции.

13-дюймовый:

15-дюймовый:

Динамика сохраняется. Теперь запустим еще и тесты.

13-дюймовый, сборка:

выполнение тестов:

15-дюймовый, сборка:

тесты:

Видим очевидную закономерность. Но у меня припрятан еще один проект. Там очень много кодогенерации для тестов и самих тестов побольше, чем в предыдущем. Посмотрим что у нас там.

13-дюймовый, сборка:

тесты:

15-дюймовый, сборка:

и тесты:

Здесь видим интересный момент: время сборки стало одного порядка, при этом время самих тестов все еще отличается в два раза. Я перезапустил эти сборки еще раз и посмотрел логи. И основное время в обоих билдах как раз «съел» сам процесс кодогенерации, а потом компиляция этого сгенерированного кода. Что там такое генерируется? МОКи для юнит-тестов, конечно же. Там 23,5 тысячи строк сгенерированного кода. 🙂

И тут мне еще стало интересно: а какая загруженность системы по ресурсам во время вот такой вот длинной сборки? Я запустил Activity Monitor и начал наблюдать, периодически делая скриншоты на пиковых значениях.

Вот как выглядит загрузка оперативной памяти в 13-дюймовом:

А вот так в 15-дюймовом:

И тут есть один очень важный момент: в 15-дюймовом МакБуке значение «Memory Used» перевалило за 8ГБ. 13-дюймовая «прошка» просто физически не смогла бы выдать столько памяти в распоряжение.

А вот почему это важно: дело в том, что всё тестирование я проводил на только что перезагруженных ноутбуках, с выгруженными из памяти сторонними приложениями. Никаких скайпов, слаков, браузеров запущено не было. А ведь в обычном рабочем режиме эти все приложения у вас будут запущены, а значит на 13-дюймовом ноутбуке вы упретесь в потолок ресурсов. А вот в 15-дюймовом еще останется немного про запас.

После мониторинга памяти я решил еще помониторить и загрузку процессора. Вот самое высокое значение использования ресурсов на 13-дюймовом МакБуке:

Как видите, резерва совсем нет. Все загружено по максимуму. 😦

А вот пиковое для 15-дюймового:

Доступна еще почти половина ресурса.

Вот итоговый график по процессору 13-дюймового:

А вот для 15-дюймового:

Характеры графиков очень схожи: первая пиковая нагрузка приходится на момент генерации кода и компиляции сгенерированного, а вторая — на само выполнение юнит-тестов. Но у 15-дюймового МакБука остается еще неплохой резерв и для других приложений, которые могут быть запущены. А вот у 13-дюймовой «прошки» этого резерва совсем нет. 😦

Ну и в заключение, все таки, немного личных субъективных ощущений. Я думаю, что ошибался, считая 15-дюймовую «прошку» громоздкой. И по габаритам и по весу этот ноутбук имеет очень хорошие показатели. Когда я начал носить с собой «пятнашку» вместо «тринашки», я вообще не ощутил разницы в весе. Но тут нужно учесть, что я ношу рюкзак, а не сумку. Ну а размер — теперь это для меня скорее плюс, и вот почему: дело в том, что у 15-дюймового МакБука очень нифиговое такое разрешение экрана: 2880 x 1800 пикселей. Когда я пользовался 13-дюймовым, дополнительный монитор был моим неизменным спутником. А вот с 15-дюймовой «прошкой» во втором мониторе просто нет необходимости, ведь полезная площадь экрана самого ноутбука просто огромна. Еще не могу не упомянуть о батарее: в «пятнашках» она большей емкости. У меня после просмотра двух полнометражных фильмов остается еще от 20 до 35% заряда.

Xcode: наверное, лучший способ работы со сторибордами.

Этот пост является вольным переводом статьи Xcode: A Better Way to Deal with Storyboards by Stan Ostrovskiy

Некоторые примеры кода в оригинальной статье устарели (ввиду выхода Swift 3) и в переводе были изменены.

Советы и рекомендации по работе с Interface Builder.

Apple серьезно улучшили Interface Builder в новом Xcode 8. Использование size classes стало более интуитивным, возможность масштабирования сториборда — очень удобной, а полное превью прям в Interface Builder — просто великолепным. Для тех у кого были сомнения насчет использования Interface Builder, это может стать хорошими плюсами.

С другой стороны, у многих разработчиков все еще есть некоторые проблемы с Interface Builder когда они создают большие многоэкранные приложения со сложной навигацией.

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

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

В вашем проекте есть один файл main.storyboard, который выглядит вот так?

С точки зрения дизайнера, все хорошо: полностью видно UI и навигацию. И это именно то, для чего Interface Builder и был создан.

Но для разработчика это несет множество проблем:

  • Контроль версий: конфликты слияния сторибордов очень трудно решать, так что работа в отдельных сторибордах сделает жизнь вашей команды проще.
  • Файл сториборда становится объемным и в нем сложно ориентироваться. Как часто вы случайно меняли constraint кликом мышки не в том вью-контроллере?
  • Вам необходимо присваивать каждому вью-контроллеру свой storyboard ID и это может привести к ошибкам: вам нужно «хардкодить» этот ID каждый раз когда хотите использовать этот вью-контроллер в коде.

Как же связать различные сториборды в вашем проекте? Есть два способа.

  1. Используйте ссылки на сториборды (storyboard referencing), которые появились в Xcode 7.

  2. Связывайте сториборды непосредственно в коде.

О первом способе вы можете почитать детальнее здесь.

Я расскажу о втором способе, так как он широко используется для сложных проектов.

2. Используйте одни и те же имена для файла со сторибордом и для связанного класса контроллера (наследника UIViewController).

Это упростит правила именования, а также даст некоторые «плюшки» о которых поговорим в пункте 3.

3. Инициализируйте сториборд непосредственно в классе контроллера.

Когда дело доходит до инициализации вью-контроллера через сториборд, я часто вижу следующий код:

let storyboard = UIStoryboard(name: “Main”, bundle: nil)
let homeViewController = storyboard.instantiateViewController(withIdentifier: “HomeViewController”)

Немного «грязновато»: вам нужно назвать сториборд, вам нужен storyboard ID вью-контроллера, и вам необходимо использовать этот паттерн каждый раз, когда вы создаете HomeViewController.

Лучше перенести этот код в сам класс контроллера и использовать статический метод, чтоб инициализировать контроллер с помощью сториборда:

class HomeViewController: UIViewController { 
    static func storyboardInstance() -> HomeViewController? { 
        let storyboard = UIStoryboard(name: “HomeViewController”, bundle: nil)
        return storyboard.instantiateInitialViewController() as? HomeViewController    
    }
}

Если вы последуете предыдущему совету (одинаковые имена файлов), то можете избежать «харкода» имени сториборда и воспользоваться String(describing:):

let storyboard = UIStoryboard(name: String(describing: self), bundle: nil)

Убедитесь, что у файла сториборда такое же имя как и у класса контроллера. Иначе ваше приложение будет «крэшится» когда вы попытаетесь создать ссылку на такой сториборд.

Это делает ваш код более читаемым и отказоустойчивым:

class HomeViewController: UIViewController {
    static func storyboardInstance() -> HomeViewController? { 
        let storyboard = UIStoryboard(name: String(describing: self), bundle: nil)
        return storyboard.instantiateInitialViewController() as? HomeViewController 
    }
}

Если вы хотите иметь доступ к вью-контроллеру через instantiateInitialViewController() убедитесь, что вы указали этот вью-контроллер как initialViewController в Interface Builder. Если у вас несколько вью-контроллеров на одном сториборде, вам придется использовать instantiateViewController(withIdentifier: _ )

Теперь, инициализация такого вью-контроллера займет одну строку:

let homeViewController = HomeViewController.storyboardInstance()

Просто и понятно, не так ли?

Вы можете использовать этот же подход для инициализации вью из nib:

class LoginView: UIView {
    static func nibInstance() -> LoginView? {
        let nib = Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil)
        return nib?.first as? LoginView
    }
}
4. Не перегружайте свой проект переходами на сториборде.

У вас не будет переходов, если вы последуете совету из пункта 1. Но даже если у вас есть несколько вью-контроллеров в одном сториборде, использование переходов (segues) для навигации между ними — не очень хорошая идея:

  • Вам нужно дать имя каждому переходу (segue), что само по себе может привести к ошибкам. «Хардкодить» строки с именами — плохая практика.
  • Метод prepareForSegue будет просто нечитаем, когда вы будете работать в нем с несколькими segue, используя операторы ветвления if/else или switch.

Какова альтернатива? Когда вы хотите перейти к следующему вью-контроллеру по нажатию на кнопку, просто добавьте IBAction для этой кнопки и инициализируйте вью-контроллер в коде: это ведь всего одна строка, как вы помните из пункта 3.

@IBAction func didTapHomeButton(_ sender: AnyObject) {
    if let nextViewController = NextViewController.storyboardInstance() {
        // initialize all your class properties
        // nextViewController.property1 = … 
        // nextViewController.property2 = … 

        // either push or present the nextViewController,
        // depending on your navigation structure 
        // present(nextViewController, animated: true, completion: nil) 

        // or push  
        navigationController?.pushViewController(nextViewController, animated: true)
    }
}
5. Unwind segue? Не, не слышал.

Иногда навигация предполагает возврат пользователя к предыдущему экрану.

Очень распространенная ошибка: использовать новый переход для навигации к предыдущему вью-контроллеру. Такой переход создает новый экземпляр вью-контроллера, который уже находится в стэке, вместо того, чтоб убрать текущий вью-контроллер и таким образом вернуться к предыдущему.

Начиная с iOS 7, Interface Builder дает вам возможность сделать «unwind» навигационного стэка.

Unwind segue позволяет вам указать возврат на предыдущий экран. Это звучит довольно просто, но на практике это требует некоторых дополнительных действий и только сбивает с толку разработчика:

  • Обычно, когда вы создаете действие для кнопки (action), Interface Builder создаст для вас код (IBAction). В этом же случае, ожидается, что код уже написан до того, как вы зажмете «Ctrl» и перетащите действие от вашей кнопки к «Exit».
  • Обычно когда вы создаете действие для кнопки, код этого действия создается в том же классе, которому и принадлежит кнопка. Для Unwind Segues, вам нужно писать код в классе того вью-контроллера, в который этот переход произойдет.
  • Метод prepareForUnwind будет иметь все те же недостатки, что и метод prepareForSegue (см. предыдущий пункт).

Каков же более простой способ?

Проще делать это в коде: вместо создания действия «unwind» для вашей кнопки, создайте обычный IBAction и используйте dismissViewController или popViewController (в зависимости от вашей навигации):

@IBAction func didTapBackButton(_ sender: AnyObject) { 
    // if you use navigation controller, just pop ViewController:
    if let nvc = navigationController {   
        nvc.popViewController(animated: true)
    } else {
        // otherwise, dismiss it
        dismiss(animated: true, completion: nil)
    }
}

На сегодня это все. Я надеюсь, вы найдете что-то полезное для себя.

От переводчика:

Благодаря методу описанному в этой статье, я очень сильно упростил работу со сторибордами в своем текущем проекте Zumme. Пока я работал над ним один — все было прекрасно, но как только появились другие разработчики — работа со сторибордом превратилась в настоящий ад. От отчаянья мы практически перешли к «банановому методу» (можно почитать здесь в разделе «Pass the banana»).

Конечно же, в идеале нужно будет рано или поздно прийти к VIPER. Но об этом будет уже другой пост. 🙂

Как отметить свои TODO, FIXME и ERROR в Xcode.

Этот пост является вольным переводом статьи How to highlight your TODOs, FIXMEs, & ERRORs in Xcode by Hector Matos

Это был самый обычный день: я писал код, устранял баги и вообще все было прекрасно. Именно тогда я написал блок кода, к которому нужно было вернуться позже. Это обычный случай, с которым вы тоже вероятно сталкивались: нужно было взаимодействовать с API который еще не был готов. Я знал общую структуру объекта, который получу по API, но я еще не мог протестировать работу с ним. Как и любой другой разработчик, я написал комментарий, который выглядит так:

В этот момент я хотел бы создать предупреждение в Xcode, такое же как мы привыкли делать в Objective-C с помощью директив компилятора:

Но увы, так не получилось и я загрустил.

Как человек действия, я сделал то, что и следовало: я действовал. Оказывается вы можете добавить run-скрипт, чтоб получить необходимый функционал.

RUN SCRIPT BUILD PHASES

Xcode поддерживает внутренние bash-команды или скрипты в различных фазах вашего цикла разработки. Вы можете запустить bash-скрипт в любое время до или после сборки, запуска, тестирования, профилирования, анализа или даже архивирования!

Чтобы сделать это, перейдите в «Build Phases» своего проекта в Xcode, нажмите на «+» слева вверху и затем из выпадающего меню выберите «New Run Script Phase»:

Затем вы увидите новый раздел в котором можете написать bash-скрипт. Если вы уже эксперт по написанию Swift-скриптов после прочтения поста scripting in swift, вы можете просто положить файл со скриптом в корневой каталог проекта и вызвать его из своего нового run-скрипта.

# Отмечаем ваши TODO, FIXME и ERROR с помощью «родных» предупреждений Xcode

В тело вашего run-скрипта поместите вот этот замечательный код:

TAGS="TODO:|FIXME:"
find "${SRCROOT}" \( -name "*.h" -or -name "*.m" -or -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"

С этого момента вы будете видеть предупреждения когда поставите метку TODO: или FIXME: в комментарии! Посмотрите как работает эта магия:

Не будем останавливаться на достигнутом и исправим скрипт таким образом, чтобы подсвечивать ошибки используя //ERROR: в комментариях. Как вы знаете, бывают ситуации, когда мы хотим обратить особое внимание, выделив ошибку с помощью //ERROR:. Чтобы сделать это, измените ваш bash-скрипт вот так:

TAGS="TODO:|FIXME:"
ERRORTAG="ERROR:"
find "${SRCROOT}" \( -name "*.h" -or -name "*.m" -or -name "*.swift" \) -print0 | xargs -0 egrep --with-filename

Не знаю как вы, но я, наверное — самый забывчивый человек в мире. В конце дня у меня не всегда закончен текущий фрагмент кода и мне нравится использовать //ERROR: чтобы напомнить самому себе над чем работать завтра.

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

ЗАКЛЮЧЕНИЕ

В своей повседневной работе вы всегда столкнетесь с блоком кода, к которому нужно будет вернуться позже, но сейчас вы вынуждены поставить «заплатку» и двигаться дальше. К сожалению, даже простого //TODO:, //FIXME: или //ERROR: в комментарии, просто недостаточно. Вы удивитесь сколько людей забывают о своих //TODO:, //FIXME: и //ERROR: в проекте. Использование run-скрипта в этой ситуации — отличный способ, чтобы убедиться, что не упустите ничего в своем цикле разработки. Надеюсь это поможет!

Счастливого кодинга, товарищи ботаники!

П.С. Из комментариев к оригинальному посту извлечена еще одна модификация скрипта, на случай если вам все-таки нужно препятствовать сборке проекта при наличии пометок //ERROR: в коде:

TAGS="TODO:|FIXME:"
ERRORTAG="ERROR:"
OUTPUT=$(find "${SRCROOT}" \( -name "*.h" -or -name "*.m" -or -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$|($ERRORTAG).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/" | perl -p -e "s/($ERRORTAG)/ error: \$1/")
ECHO "$OUTPUT"

if [[ $OUTPUT == *" error: "* ]]
then
exit 1
fi

Genymotion — быстрые симуляторы для Андроид.

Раньше я писал об одной из основных причин почему я выбрал iOS, а не Андроид. И, честно говоря, я понимал, что ограничиться одной «ОСью» было бы ошибкой. Но каждый раз когда я пытался возобновить свои «отношения» с Андроид-студией, я натыкался на него — симулятор-эмулятор. Обычный «Hello, World!» никак не мог запуститься на стандартных мобильных эмуляторах Андроид-студии. Я все надеялся, на то, что должны же разработчики IDE услышать своих пользователей и решить эту проблему раз и навсегда, но решения все не было. До сегодняшнего дня.

Сегодня на одном из форумов по андроид разработке добрый человек по имени Иван написал всего одно слово. И слово это было — «Genymotion». Я уже натыкался на него ранее, но никак не мог выбрать время, чтоб прочитать и разобраться что это и как это работает. И вот сегодня все прояснилось.

Genymotion — это быстрые симуляторы для Андроида. Чтобы ими воспользоваться нужно зайти сюда: https://www.genymotion.com
На сайте нужно зарегистрироваться (это понадобится потом для установки симуляторов различных устройств). Сами симуляторы бесплатны для некоммерческого использования, поэтому вы полностью остаетесь в легальном поле всего за ноль долларов и ноль центов ровно.

В дополнение к genymotion вам понадобится VirtualBox: https://www.virtualbox.org/wiki/Downloads (без него симуляторы не запустятся).

Первое впечатление от использования: Вау! Я могу писать приложения для Андроид! Я могу проходить уроки, выполнять домашние задания, рисовать интерфейсы и смотреть как это все работает на разных устройствах с разными экранами.

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

Поэтому, если вы хотели что-то написать под Андроид, но вам мешала эта проблема — теперь вы знаете как ее решить.

Заряжаем Xcode.

Этот пост является вольным переводом статьи Xcode, Supercharged.

Для нас, как инженеров, очень важно привыкнуть к инструментам, которые мы используем в работе каждый день, но никогда не стоит останавливаться на их изучении. Всегда найдутся скрытые возможности, которые помогают нам работать быстрее и концентрироваться на цели, а не на средствах ее достижения. Я покажу некоторые «фишки», которые обнаружил за время своей работы в среде разработки Xcode. Надеюсь, они и вам пригодятся.

1. Ctrl + цифры

В Xcode есть быстрая навигация по всему проекту: от корневого каталога до файлов и методов в них. Просто нажмите Ctrl + цифры от 1 до 6 и сами увидите. В появляющихся окнах также работает поиск.

2. «Фишки» брэйкпоинтов

Брэйкпоинты — прекрасны. Их тоже можно «зарядить». Вы знали, что можете выполнять LLVM-комманды и даже воспроизводить алерты при срабатывании брэйкпоинта? Причем вы можете комбинировать это с беспрерывным выполнением (когда вам нужно понять, что метод вызывается, но не нужно останавливать приложение).

3. Нечеткий поиск где угодно

Не можете вспомнить где видели что-то в коде? В Xcode есть нечеткий поиск по всему проекту — Cmd+Shift+O. Ключевой момент именно в нечеткости: если результатов поиска слишком много — просто продолжайте печатать пока не найдете то что ищете.

4. Редактирование в области видимости (in Scope)

Поставьте курсор на имя метода или переменной и нажмите Cmd+Ctrl+E. Обратите внимание как выделено каждое упоминание этого слова. Достаточно изменить это имя один раз и Xcode изменит его везде в классе, в котором оно используется. Этим очень удобно пользоваться, когда вам нужно быстро переименовать какую-то переменную или метод. Также это работает для локальных переменных в их областях видимости. Это особенно удобно, когда вы дали название свойству/методу, а потом передумали.

5. camelCase выделение

Эта «фишка» отлично работает в сочетании с предыдущей. В Xcode можно быстро выделять camelCase-текст с помощью Ctrl+Shift+стрелка вправо/влево. Вы просто быстро выделяете слова в названии переменной. Это очень удобно. Обратите внимание, что это может конфликтовать с настройками системы, особенно с переключением между рабочими областями в OS X.

6. Простое переключение между кодом и навигатором

Хотите быстро переключиться из редактора в навигатор файлов? Cmd+Shift+J и вы уже там. Хотите обратно в редактор? И чтоб не тянуться к мышке или трекпаду? Пожалуйста: Cmd+J. Бонусом к этому идет быстрый поиск файлов в навигаторе. Просто нажмите Cmd+Option(Alt)+J.

7. Брэйкпоинты на переменных

Поставьте брэйкпоинт на строку с объявлением переменной и Xcode будет там останавливаться каждый раз когда значение переменной изменяется (на самом деле, в данном примере брэйкпоинт срабатывает, потому что в этой же строке описан метод didSet(…) {…}).

8. Быстро перейти к определению

Вы ведь нажимали Cmd и кликали мышкой по названию переменной или метода, чтоб разобраться что это такое? Поставьте курсор в текст и нажмите Cmd+Ctrl+J. Это также работает и для ваших собственных определений.

9. Различия с последнего коммита

Кому нужны сторонние git-инструменты, если можно посмотреть различия прям внутри Xcode? Cmd+Shift+Alt+Enter(Return).

10. Быстрая работа с брэйкпоинтами

Нажмите Cmd+\ чтоб поставить или убрать брэйкпоинт в строке в которой находится курсор. Также можете использовать Cmd+Y чтоб включать-выключать брэйкпоинты во всем проекте.

Эти комбинации клавиш стали частью моей повседневной работы и помогли ускорить написание кода и внесения изменений. Если же какая-то из этих комбинаций конфликтует с другой настройкой, которую вы сделали раньше, вы всегда можете их изменить. Просто нажмите Cmd+,(запятая) и зайдите в «Key Bindings». Удачного вам фаст-программинга!

Objective-C. Курс для начинающего.

Есть очень клевый парень Алексей Скутаренко. Он живет в штатах, и периодически выкладывает уроки по разработке для iOS.

Для начала, рекомендую посмотреть два его видеоурока по ОПП. Дело в том, что Алексей объясняет довольно быстро и, лучше сначала посмотреть что-нибудь более-менее простое в его исполнении, чтоб привыкнуть к скорости и стилю изложения (тогда все последующие видео будут восприниматься лучше).

А вот и сам курс по Objective-C для «бегиннеров». Наслаждайтесь:

Прототипы.

Перед тем как садиться непосредственно за программинг вашего супер-пупер-мега приложения, я бы очень советовал накидать его эскизы, они же мокапы (от англ. mockup). Хотя, по большому счету, программист со стажем, запросто может такой эскиз «накидать» в самом XCode.

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

Я честно пытался рисовать карандашом в блокноте, но художник из меня так себе, поэтому я регулярно пользуюсь сервисом NinjaMock. Сервис очень удобный, есть множество уже готовых элементов интерфейса, которые нужно «сложить» на «экран» и вуаля.

Сервис условно-бесплатный. Абсолютно все функции доступны в бесплатном варианте, есть только ограничение по количеству проектов — их может быть не больше трех.

Хотите узнать больше про него? Как всегда, исчерпывающая статья на «Хабре» ждет вас: https://habrahabr.ru/company/ninjamock/blog/208406/