Все новости с меткой: ios


Представим, что у нас бывают тяжеловатые задачи, которые на некоторое время заметно блокируют UI приложения. Например, это может быть чтение и десериализация какого-нибудь JSON-файла из Bundle на старте приложения. Для заметного ускорения можно разгрузить главный runloop приложения, а также задействовать для решения задачи другие свободные ядра процессора на смартфоне.

Для этого нам поможет класс-хелпер, чем-то напоминающий Promise, но без возможности зафейлиться, т.е. результат будет возвращаться всегда. Базироваться он будет на DispatchQueue, где в глобальной очереди будет исполнятся сама задача, а результат возвращаться в главную очередь обратно.


Как пользоваться?

А вот пользоваться получается очень удобно:

async {

    print("heavy task impl");

}.then {

    print("perform UI updates");

}

Если же функция имеет возвращаемый результат, то выглядеть метод, например асинхронной загрузки изображения из интернета, будет таким образом:

А использовать вызов этой фунции одно удовольствие: никакого вложенного спагетти из кода между DispatchQueue

loadImageAsync(url).then { image in
    imageView.image = image;
}

Подробнее




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

 

Реализовано, конечно, не совсем как в гайдлайне материал дизайна, но задача была сформулирована именно таким образом. В реализации используется CoreGraphics Affine Transform для плавной анимации UILabel для плейсхолдера. Также переопределено само свойство placeholder со своими сеттерами и геттерами для текста нового UILabel. Можно задавать текст прямо из storyboard и, внимание, менять цвет текста плейсхолдера, ведь раньше приходилось хачить в рантайме через attributedPlaceholder. Исходный код лежит на гитхабе.

Подробнее




В какой-то момент времени мы понимаем, что первый релиз уже на подходе и пора бы добавить локализацию проекта. Делается это легко, настройках проекта добавляется новая локализация, на основе базового storyboard будет сгенерирован файл Main.strings, в котором по ObjectId идет замена заголовков контролов на нужный язык.

Это все очень классно, но проблема таится в следующем - как обновить этот strings-файл новыми строками в добавок к уже существующем, к следующему релизу обязательно появляются новые ViewController-ы. Решения нормального нет: можно либо перегенерить заново этот strings-файл с непереведенными строчками, потом глазом искать новые и добавлять в старый файл. Либо руками выцеплять ObjectId, тыкая на свойства каждого контрола и вручную добавлять для них поля для перевода. Все это неудобно и не понятно, по каким причинам нельзя было встроить это в XCode.

В целом я придумал простое решение в виде скрипта на bash, который генерит заново файл локализации, смотрит в существующий файл и если не находит в нем существующего ObjectID - добавляет новую строчку с локализацией
 


Подробнее




Вот прямо руки чешутся написать про это, а точнее высказать свое негодование.

Представьте, что вам вдруг во время программирования яблокодевайса понадобилось указать какой-либо цвет (ну там подхайлайтить что-то), то вы, определившись с цветом с помощью пипетки или на глаз (ну там ВЫРВИГЛАЗНОЖЕЛТЫЙ) пытаетесь создать объект класса UIColor. И тут начинается ступор. Я конечно понимаю, что компания Apple еще те извращенцы пытается быть не как все, но чтобы извратиться и придумать конструктор от объекта UIColor в виде покомпонентно разложенных каналов, причем не от нуля до 0xff (да-да, я чуть не охренел от эротической фантазии того, кто это придумал), — а от дробного числа в  интервале [0..1]!!!!

Блин, ну ребята, задавать цвет в rgb hex формате - это стандарт, который используется ну просто везде, начиная с самых древнейших версий HTML, CSS, Qt и так далее. Даже в андроиде не поленились написать метод Color.parseColor. Максимум, где я встретил такую нотацию - это при создании цвета в OpenGL. Т.е. примерно у каждого ui-разработчика есть представление в голове, что вот, противно- приятно-голубой цвет, который используется просто повсюду - это #0099cc, оранжевый - это наоборот надо поменять местами каналы, и так далее. И тут у тебя начинается разрыв мозга, как привычный цвет в голове быстренько перевести в систему счисления от нуля до единицы?)) не, ну я конечно заметил, что разработчики ПРОВЕЛИ ИССЛЕДОВАНИЯ и заметили, что 50 оттенков серого настолько популярны, что они сделали специальный конструктор для этого - colorWithWhite:alpha:

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


UIColor* ColorFromStr(NSString *colorStr)
{
	unsigned int color = 0;
	float r, g, b, a = 1.0;
	NSScanner *scanner = [NSScanner scannerWithString:colorStr];
	[scanner setScanLocation:1];
	[scanner scanHexInt:&color];
	
	if ([colorStr length] == 9) {
		a = (color & 0xff) / 255.0;
		color >>= 8;
	}
	r = ((color & 0xff0000) >> 16) / 255.0;
	g = ((color & 0xff00) >> 8) / 255.0;
	b = (color & 0xff) / 255.0;
	return [UIColor colorWithRed:r green:g blue:b alpha:a];
} 

UPD: Либо можно тоже самое изобразить на Swift:

extension UIColor {
    convenience init(htmlColor: String) {
        var color:UInt32 = 0;
        var r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat = 1.0;
        let scanner:NSScanner = NSScanner(string: htmlColor);

        scanner.scanLocation = 1;
        scanner.scanHexInt(&color)
        
        if (htmlColor.characters.count == 9) {
            a = CGFloat(color & 0xff) / 255.0;
            color >>= 8;
        }
        r = CGFloat((color & 0xff0000) >> 16) / 255.0;
        g = CGFloat((color & 0xff00) >> 8) / 255.0;
        b = CGFloat(color & 0xff) / 255.0;
        self.init(red:r, green:g, blue:b, alpha:a);
    }
}

Подробнее