• Telegram. Безлимитный сетевой диск. Бесплатный
    +2
    Автор молодец: ) Я тут сделал что-то похожее, но без телеграмма. Я сам заинтересовался историей создания удобного удаленного хранилища. Однако от FUSE пришлось частично отказаться по следующим (субъективным) причинам:

    1. Я не вижу ни одного проекта на FUSE, который я мог бы назвать стабильным и шустрым, к сожалению. NTFS-3G яркий тому пример, ведь в его разработку вложено великое множество человекочасов совсем не глупых людей. И, тем не менее, показатели производительности этого решения сильно отстают от других, проприетарных, имплементаций (не основанных на FUSE).

    2. Корректная имплементация файловой системы это сложно. Нет, правда. Первая итерация выходит очень быстро, но потом практика показывает, что работы впереди непочатый край.

    Возможно я не прав и если это так — буду рад примерам FS.

    Можно использовать FUSE для того, чтобы предоставить ОС образ, который она может смонтировать и отформатировать в обычную ФС, имлементация и кеши которой живут в ядре. Такой способ позволяет избежать необходимости имплементировать какое бы то ни было подобие файловой системы и дает возможность сосредоточиться на жонглировании блоками + из коробки fsck и поддержка extended attributes.

    Чтобы блоки, которых нужно ждать, не тормозили IO соседей, ОС через fuse отдается не .dmg а .sparsebundle. В моем случае бекендом служит яндекс диск. Сейчас диск в тестовом режиме на 180гб забит исходниками всякого рода, видео и игрушками. Кеш на локальном диске пытается удержаться в заданных пределах (20гб) и в памяти (2гб), LRU. +Readahead в 2 блока. 1блок — 8мб (надо меньше, 1мб делать). Локально данные сжимаются snappy и сохраняются в badger, удаленные блоки сжимаются зипом (8).

    Подход позволил играть в игрушки со steam без какого либо дискомфорта, кроме продолжительных загрузочных экранов, и смотреть видео с возможностью перемотки без ожидания дозагрузки. И впереди еще много работы. И самое главное — избавиться от FUSE полностью.

    Почему у нас нет Block device in User SpacE? Ближайшее — nbd, linux-only и в неизвестном состоянии.

    Перформанс
    image


  • Монорепозитории: пожалуйста, не надо (часть 2)
    0
    Не могу плюсовать, карма зло.

    Да, хорошо, т.е неудобства появляются, когда древо зависимостей имеет глубину больше двух. Принято. Это основное неудобство в приведенной ситуации?
  • Монорепозитории: пожалуйста, не надо (часть 2)
    0
    А все же, почему количество воспринимается как что-то, зависящее от количества разработчиков и что-то, несущее накладные расходы в принципе?

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

    А потом возьмем и разобьем все это дело на 21 репозиторий. В первом — основной код, и вот таких вот 20 либ. Чтобы ими пользоваться используется просто местный менеджер зависимостей для вашего ЯП — go mod, cocoapods, npm, cargo, вот эти ребята.

    Где конкретно здесь появляются неудобства и дискомфорт? И как они изменяются при изменении количества реп с 1 до 100?
  • GraphQL — новый взгляд на API. Ч.1
    0
    Не обязательно. В некоторых компаниях между сервисами общение происходит по RPC, отличному от http/rest. А их, помимо grpc, великое множество. Просадка имеется не в производительности, а в latency. И это на больших масштабах вполне приемлемая цена за масштабируемость.
  • DockStation. Почему мы решили сделать этот проект
    0
    Две недели назад начал делать тоже самое, удивляясь, что этого никто еще не сделал, и все UI для докера практически бесполезны, да и заходить в них приходится через браузер (с ума все посходили с этим вебом). Я так понимаю проект был на веб стеке собран, на каком-нибудь electron? Печально, что это единственный сегодня существующий способ. Тем не менее, огромное спасибо за ваши старания, это очень круто! /me пошел выкидывать свое поделие в корзину и наслаждаться свободным временем
  • Монады для Go-программистов
    +1
    Вы ставите общительность в претензию каждому своему собеседнику?

    К сожалению, в go это не работает. И не очень ясно хорошо это, или нет. PR'ы и просто предложения разворачиваются на месте, потому что они противоречат религиозным убеждениям core team. Как противоположность — swift. Я не люблю swift, но там, в отличии от go, имеет смысл вкладывать силы и время. Их changelog каждый год впечатляет, и все это делает комюнити. Это круто.
  • Монады для Go-программистов
    0
    Все правильно говорите. Все, что я хотел, это выразить мнение, что язык вынуждает разработчиков страдать, а предоставляемый им альтернативный вариант, по большей части, не применим. Соответственно остается только хотябы на уровне IDE схлопывать бойлерплейт. Не понимаю, что Вам тут было смешно. Это грустно.

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

    func connect(addr string) (*connection, error) {
    	con, err := db.Connect(addr)
    	if err != nil {
    		return nil, err
    	}
    
    	err = prepare(con)
    	if err != nil {
    		con.Close()
    		return nil, err
    	}
    
    	return con, nil
    }
    


    Ошибка в нем следующая: если prepare() вывалится с паникой, коннект утечет (кто сказал, что fd закрывается в файналайзере?). Городить ли defer с recover? Наверное не городить. Месяца через три петух на продакшене хорошо прожарится и наточит клюв.

    Всего этого безобразия можно было бы избежать, если бы ошибки были бы частью языка, а паник как понятия не существовало:

    func connect(addr string) *connection {
    	con := db.Connect(addr)
    	onError con.Close()
    
    	prepare(con)
    
    	return con
    }
    


    Не положил в переменную — эквивалентно старой доброй мантре. У всех функций неявное последнее возвращаемое значение — ошибка. onError == defer с проверкой на err != nil. Остается единственный вопрос со стектрейсом, но собственно и все.

    Но нет. Мы будем страдать. Спасибо google.
  • Монады для Go-программистов
    0
    Почему же тогда никто их не использует, наоборот, все радостно пишут эту мантру, и ругают за паники? =)
  • Монады для Go-программистов
    +3
    На обработку ошибок «плевать» в более чем 90% случаев. Случаи обработки конкретных ошибок крайне редки. Как часто вы при попытке вставить что либо в бд проверяете на конкретную ошибку о существовании записи и делаете в таком случае что-то другое? Обычно вы просто чистите за собой, куданибудь вываливаете это в лог и все.

    Выпад про синие экраны смерти тут некорректен. Язык действительно тебя заставляет либо как идиоту писать после каждой 1 строчки мантру из 4 строк, либо использовать паники. Но в последнем случае тебя Go-сообщество справедливо закидает заранее подготовленным и свеже-подогретым говном. Вот сидим, пишем эту хреноту, да себя и всех вокруг убеждаем, что это хорошо.
  • Монады для Go-программистов
    +4
    Потому что на 3 строчки полезного кода 12 строк iferr!=nil{returnerr}\n мантры. Это бессмысленная трата времени разработчика на печатание и затем на чтение всего этого бойлерплейта. Если их схлопывать, то хоть как-то это можно читать.
  • Монады для Go-программистов
    0
    Если вас сильно раздражает проверка на if err!=nil, то в Gogland уже давно впилен мой патч, скрывающий их нафиг. image
  • Что нового нас ждет в Swift 4?
    0
    Извините за некропостинг, но… «Ключи пути»? Серьезно?
  • Про похудение с точки зрения химика. Как я перепрограммировал свой организм
    0
    Любопытно. Я не считал, но что-то мне подсказывает, что закон сохранения энергии здесь надо учитывать с одной маленькой оговоркой: усваиваемость и скорость обмена веществ. Я знаю людей, которые едят столько, что в меня не влезло бы, при этом весят 50 и не могут набрать.

    Я пил от 3 до 5 литров чистой воды, жрал раз 6 в день, в основном овощи и курица, чаще всего просто брал ролл в subway с курицей-беконом без соусов. В зал ходил три раза в неделю, через день, обычные занятия (одна большая, одна малая группа мышц), только они начинались с 20-40 минут элипса на износ, чтобы сжечь глюкозу в ноль. Ну и чтобы со всего этого не слететь, не отказывал себе, если очень хотелось пиццу или шоколадку и не считал это проколом.

    В итоге подтянулся, живот пропал, все как заказывали. Just fucking do it, и получай удовольствие. Все это дело продержалось где-то год, потом стал обратно толстеть, похудел на 8кг, это продержалось пол года, и вот сейчас активно идет дубль три. Почему-то гораздо хуже, чем раньше, но видимо 4 года разницы дают знать, хз.
  • Про похудение с точки зрения химика. Как я перепрограммировал свой организм
    0
    Блин. Серьезно? Он потерял 28кг за больше чем полгода, не ел и долго ходил, а я на 20 за 1.5 месяца (89->69), и жрал каждые два часа, вкусно. И иногда даже пиццы с конфетками. WTF?
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    1. Очевидно, с чего взяли? Я сказал, открываем менюшку и делаем констрейнты.
    2. Очевидно, с чего взяли? По поводу button — а что это изменит?
    3. А вот этого не знал.

    И я тоже самое сделал, что вы написали — я весь интерфейс сделал в IB, а цвета по условию должны рождаться из кода, следовательно нужны IBOutlet.

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

    Т.е я не согласен с утверждением, что любой разработчик сразу поймет проект по сториборду и частично не согласен, что не поймет код — единственная сторонняя библиотека тут это KeepLayout. Можно открыть их страницу гитхаба и один раз прочитать. Констрейнты везде одинаковые и несут один и тот же смысл. Опять же, в следствии малого обьема получается как-то не серьезно. Мы всетаки разработчики, а не индусы, это наша работа шевелить мозгами. Разница лишь в том, на сколько адекватно то, над чем тебе приходится думать, и на сколько усилия соответствуют получаемому результату. Зашарить маленькую обертку над оригинальным AutoLayout займет совсем ничего, а результат — возможность не вылазить из кода и делать интерфейс быстрее и проще, нежели двигать мышкой.
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    Смотря в какой плоскости. Если совсем абстрагироваться от IB, то UI относительно текстового интерфейса можно и нужно считать прогрессом в плоскости связанной с UX: в большинстве случаев обычному пользователю гораздо проще как-то интуитивно найти нужную кнопку в панели управления (e.g. windows), нежели какой-то там конфиг файл (e.g. linux). Т.е. новичку, особенно далекому от IT, гораздо проще освоить некое графическое представление интерфейса, нежели текстовое. Однако конфиг файлы до сих пор существуют и повсеместно используются, и как причину такого состояния дел я вижу не лень больших компаний сделать UI для своих продуктов, например баз данных, а тот (для меня) факт, что разработчики — не обычные пользователи и им гораздо проще работать с текстом, кодом, нежели искать заветные галочки в дебрях интерфейса. Да, в общем случае для этого нужно много знать и приходится много гуглить, это сильный минус, который покрывается позднее скоростью выполнения работы и лучшим контролем.

    Например, что проще, зайти в панель управления -> установка/удаление программ -> найти в списке нужную, нажать на удалить и появившемся wizard еще пару раз нажать на next (как аналог можно рассмотреть упрощенные пакетные менеджеры убунты), или просто вбить в терминал `sudo pacman -R packetName`? В данной ситуации скорость очевидно за вторым вариантом, а больший контроль проявляется как только вы хотите удалить программу и все ее зависимости, или же хотите наоборот оставить зависимости на месте: в интерфейсе этого просто не выведено в упрощенных пакетных менеджерах (ведь от этого страдает UX, иначе зачем изобретать велосипед и заменять популярный и мощный Synaptic в убунту) и в windows не подразумевается возможным, а через терминал `sudo pacman -Rs packetName`. Контроль в большинстве случаев остается за вторым вариантом (оспорить или доказать это утверждение весьма проблематично, однако мне оно кажется очевидным), а его минусом остается тот факт, что пользователь должен знать, что такое sudo, pacman и аргументы последнего. Однако я не считаю, что в случае с UI работа, которую человек должен затратить на то, чтобы пройти весь путь по интерфейсу до получения желаемого результата равна нулю. Я утверждаю, что программистам проще и быстрее разобраться с консольными интерфейсами и конфиг файлами, нежели искать галочки в интерфейсе, потому что для того, чтобы интерфейс удовлетворял всем «нестандартным» потребностям, с которыми неминуемо сталкиваешься при разработке ПО, его приходится изрядно перегрузить.

    Возвращаясь к IB, предлагаю провести аналогию и рассмотреть конкретный пример. Допустим я хочу на экране два прямоугольника размером 100х100 и 50х35, цвет каждого прямоугольника зависит от третьих факторов (например рандом), один в правом верхнем углу, другой слева слева снизу. Первый с учетом margin'ов, второй без. При этом я не хочу, чтобы при недостатке места они пересекались, более того пересекались значения координат их точек: ни одна точка первого прямоугольника не должна быть правее ни одной точки второго, аналогично для вертикали (это упрощение, а не усложнение). Уменьшаться должен, при недостатке места, первый прямоугольник. Экран этот должен быть под UINavigationController и нажатие на любой из этих прямоугольников должно вызывать пуш каких-то других экранов в зависимости от третьих факторов (т.е переход не детерминирован на этапе компиляции). Поехали. В дальнейших рассуждениях подсчет времени, затрачиваемого на каждое действие, оставляю за вами. Все максимально минималистично и просто.

    IB:
    Находим и перетаскиваем UINavigationController, идем в соответствующую вкладку и назначаем его как стартовый. Аналогично перетаскиваем UIViewController и связываем их. Ищем кастум вью, перетаскиваем два инстанса. Выделяем одну из вьюшек, кликаем по кнопке констрейнтов снизу и выставляем соответствующие констрейнты: фиксированные размеры и отступы друг от друга (с последним может возникнуть проблема, ведь если добавить еще одну вью между ними, то IB будет предлагать выставить отступы именно от нее, а не от нужного прямоугольника, ведь она будет ближайшей, и нужно будет (?) идти во вкладку инспектора и делать это там). Далее создаем segue (один или два? А можно ли сделать segue и не указывать destination?) для каждого прямоугольника, либо же IBAction в контроллере, для чего потребуется переключиться на код. Коль уже переключились, допишем еще IBOutlet'ы в контроллер и свяжем их с вьюшками. Не забудем попросить IB обновить представление вьюшек, чтобы убедиться, что они правильно расставлены.

    Далее уже в коде во -viewWillAppear выставляем нужные цвета прямоугольникам через оутлеты, и либо в -prepareForSegue или в методах IBAction дописываем пуш на нужный контроллер. Кажется ничего не забыл.

    Code only:
    AppDelegate.m, в application:didFinishLoading:
    ```
    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[MyViewController new]];
    [window makeKeyAndVisible];
    _window = window;
    ```

    В MyViewController.m:
    В viewDidLoad:
    ```
    UIView *first = [UIView new];
    first.backgroundColor = ...;
    [first addGestureRecognizer:[[UITapGestureRecognizer alloc] recogrnizerWithTarget:self selector:@selector(firstTap:)]];
    [self.view addSubview:first];
    _first = first;

    UIView *second = [UIView new];
    second.backgroundColor = ...;
    [second addGestureRecognizer:[[UITapGestureRecognizer alloc] recogrnizerWithTarget:self selector:@selector(secondTap:)]];
    [self.view addSubview:second];
    _second = second;
    ```

    В updateConstraints:
    ```
    _first.keepTopMarginInset.equal = 0;
    _first.keepRightMarginInset.equal = 0;
    [_first keepSize:CGSizeMake(100,100) withPriority:KeepHigh];

    _second.keepTopOffsetTo(_first).min = 0
    _second.keepLeftOffsetTo(_first).min = 0;
    _second.keepBottomInset.equal = 0;
    _second.keepLeftInset.equal = 0;
    [_second keepSizeTo:CGSizeMake(50,35)];
    ```

    Ну и совершенно аналогично с IB в случае с IBAction код пуша соответствующего экрана. Вы действительно считаете, что вариант с IB сделать быстрее? Этот код можно спокойно печатать даже без подсказок и других инструментов, в частности автоматических import'ов и созданий ivar'ов в AppCode (то, что в xcode писать код тяжело похоже никогда не изменится) и гораздо быстрее, чем двигать мышкой по IB в поисках нужных вещей. А с подсказками, особенно fuzzysearch, когда IDE буквально все пишет за тебя — это делается еще быстрее. Плюс этот код легче поддерживать и менять, ведь все, что происходит, находится перед глазами и не скрыто в панельках IB.

  • Xcode: наверное, лучший способ работы со сторибордами
    0
    Демагогия: Вы приравняли использование IB к прогрессу (инструменты построения интерфейса существуют уже очень давно) и сослались на то, что если прогресс это хорошо, то IB тоже.

    Так же вы приравняли расстановку view в коде к безобразию без аргументации. Делегирование к устаревшему подходу (подходу к решению какой конкретно проблемы?) аналогично. Почему, кстати, тогда UITableView все еще на делегатах, а не на блоках? Делегирование до появления блоков использовалось для решения всех проблем обратной связи между обьектами, и не для всех оно подходило. Блоки решили этот вопрос. Использовать блоки для всего и вся такой же моветон, как использовать делегирование аналогичным образом.

    Создание предполагается делать в -init у view, а расстановку в -updateConstraints. Никакой вермишели, как раз наоборот: создание и расстановка четко разделены и при этом не так далеко, чтобы приходилось бегать из IB в код и обратно, и при изменении одного менять другое. А логика вся остается в VC и никак не пересекается с созданием и расстановкой вьюшек. Какие конкретно минусы в этом подходе?
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    Советую KeepLayout. Задача всех этих оберток — предоставить синтаксический сахар и только.

    В anchors нужно писать вот так
    ```
    [_myView.bottomAnchor constraintEqualToAnchor:_view.topAnchor constant:8.0].active = YES;
    ````

    в KeepLayout вот так

    ```
    _myView.keepTopInset.equal = 8;
    ```
    если я правильно понял, что делает anchors в этом коде (скорее всего нет :) ).
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    Красивее и правильней создать отдельную сущность для получения и сортировки, она будет тестируема, да, но это сделает кодовую базу сложнее, чего стоит избегать. Если экран большой и содержит в себе очень много логики — возможно да, имеет смысл озаботиться вопросом. Если приложение security-sensitive и тестирование необходимо — тоже. Нужно лишь понимать, что ничто в этом мире не бесплатно и чем больше в коде движущихся частей, тем труднее с ним работать и иногда лучше придерживаться политики, что твой код после тебя будет поддерживать джуниор, и он должен быть максимально прост для понимания и внесения изменений.
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    На первый взгляд логично, но спорно. Паттерн MVC, как его предоставляет нам Apple, к сожалению толкает разработчиков выносить логику из модели в контроллер. Вопрос тестирования начинает гореть синими пламенем в этот момент и да, в общем случае действительно лучше сопротивляться и выносить все в модель. Но у медали есть обратная сторона: в результате таких действий, если логики на самом деле мало, можно легко нарушить принцип KISS, получить большое количество сущностей и абстракций там, где необходимости в этом никакой нет, и следующий после вас разработчик потратит слишком много времени для того, чтобы разобраться в устройстве проекта. Например если вся суть экрана — загрузить список треков с сервера, отсортировать и показать, то вопрос показа стоит вынести во вью (сделать ему property NSArray<PRXTrack*>* tracks), вопрос сортировки оставить в контроллере, как и получение данных, оставить в контроллере. Контроллер вызывает дата менеджер, который вызывает сервер менеджер, получает данные, мэпит и возвращает обратно.
  • Xcode: наверное, лучший способ работы со сторибордами
    +2
    Это плюс, но разве он оправдывает минусы? Тем более, что всегда можно запустить симулятор и посмотреть в живую. Это не так удобно, с одной стороны, с другой стоимость сторибордов для такой простой вещи оказывается слишком велика, нужны какие-то еще плюсы, чтобы ее оправдать. А с учетом инжектов без перекомпиляции/перезапуска плюс совсем меркнет.
  • Xcode: наверное, лучший способ работы со сторибордами
    +1
    Я согласен с тем, что описанный подход улучшает ситуацию. Но это не отвечает на вопрос, который я задал: зачем нужны сториборды вообще? Зачем нужно поддерживать какую-то дополнительную сущность, при работе с которой требуется быть очень осторожным, тратить так много времени на разброску констрейнтов и атрибутов контролов мышкой, заниматься копипастой, пробрасывать IBOutlet'ы и прочая прочая?
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    Уточню. Совсем. Никаких .storyboard, никаких .xib, никакого interface builder, никогда. Я не видел ни одного проекта за шесть лет опыта с IB, который был бы действительно хорошо написан. С .xib — да, было, но .storyboard — всегда ад. Даже если по сториборде на экран.

    Давайте честно. Зачем нужны сториборды вообще? Вот альтернативный подход, критикуйте:
    На каждый экран свой контроллер, и свой подкласс UIView. Весь лейаут и взаимодействие с пользователем — во вью, вся бизнесс логика — в контроллере. Контроллер пинает вью напрямую, вью — через протокол делегирования. Лейаут — через обертки аутолейаута по вкусу (KeepLayout), код в -updateContraints. Для ускорения процесса разработки — dyci или аналог (нажал хоткей — изменения в коде инжектировались и экран обновился).

    Вот накипело уже. От IB одна только головная боль и толпы радостных индусов, размахивающих очередным новым способом не увязнуть в дебрях IB, продолжая использовать IB. Мыши плакали, кололись, но продолжали жрать кактус. Приходишь собеседоваться в большую серьезную компанию, а они пол года ваяют приложение и никуда оно не движется. Смотришь, код вроде бы нормальный, разработчики толковые и адекватные, а в сторибордах очередной срач, IBDesignable падает и не работает, все в каких-то страшных Segue и черт ногу сломает. Зато MVVC, IB, Swift, ага. Вам шашечки или ехать? Надоело переписывать за другими разрабами проекты. Нет, с одной стороны мне за это платят зарплаты, но с другой разобраться в этой дикой вермишели порой бывает без бутылки не возможно и нервы не резиновые.
  • Xcode: наверное, лучший способ работы со сторибордами
    0
    А еще лучше просто не использовать сториборды вообще.
  • Пол Грэм: Иная сторона «шедевров в срок»
    0
    Real artists ship — настоящие художники доставляют.
    Дословный перевод тоже не плохой, пусть и теряет смысл про сроки)
  • VPN везде и всюду: IPsec без L2TP со strongSwan
    0
    Так и не удается настроить по статье. Получаю neagent[58163]: Received error: Error (Authentication Failed) на OS X и iOS.

    Не ясно, как сервер понимает, что пользователь «свой». Просто глядя на то, что его сертификат подписан тем же CA, чьи ключи указаны в ipsec.secrets?

    Не ясно куда копать. Вроде бы все рекомендации и инструкции учел. Только вот dns имени нет, указывал везде и всюду вместо него IP адрес…
  • Null, великий и ужасный
    0
    Кстати, волею судеб вынужден работать с C#. Вопрос к тем, кому скучно и он долистал до дна коментариев:
    Как в С# симулировать поведение obj-c:
    ```
    Class1 a = obj1.method1().method2()
    ```
    В а должен оказаться null, даже если obj1 == null или obj1.method1() == null? Это какое-то издевательство бегать и ловить эти null'ы. Эквивалентный код:

    ```
    Class1 a = null;
    if (obj1 != null && obj1.method1() != null) { a = obj1.method1() }
    ```
  • Null, великий и ужасный
    0
    Ну да, и мне интересен ответ на вопрос «а зачем так сделали?». Вон Swift сейчас с этими оптционалами городит. И зачем оно? А если меня устраивает null повсюду? А если в выражении `var firstCarIsRed = (containers.cars.firstObject.color == red)` меня не волнует, что containers == null / cars.count = 0? А если в 90% кода ситуация аналогичная? Моя мысль в том, что писать код гораздо проще несколько с другой стороны: проще требовать не-нулл в тех местах, где это важно, чем повсеместно проверять на null везде, чтобы оно не упало.
  • Null, великий и ужасный
    –1
    В Obj-C
    ```
    (null).anyMethod == 0/null
    ```
    и никаких nullReferenceException.

    Это было чуть ли не идеальное решение.

    > Обрабатывать это исключение бесполезно: оно означает безусловную ошибку в коде.

    Что? Нет! Ну как, конечно если язык падает при доступе к такой переменной и заставляет ее всячески обворачивать то да, ошибка. А так — нет. И никаких лишних движений.
  • Работа мечты или небольшая история мобильной разработки
    0
    Больше всего понравился самый первый скриншот, прототип :)
  • Весёлые табы в MAC OS X или история про тот самый Tab View
    0
    Все хейтят IB потому что люди не умеют его готовить и строят громадные приложения в одной сториборде, а потом за ними переписывай.

    И я заказчику накодю что угодно, и даже не буду ждать перекомпиляции проекта — хоткей и в симуляторе интерфейс перестроился. Если писать без обертки на чистом AL, то это действительно дольше, чем в IB.

    AL без оберток очень плохо читаем.
    iOS разработка != java dev != c++ dev. Тут другие правила и по факту 50 зависимостей в cocoapods гораздо лучше, чем свои решения и на практике проблем с ними не возникает. Есть непоправленная бага в стороннем проекте — форкни, поправь, в поде выставь ссылку на свой git, profit. Pull request не забыть сделать. Это гораздо быстрее, чем делать что либо самому. Потом на ваше место прийдет другой разработчик, и ему в этом всем разбираться.

    А собственно ответьте на свой вопрос сами: а зачем? Чтобы понимать? Ясен перец нужно, а еще?

  • Весёлые табы в MAC OS X или история про тот самый Tab View
    +1
    Добро пожаловать на борт.
    Не используйте InterfaceBuilder. Он принесет больше боли, чем пользы. На всех платформах боль от использования средств создания интерфейса графическим путем примерно одинакова, но в случае ios/osx интерфейс эпически просто создавать из кода благодаря оберткам над AutoLayout (использовать его в чистом виде это как пить чистый спирт, не надо).

    https://github.com/Tricertops/KeepLayout

    Добавление Вашего таб бара бы выглядело в методе -loadView следующим образом:

    ```
    MMTabBarView *tabBar = [MMTabBarView new];
    tabBar.foo = bar; // тут выставляем всякие параметры
    [view addSubview:tabBar];
    tabBar.keepTopInset.equal = 0;
    tabBar.keepHorizontalInsets.equal = 0;
    tabBar.keepHeight.equal = 20; // Опционально, если автор не указал стандартный размер через -intrinsicContentSize
    _tabBarIvar = tabBar;
    ```

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

    И еще: AppCode, Cocoapods.

    Happy coding! ^_^
  • До чего доводит идея (Objective-C) — target-action на блоках и много рантайма
    0
    Принято :) Не заметил.

    Кстати, у Вас в структуре block ABI ошибка, на самом деле она выглядит вот так
    struct ASPBlockDescriptor
    {
    __unused unsigned long int reserved;
    __unused unsigned long int size;
    union
    {
    struct
    {
    __unused void (*copy_helper)(void *dst, void *src);
    __unused void (*dispose_helper)(void *src);
    const char *copy_dispose_signature;
    };

    const char *usual_signature;
    };
    };

    Документация is out of date, информацию о реальной имплементации можно найти в исходниках llvm. Разница не принципиальная, и так и так работает, но просто на заметку.

    Попробуйте фана ради решить такую задачу: сделать возможным замену методов у конкретного инстанса класса с вызовом оригинальной имплементации перед\до. Например

    [object injectAfter:@selector(someMethod:) withBlock:^(id _s, ArgType arg){}];


    Блок должен быть вызван в этом примере после отработки оригинальной имплементации и при этом с теми же аргументами. Решение готовое уже есть на гитхабе, можете поискать, но оно использует NSInvocation и, по сему, невероятно медленное (о чем говорит их дока и мой опыт). Однако инструмент очень полезен: можно, например, очень быстро распихать аналитику по всему приложению, не вставляя злосчастные вызовы логинга эвентов посреди бизнес логики или UI.

    Нужно сделать без использования NSInvocation. Эта задача мне кажется интересней и сложнее. Все здорово, покуда можно использовать NSInvocation. А вот без него? :) (PS: как видно в примере, _s не убирается и не требуется: у Вас узкий кейс с лямбдами, а эта задача о другом и self часто нужен)
  • До чего доводит идея (Objective-C) — target-action на блоках и много рантайма
    0
    Сам имею аналогичное решение, похожее на анонимные классы в джаве:

    tableView.datasource = [ASPDelegate delegate:^(ASPDynamicDelegate* delegate){

    [delegate addSelector:@selector(tableView:numberOfRowsInSection:) withBlock:^NSUInteger(id _s, NSTableView *tv, NSUInteger section){
    return 10;
    }]

    }];


    И только для того, чтобы избавиться от id _s, вы решили прибегнуть к такому огромному количеству приседаний и использованию NSInvocation? Why?
  • Реализуем свой dropDown ViewController (aka iOS 8 Mail app) в 200 строк
    0
    О боже. Method swizzling это следствие всей прелести obj-c runtime и каждый разраб должен уметь готовить его с закрытыми глазами.
    Оверрайд с помощью категорий это UB.

    Т.е вместо того, чтобы поймать за шкирку контейнер вью и заменить класс в рантайме на нужный подкласс с таким пропускным поведением, Вы решили воспользоваться Undefined Behavior и поменять поведение hitTest во всех UIView.

    О какой черной коробке вообще может идти речь, если она модифицирует метод во всей системе?

    PS: Apple не банит и никогда не банила за использование функций obj-c runtime, откуда Вы это взяли.
  • Objective-C: как работают блоки
    0
    Blocks ABI опушен, а это самый сок. Тема не раскрыта :) ведь блоки нужны для того, чтобы их вызывать, а как они вызываются вы не описали.

    ЗЫ: советую помимо документации силанга посмотреть исходники, там больше информации можно почерпнуть.
  • Дизайним прототипы ячеек в одном XIB-е с UITableView
    +3
    Статья рассказывает о двух (имхо — совершенно) не связанных задачах и их так же не связанных решениях. Думаю было бы лучше разобрать что-то одно, но очень подробно, в техническом плане: не просто, куда нажать, чтобы заработало, а глубокий экскурс в то, как это вообще работает.

    Пояснение:
    Я не пользуюсь сторибордами, ксибами и строю весь интерфейс на аутолейауте с помощью KeepLayout. Сторонник мнения, что сториборды — зло. По этому вопросы могут показаться странными.

    Вопросы:
    1. Почему не реализовать нужные клетки в отдельных ксибах, по старинке, и просто зарегистрировать нужные классы так же, как вы делаете в статье? Кода, как либо связанного с IBOutletCollection не будет, и клетки могут быть использованы в разных контроллерах, без какой-либо привязки к сторибордам.

    2. Что значит
    И тут мы сталкиваемся с проблемой, что прототипы ячеек для таблицы придется класть во внешние Xib-ы, причем по одному в файл, и явно регистрировать их в коде. После использования Storyboard совсем не хочется так делать.
    ? Вы же именно это и делаете, регистрируете каждый по отдельности, только создаете ксибу для целого вью контроллера. А если клетки используются в разных контроллерах? Таким образом вы жестко привязали клетки к классу контроллера, но с теоретической стороны связи быть не должно и потребуются дополнительные телодвижения для того, чтобы позже это исправить, плюс вы уже совершили больше телодвижений, чем можно было для достижение цели строить интерфейс графически.

    3. Что значит
    Теперь таблица может работать, как будто ее загрузили из Storyboard.
    ? В чем отличие поведения UITableView, созданной в сториборде, от онной, созданной в коде?

    4.
    - (NSArray*)cellPrototypes { return nil; } //Чтобы не было warning-a
    
    Серьезно? Вы только что все сломали. Обьясните, пожалуйста, читателям, почему класс, которому добавили аксессорный метод, возвращающий nil, когда либо будет возвращать по этому проперти не nil? Расскажите, как работает Extensions в Obj-C? Метод, который я имплементировал в Extension, когда и как добавляется в класс? Расскажите, как работает IBOutlet/IBOutletCollection для property? При загрузке из nib выполняется -setPropertyName: или же в рантайме имплементируется геттер -propertyName? Если первое, то почему нет краша, ведь поведение проперти по умолчанию это
    @sythnesize propertyName = _propertyName;
    
    , а ClassExtensions не умеет добавлять iVar'ы в класс по очевидным причинам, и для Extensions пропертя делается (скорее всего, я не компилировал такой случай на моей практике без имплементации аксессорных методов в extension, чтобы посмотреть, что будет)
    @dynamic propertyName
    

    и ожидает, что вы имплементируете свои методы, и если вы этого не сделаете, то будет краш. Если же второе, то почему ваша имплементация, если код рабочий, оверрайдится имплементацией для IBOutlet? Это противоречит ожидаемому поведению dynamic пропертей в Foundation и ко. Например NSManagedObject в CoreData. Да и о каком конкретно ворнинге речь, и почему вы просто от него отмахиваетесь?

    Предложения:
    5. Все связанное с высотой клеток, имхо, стоит вынести в классы самих клеток, а точнее имплементировать их суперкласс, который будет хранить «невидимые» клетки по именам классов и блоки их инициализаций, заместо нагружения лишним кодом ваш контроллер.

    6.
    static char cellPrototypesKey;
    // ...
    objc_setAssociatedObject(self, &cellPrototypesKey, cellPrototypes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    Вы только что создали бестолковую переменную, которая торчит в скопе всего файла. Вместо этого предлагается (http://nshipster.com/associated-objects/) делать
    objc_setAssociatedObject(self, @selector(getterName), cellPrototypes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
  • Работа iOS App в фоновом режиме
    0
    Ключи бы я изначально выставил. А затем предложил бы для товарищей код-ревью бекграунд аудио какое-то, мол, смотрите, вот по делу. А на самом деле с дарк релизом бы эту обманку выключил.
    Для того, чтобы так сильно заморачиваться, должны быть веские причины. Мой посыл лишь в том, что это возможно.
  • Декларативное программирование на C++
    +6
    Может, наоборот, учитывая время выхода статей? :)
  • Работа iOS App в фоновом режиме
    0
    posix_spawn режется. Имхо режутся все системные вызовы по номерам. Еще варианты?

    Да ладно, не жалуют, самые одаренные малвар-кодеры потом и пишут весь фундамент, на котором все работает. Ну, если в плохих мальчиков надоест играть. :3