Функция задержки на Swift
Очень приятный синтаксический сахар - функция для запуска кода с задержкой через Grand Central Dispatch с помощью dispatch_after:
Update 2024. Swift 5.5+
Если нужна задержка внутри async-функции:func someMethod() async throws {
// sleep for 2 seconds
try await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
}
Swift 2:
/**
Delay function using GCD. Syntax sugar.
- parameter delay: delay in seconds
- parameter closure: closure code to execute after delay
*/
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
Swift 3:
/**
Delay function using GCD. Syntax sugar.
- parameter delay: delay in seconds
- parameter closure: closure code to execute after delay
*/
func delay(_ delay: Double, closure:()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
Использование:
delay(0.4) {
// код
}
comment
comments
Модальный UIVIewController с прозрачностью
Шпаргалка - как запрезентить UIViewController поверх другого так, чтобы он был полупрозрачный и под ним просвечивал контент.
Выставляем в Storyboard для Segue поле Kind как «Present Modally». Для UIViewController, который показываем, выставляем цвет фона Clear Color, делаем внутри фон (картинка или другой UIView) со значением alpha, например, 0.5.
В коде:
self.performSegueWithIdentifier("segueName", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueName" {
let vc = segue.destinationViewController as! YourViewController
vc.modalPresentationStyle = .Custom
}
}
comment
comments
Редизайн блога
Решил поизучать, как выглядят сайты в Material Design от Google. Нашёл у них библиотеку Material Design Lite и запили его на сайт. Стало читабельнее, вроде, и из коробки адаптивный дизайн, можно читать с мобилок, да и на ретине выглядит теперь сочнее. Удобно, когда из готовых кусков можно собрать то, что тебе нравится. Результат мне нравится больше, чем то, что можно наваять, например, на Twitter Bootstrap.
Долго думал над шапкой и в итоге с любовью спёр идею у Apple с их страницы, посвящённой WWDC '16 :) запилил на SVG и анимировал курсор на JS (правда, только на десктопной версии). Смотрел на Polymer, но что-то оно как-то не завелось у меня сходу, да и уже на MDL многое сделал. Идея веб-компонентов, конечно, классная, и семантически круто выглядит, но пока отложу её до более хорошей поддержки браузерами. Как-то там, есть ощущение, что всё сильно на Node.JS завязано, а переписывать его на ноду мне уже не хочется, жду новых релизов Swift, чтобы на него переписать.
comment commentsТестирование асинхронного кода в XCTest
Пока писал тесты в приложении, столкнулся с тем, что не работают тесты, в которых есть асинхронный код. Например, если мы делаем асинхронный запрос в сеть и callback-блоке проверяем то, что получилось. Проверки просто не выболнялись и Xcode говорил, что тест удачно пройден, даже если он заведомо не должен пройти.
В ходе гугления оказалось два решения - одно через семафоры из Grand Central Dispatch, воторое с помощью expectations. С expectations мне понравилось больше. Пример теста:
import XCTest
class apiClientTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
/**
SampleTest
*/
func testSampleAsyncRequest() {
let exp = expectationWithDescription("\(#function)\(#line)")
APIClient.sharedInstance.someMethod { (responseObject, error) in
XCTAssertNotNil(responseObject, "responseObject should not be nil")
XCTAssertNil(error, "error should be nil")
exp.fulfill()
}
waitForExpectationsWithTimeout(40) { (error) in
if error != nil {
XCTAssertTrue(false)
}
}
}
}
P.S. - если хочешь, чтобы тесты запускались в определённом порядке - то надо помнить, что они запускаются тупо в алфавитном порядке. То есть надо именовать тесты test1Name, test2Name и т.д.
comment commentsПро использование Swift на сервере
Начал пробовать использовать Swift на сервере для бэкенда. Если с макосью всё довольно понятно в плане как начать использовать Swift (да хотя бы тот же Xcode), то с Linux не так всё очевидно оказалось.
На сайте Swift.org есть инструкция для OS X и для Ubuntu (14.04 и 15.04). Сразу обрадовался, что они выкладывают уже скомпилированные бинарники. Вкратце - скачиваем архив, скачиваем всякие ключи и подписи, проверяем подпись архива на всякий случай, распаковываем архив и делаем export чтобы из консоли можно было выполнить команду. Например
swift --version
Swift version 2.2.1-dev (LLVM da67bff217, Clang 81d0486fb2, Swift 82adb8fc96)
Target: x86_64-unknown-linux-gnu
Начинаем какой-нибудь простой Hello World - просто создаём проектик, который в консоль выводит текст, что-то вроде:
import Foundation
print("hello world")
Далее надо проверить - работает ли оно. Выполняем:
swift build
error: unable to invoke subcommand: /home/webserver/swift-2.2.1-SNAPSHOT-2016-04-23-a-ubuntu14.04/usr/bin/swift-build (No such file or directory)
Сюрприз! В релизную версию Swift версии 2.2.1 не включён swift-build. То есть собрать проект релизной версии мы не можем. Слегка офигеваешь от этого. Гуглишь - оказывается, надо дев-версию Swift скачивать. А это предрелизная версия Swift 3.0.
В ней всё есть, проект собирается, бинарник запускается и выводит текст в консоль. Но как-то это странно, что туториал с сайта не работает на релизной версии. Хотя пишут, что в предыдущих релизах он был.
Самое грустное - что пока даже сетевые запросы нельзя слать из опенсорсного Swift - в Foundation не реализован NSURLRequest, значит мои мысли о том, чтобы юзать CouchDB через его REST API пока можно отложить. И на гитхабе пока красуется надпись в описании текущего состояния Swift:
NSURLSession and related classes are not yet implemented.
Можно, конечно, сишные библиотеки использовать. Например, IBM используют обёртку на CURL под названием CCurl. Но хочется как-то из коробки, средствами языка. Поэтому, пожалуй, подожду, когда это наконец сделают.
Мои ковыряния с web-фреймворком Swift Express показали, что сделать на нём сайт или REST API можно. Я вчера вечером даже сделал заготовку для переписывания этого блога - готовы шаблоны, роутинг, выводится всё оформление сайта, осталось подставлять данные из базы данных. И теперь стоит вопрос - как доставать данные из базы. Есть обёртки над сишными библиотеками для MySQL и MongoDB, но мне вот всё хочется продолжать использовать CouchDB, раз уж я им итак пользуюсь во многих проектах. А у него REST API, то есть доставать данные надо через сетевые запросы, которые в Foundation пока не завезли, а использовать сторонние инструменты как-то не хочется, потому что потом, когда всё реализуют, будет логичнее перейти на встроенные инструменты, то есть придётся выпиливать. Подожду пока с переписыванием своего бложека на Swift :)
comment commentsЗаметка про Socket.IO-Client-Swift
Небольшая шпаргалка - для socket.io есть клиент на Swift. Казалось бы, на гитхабе хорошо расписано, как его использовать. Вот только к моему бэкенду на Node.js он никак не хотел подключаться с кодом примеров.
Логи показывали (если пробовать через polling-запросы), что клиент стучится по адресу /engine.io и получает 404 ошибку. Изучение браузерной Javascript-библиотеки, которая с этим же бэкендом работает без каких-либо танцев с бубном, показало, что надо указать другой путь - /socket.io. Благо, для этого есть специальная опция.
Итого, получаем:
let socketURL = NSURL(string: "http://localhost:3000")
let socket = SocketIOClient(socketURL: socketURL!, options: [
.ForceWebsockets(true),
.Path("/socket.io/"),
.ConnectParams(["token": "token"])
])
socket.on("connect") {data, ack in
print("socket connected")
}
socket.connect()
comment
comments
App Store Release Informer 1.1.0
Переписал своего бота на ES2015, плюс добавил тесты. Когда бот пишет о том, что вышла новая версия в App Store, то пишется и что нового в этой версии.
comment comments