Pull to refresh
4
0
Send message

Я очень скептически был настроен, когда открывал статью. Название — кликбэйт. Именовали бы честно: дебажим при использовании ssl pinning’а.
Использовать js, чтобы в дебаге отключить ssl pinning, тоже спорная затея. Выставляете флаг в настройках проекта, ну или прям DEBUG значение проверяете. Всё равно история с получением имени функции не должна сработать в релизе. Вы же функцию не публичной делали, а значит компилятор порежит этот символ. А ксли публичной… то плохие дяди и так её потом поменяют :)

"Неверно представление о блоках"
1) target-action на блоках, простенькая задача, но вы написали статью на пару А4, что создает впечатление о неподъемности вопроса
2) Если вы написали там много, и хотели показать всю взаимосвязь, то надо было еще добавить Такую цепочку логики — блок — это объект, объест это структура, простая Сишная структура с определенными правилами формирования. И тогда понятно зачем в статье декларируются странные структуры.
3) Слово магия недопустима в статьях, вообще. Как и мое многократное повторение слово структура :)

Параметры:
1) target-action ни есть задача о performSelector:withObject:
2) Если надо передать объект в блок как в performSelector:withObject:, просто используйте переменную блоке, и все счастливы будут
3) У меня на каждую пару эвент/кнопка всегда свой метод, и поэтому с моей "колокольни" это и не нужно. Но вот если прям очень-очень нужно, то

typedef void  (^ButtonExecutionBlock)(void);

@implementation UIButton (XYZ_SomeLabel)

- (void)XYZ_addBlock:(void (^)(id, UIControlEvents))block forEvent:(UIControlEvents)event
{
  weakify(self)
  ButtonExecutionBlock eventBlock = ^(void){
    strongify(self)
    block(self, event);
  };

  NSString *key = [NSString stringWithFormat:@"%lu", (unsigned long)event];
  const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];

  NSMutableArray *blocks = objc_getAssociatedObject(self, cKey);
  if (blocks == nil) {
    blocks = [NSMutableArray array];
    objc_setAssociatedObject(self, cKey, blocks, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  }
  [blocks addObject:eventBlock];

  [self addTarget:eventBlock
              action:@selector(invoke)
    forControlEvents:UIControlEventTouchUpInside];
}

@end

Да, тут нельзя удалить эвент, но тем не менее, допилить небольшая работа.
Да, ломается 2х строчное решение
Но это все равно меньше пары классов и статьи на пару А4. А по сути всего один метод у UIButton

Если бы Вы ограничили статью только темой "Разбираемся с NSMethodSignature на примере комбинирования stringWithFormat и NSArray" и убрали привязку к target-action — я бы лайкал статью неистово, всем одним лайком который у меня есть.
Если честно я был в шоке. Мало того что очень странным путем пошли. Так еще и магию много раз вспомнили.
А как Вам решение в 2 строки?

_buttonOwner.strongPropertyForBlock = block
[button addTarget:block action:@selector(invoke) forControlEvents:UIControlEventTouchUpInside]

Главное держать блок столько же, сколько живет кнопка. Можно просто у владельца кнопки создать массив всех блоков. Можно даже к кнопке его приделать — это не хитрый метод, раз вы знакомы с рантайном, добавить проперти в системный класс — плёвое дело.

И вся статья сводится к:
1) Болк это NSObject, Наверно у него есть методы, вот давайте их и используем.
2) А если есть какие то контекстные переменные для блока, то создаем переменную, помечаем ее как __block и используем в блоке как хотим.

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

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

P.S Не смотря на комент "When you call this method, target is not retained." у UIControl, даже если не держать ссылку на блок, все работает. Но я всегда храню ссылку на блок. Но раз живет на тестах. то давайте решение будет вообще однострочным.

P.P.S. Я не злой, но за 2 недели вижу такое решение 2ой раз. И считаю что такое на надо рассказывать. Сделали, заработало. Проктической пользы не несёт? Значит прячем в архивы на долгую память.

Вот вам распечатка интерфейса блока
@interface NSBlock: NSObject {
}

  • (id)copy;
  • (id)copyWithZone:(struct _NSZone { }*)arg1;
  • (void)invoke;
  • (void)performAfterDelay:(double)arg1;

end

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

Спасибо, буду иметь ввиду. Пока что мне не приходилось ни разу «трастить» профайл который ставил с мака.
Вы меня конечно простите, но это очень странная статься. Она должны быть переводом вот этой страницы. Однако нет.
Комментарии по мере важности:
1) Не надо скриптов и мучительных выборов профайлов. Вы же показали скрин где проверили наличие provisioning'а. Нажмите правой кнопкой.
Вот как это выглядит

Он откроется в Finder и подсветится. И не важно какой там бардак.

2) Установка через iTunes имеет негативный эффект — надо синхронизовать девайс и iTunes, что невозможно сделать если это по работе. То есть если это не ваше устройство, то при синхронизации Вы человеку всё потрете. Поэтому есть более верный, на мой взгляд, способ — Xcode -> Window -> Devices. Там выбрать свой девайс и в секции «Installed Apps» нажать "+". Аналогично на устройстве можно нажать правой кнопкой мыши и перейти в установленные provisioning. Ну и да, раз вы ставите с компьютера, то по идеи все профайлы будут приняты сразу, потому что при подключении вы нажали «Trust». Их надо вручную «Доверять», только если установка идет по воздуху.

3) В описанном методе отсутсвует важный момент. Все это работает пока ваше приложение не просит ничего особого от системы — ApplePay, In-App Purchase, например. Вроде упоминали это в коментах. Вот полное сравнение, что можно, а что нельзя без Developer program

4) Прежде чем брать и переподписывать чужое приложение(я уже даже не говорю что ни в коем случае нельзя для этого использовать сторонне ПО, как показано в вашем примере), стоит подумать, а нету ли там вредоносных компанент. Потому что те, кто не кладет что то в appstore из-за политики apple — просто выложат исходники. А вот брать собранную ipa и так смело ставить себе ее на устройство, да еще и используя стороннее ПО… Это смело! Вы наверно пропустили вот такие новости — 1 и 2. Речь об одном и том же инциденте, просто выберете что приятней почитать. И если тут вреда особо не наносили, то в ipa, которую вы скачали, могут и нанести.

P.S. А если после установки удалить provisioning с устройства, то приложение не запустится. Это было новостью для меня
Мне статья нравится. Особенно нравится подход, когда пробуют все своими руками. Но есть пара замечаний.
1) Вы используете термины, которе тут абсолютно лишние: «окрестности Мура», «окрестности фон Неймана». Статья написана для неискушенного пользователя, а вот такие термины, как бы намекают на очень сильную связь с научным трактатом. А ведь можно было смело без терминов обойтись.
2) Либо у конкретно вашей реализации, либо у волнового алгоритма в целом нету возможности задать «проходимость клетки», то есть поиск пути в ситуации, где клетки могут быть пройдены с разной скоростью и «кратчайший» != «оптимальный». Например может будет быстрее пробежать по мосту, чем плыть через реку.
Вот очень странно, я не увидел самого ожидаемого комментария: у все этой идеи есть проблема — алерты системы. К примеру, с просьбой ввести логин и пароль при покупке. Они будут локализованы языком системы. И вы никак не решаете эту проблему.
Сочувствую. Правильный подход — пометить файл как Legacy… и постепенно пилить новый функционал. Потому то рефакторить такое… и не внести багов… нереально.
При классах в 100 строк — класс делает ничего. Большая группа классов, которые делают ничего и только друг другу передают вызовы. Для меня 450 — пока все в норме, 600 — надо рефакторить, 1000 — блин, кажется я что то пропустил… Так что в среднем классы по 400 — 500 строк и все отлично.
Ну и да #pragma mark отлично разделяет методы в списке методов в классе. Это который выпадающий список в пути файла под Tool Bar'ом
А вот я бы рекомендовал убрать все пробелы из имен папок. Потому что в тот день, когда вы захотите добавить какой-нибудь скрипт — вы будете очень сожалеть о том что столько много директорий имеют пробелы. В принципе, все сработает и с пробелами, но не раз наткнетесь на то что bash разделит имя файла на 2 пути.
Ну у нас не экстремальный случай. Несмотря на небольшой размер bundle, открывается быстро(бинарь сам по себе небольшой).
Когда-нибудь, когда я попаду в идеальный мир, и я обязательно забуду о таких вещах как маркетинг и брэнд.
Но пока я вынужден жить в этом мире. И раз уж приложение дает и так неплохой бесплатный контент для пользователя, значит для нас оно должно давать иную пользу.
Вариант грузить постранично даже не рассматривается. На странице одно предложение. И раз уж мы стараемся сделать хороший продукт и идем на встречу тем у кого 3g, то и книжка должна быть вся на девайсе когда пользователь ее читает.
Вы конечно простите, но постраничная загрузка… это прям вэб. А наше приложение отлично работает и без инета(как минимум одна книжка в комплекте), а потом можно скачать остальные и спокойно отключится от всех сетей.
Одно из главных преимуществ нативных приложений — это работа в офлайн. С ним может поспорить только «скорость работы».
конечно. никому не нужна задердка после 5 секунд старта. даже болше скажу, меряю паузу от попадания в main.
Когда на iPad Mini я увидел 23Mb — я очень обрадовался. У приложения есть все шансы пережить ночь без использования на девайсе)
Решение и вправду спорное.
Но это необходимо с точки зрения маркетинга. Зато приложение реже умирает в background даже на iPad Mini, то есть ли вы ненадолго отвлеклись во время чтения сказки, то и перезапуск приложения не произойдет, и логотип вы не увидите.
Второй момент — на новый iPad вы даже не успеваете прочитать название компании.
Векторная графика не всегда возможна. К примеру в сказках есть животные — это рисованные от руки персонажи, с тенями и там далее. Они не представимы в виде векторных изображений. Конечно есть изображения, которые, по сути, это фон + эффект и тогда я откажусь от картинки и буду в программно применять эффект. А если что то смогу свести к svg — то и вообще заиспользую сторонние либы. Но эта статья была про достаточно простое решение, которое сьело разумное время, зато дало хороший результат.
Да, так и есть. Я использовал самый популярный набор задач. Но аналога для pvc нет. А если говорить о UIView, то нельзя вывести superview рекурсивно. Но с аддоном можно — pviews --up <_pointer_>. То есть ли Вы остановились где на breakpoint и хотите посмотреть, не всю иерархию UIView, а только относительно конкретной UIView(причем вврех), используйте приведенную команду.
Ну или же вот так
po [((UIApplication *)[UIApplication sharedApplication]).delegate window]

Я предпочитаю в коде использовать NSObject.property, нежели [NSObject getter]. Использование их в lldb приводит к излишним скобкам, но привычка.
Ошибку поправил. Больше спасибо, за комментарий.
Я уже по привычке набираю приведение всех типов, где возвращается id, забыл что window часть UIApplicationDelegate.

Information

Rating
Does not participate
Location
London, England - London, Великобритания
Date of birth
Registered
Activity