Swift
Интеграция SpriteKit
шаг первый
в ViewController пишем
шаг второй в stoyboard у главной view указываем тип SKView

For Base Controller
Size Of Screen
var screenSize: CGSize { return UIScreen.main.bounds.size }
Версия приложения
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String let build = Bundle.main.infoDictionary?["CFBundleVersion"] as! String
пишем расширение
extension UIApplication { func getVersion() -> String { let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String let build = Bundle.main.infoDictionary?["CFBundleVersion"] as! String return "\(version).\(build)" } }
применение
... UIApplication.shared.getVersion() ...
Date
Дату из текущей + N дней
extension Date { func dateFromDays(_ days: Int) -> Date { return (Calendar.current as NSCalendar).date(byAdding: .day, value: days, to: self, options: [])! } }
let startDate = Date() let endDate = startDate.dateFromDays(+10)
Custom action in UITableViewCell
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in print("share button tapped") } share.backgroundColor = UIColor.blue let deleteAction = UITableViewRowAction(style: .default, title: "Del") {action, index in self.deleteRow(index) } deleteAction.backgroundColor = .red return [deleteAction, share] }
Realm
let uiRealm = RealmHelper.shared if let currentTaskList = self.taskList { try! uiRealm.write { ()->Void in currentTaskList.tasks.append(newTask) } }
SnapKit
func setupConstraints(){ uiLogo.snp.makeConstraints{ set in set.width.equalTo(AppStyles.About.logoSize) set.height.equalTo(AppStyles.About.logoSize) set.top.equalToSuperview().offset(AppStyles.About.offsetTop) set.centerX.equalToSuperview() } uiVersion.snp.makeConstraints{set in set.top.equalTo(uiLogo.snp.bottom).offset(AppStyles.About.offetBottom) set.centerX.equalToSuperview() } uiBack.snp.makeConstraints{make in make.width.equalTo(AppStyles.About.backSize) make.height.equalTo(AppStyles.About.backSize) make.centerX.equalToSuperview() make.bottom.equalToSuperview().offset(-AppStyles.About.offetBottom) } }
Множественные аргументы метода
Multi, Мульти аргументы
typealias Person = (id: Int, name: String) class Persons{ var items:[Person] = [] func add(_ persons: Person...){ persons.forEach{id,name in print("id: \(id) name: \(name)") } } }
Persons().add( (1,"Yuriy"), (2,"Vadim"), (3,"Anastasya") )
Трюк использования #function
UserDefaults
let isInstalledErlier = UserDefaults.standard.bool(forKey: "isInstalledErlier") ?? false if isInstalledErlier { UserDefaults.standard.set(true, forKey: "isInstalledErlier") }
Если создать расширение для UserDefaults
extension UserDefaults { var isInstalledErlier: Bool { get { return bool(forKey: #function) } set { set(newValue, forKey: #function) } } }
то использовать будет проще
if UserDefaults.standard.isInstalledErlier == false { // тут какой-то полезный код UserDefaults.standard.isInstalledErlier = true }
Пример
extension UserDefaults { var firstLaunch: Bool { get { return bool(forKey: #function) } set { set(newValue, forKey: #function) } } }
extension UserDefaults { var isActivated: Bool { get { return bool(forKey: #function) } set { set(newValue, forKey: #function) } } var appName: String { get { return string(forKey: #function)! } set { set(newValue, forKey: #function) } } }
UserDefaults.standard.appName = "Tinder"
(Обсуждение) Вопросы собеседований на Junior Developer
Темы для собеседований:
- Простые типы и алгоритмы работы с ними
- Многопоточность (MultiThreading)
- Жизненный цикл MVC
- Runloop
- CoreData
Простые типы и алгоритмы работы с ними
обычно, эта тема называется Структуры данных и алгоритмы
Связанный список
Стек
Очередь
RxSwift
RxGesture
labelView.rx .anyGesture(.longPress()) .when(.began) .subscribe(onNext: {_ in //react to long Press UIView.animate(withDuration: 1, animations: { self.labelView.bounds.size.width = 200 }, completion: { ok in self.labelView.bounds.size = self.sizeOfButton }) print("long press") }).addDisposableTo(disposeBag)
UISwitch
var uiDone = UISwitch() uiDone.rx.isOn .subscribe(onNext: { isOn in print( isOn ? "it's ON" : "it's OFF" ) try! self.uiRealm.write { ()->Void in self.taskModel.isCompleted = isOn } }).addDisposableTo(disposeBag)
UIPanGestureRecognizer PanGesture
вот и всё что нужно чтобы повесить PanGesture программно, просто пишем его кодом
func setupGestures(){ let pan = UIPanGestureRecognizer(target: self, action: #selector(actionPan(_:))) scaleView.addGestureRecognizer(pan) }
сам обработчик касания
func actionPan(_ sender:UIPanGestureRecognizer){ let moving = sender.translation(in: self) print("Pan Action: \(moving)") let toPoint = CGPoint(x: scaleView.center.x + moving.x, y: scaleView.center.y + moving.y) scaleView.center = toPoint sender.setTranslation(CGPoint(x: 0, y: 0), in: self) }
@discardableResult
полезный модификатор возвращаемого типа, если не всегда хотим получать warning при вызове функции, не обрабатывая её результат
@discardableResult func getItem(x:Int) -> Int { return x*x }
getItem()
пример кода с CocoaHeads Май 2017 Alexander Zimin
protocol CellViewAnyModel { static var cellAnyType: UIView.Type { get } func setupAny(cell: UIView) } protocol CellViewModel: CellViewAnyModel { associatedtype CellType: UIView func setup(cell: CellType) } extension CellViewModel { static var cellAnyType: UIView.Type { return CellType.self } func setupAny(cell: UIView) { if let cell = cell as? CellType { setup(cell: cell) } else { assertionFailure("Wrong usage") } } } extension UITableView { func dequeueReusableCell(withModel model: CellViewAnyModel, for indexPath: IndexPath) -> UITableViewCell { let indetifier = String(describing: type(of: model).cellAnyType) let cell = self.dequeueReusableCell(withIdentifier: indetifier, for: indexPath) model.setupAny(cell: cell) return cell } func register(nibModels: [CellViewAnyModel.Type]) { for model in nibModels { let identifier = String(describing: model.cellAnyType) let nib = UINib(nibName: identifier, bundle: nil) self.register(nib, forCellReuseIdentifier: identifier) } } }
Как получить имя класса из статического метода ?
вариант 1
через рефлексию
static func getEntityName() -> String { return String(describing: Mirror(reflecting: self).subjectType).components(separatedBy: ".").first! }
вариант 2
немного устаревший вариант
static func getEntityName() -> String { return NSStringFromClass(self).components(separatedBy: ".").last! }
Кодогенерация — это просто
Sourcery
Пример файла настроек для генерации
sources: - src/ templates: - Templates/ output: out/ args:
у ключей sources и templates обязательно должны стоять символы —
В качестве шаблонизатора используется Stencil
для кастомизации имён генерируемых файлов можно использовать спец теги // sourcery:file:
// sourcery:file:TemplateName.swift ... какой-то наш код // sourcery:end
пример:
// sourcery:file:TemplateName.swift // template of UIView import UIKit class EventModelView: UIView, EventProtocol { } // sourcery:end // sourcery:file:Views/TemplateName2.swift // template of UIView import UIKit class EventModelView2: UIView, EventProtocol { } // sourcery:end
Parallax Effect with Motion Device
Формула Parallax
var parallaxImageHeight: CGFloat { let maxOffset = (sqrt( cellHeight * cellHeight + 4 * parallaxSpeed * self.tableView.frame.height) - cellHeight) / 2 return maxOffset + self.cellHeight }