Расшифровывается как Core Animation. Это фреймворк, используемый в iOS и macOS для создания анимаций. Core Animation предоставляет высокоуровневый API для работы с анимациями, которые могут быть применены к слоям (CALayer). Он позволяет разработчикам создавать плавные и эффективные анимации с минимальными усилиями.
Анимация изменения свойств слоя, таких как позиция, масштаб, поворот, прозрачность и т.д.
Создание сложных анимаций с использованием ключевых кадров, позволяющих анимировать свойства слоя по нескольким значениям.
Одновременное выполнение нескольких анимаций, объединенных в одну группу.
Анимация переходов между состояниями слоев, таких как изменение содержимого или структуры слоя.
Core Animation основывается на слоях (CALayer), которые представляют собой абстракцию для управления графическим содержимым и анимациями.
Основная анимация (CABasicAnimation)
import UIKit
class AnimationViewController: UIViewController {
let animatedLayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
// Настройка слоя
animatedLayer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
animatedLayer.backgroundColor = UIColor.blue.cgColor
self.view.layer.addSublayer(animatedLayer)
// Создание анимации перемещения
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = CGPoint(x: 50, y: 50)
animation.toValue = CGPoint(x: 300, y: 300)
animation.duration = 2.0
// Добавление анимации к слою
animatedLayer.add(animation, forKey: "positionAnimation")
// Обновление конечного состояния слоя
animatedLayer.position = CGPoint(x: 300, y: 300)
}
}
CAKeyframeAnimation
import UIKit
class KeyframeAnimationViewController: UIViewController {
let animatedLayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
// Настройка слоя
animatedLayer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
animatedLayer.backgroundColor = UIColor.red.cgColor
self.view.layer.addSublayer(animatedLayer)
// Создание анимации ключевых кадров
let keyframeAnimation = CAKeyframeAnimation(keyPath: "position")
keyframeAnimation.values = [
CGPoint(x: 50, y: 50),
CGPoint(x: 150, y: 150),
CGPoint(x: 250, y: 50),
CGPoint(x: 300, y: 300)
]
keyframeAnimation.duration = 4.0
// Добавление анимации к слою
animatedLayer.add(keyframeAnimation, forKey: "positionKeyframeAnimation")
// Обновление конечного состояния слоя
animatedLayer.position = CGPoint(x: 300, y: 300)
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3😁1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3😁1
Это высокоуровневый механизм синхронизации, который объединяет взаимное исключение (mutex) и условные переменные (condition variables) для управления доступом к объектам в многопоточной среде.
Только один поток может выполнить защищенный блок кода в любой момент времени.
Позволяют потокам ожидать определенных условий, а другим потокам уведомлять их о наступлении этих условий.
class ThreadSafeClass {
private var internalState = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")
func increment() {
queue.sync {
internalState += 1
}
}
func getState() -> Int {
return queue.sync {
internalState
}
}
}С
NSLockclass ThreadSafeClass {
private var internalState = 0
private let lock = NSLock()
func increment() {
lock.lock()
internalState += 1
lock.unlock()
}
func getState() -> Int {
lock.lock()
let state = internalState
lock.unlock()
return state
}
}С
objc_sync_enter и objc_sync_exitclass ThreadSafeClass: NSObject {
private var internalState = 0
func increment() {
objc_sync_enter(self)
internalState += 1
objc_sync_exit(self)
}
func getState() -> Int {
objc_sync_enter(self)
let state = internalState
objc_sync_exit(self)
return state
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3
В отличие от некоторых других языков, таких как Java, нет прямого способа "повесить" синхронизацию на отдельную переменную с использованием ключевого слова
synchronized. Вместо этого, синхронизация осуществляется на уровне методов или блоков кода, которые обращаются к переменной. Это достигается использованием механизмов синхронизации, таких как NSLock, DispatchQueue, или атомарные переменные.В данном примере, доступ к переменной
_value синхронизирован с помощью NSLock, что предотвращает одновременное чтение и запись из нескольких потоков.class ThreadSafeVariable {
private var _value: Int = 0
private let lock = NSLock()
var value: Int {
get {
lock.lock()
let v = _value
lock.unlock()
return v
}
set {
lock.lock()
_value = newValue
lock.unlock()
}
}
}В этом примере, доступ к переменной
_value осуществляется через серийную очередь, что обеспечивает эксклюзивный доступ к переменной в любой момент времени.class ThreadSafeVariable {
private var _value: Int = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")
var value: Int {
get {
return queue.sync {
_value
}
}
set {
queue.sync {
_value = newValue
}
}
}
}Здесь используется атомарная переменная
ManagedAtomic для обеспечения безопасного доступа к переменной _value.import Atomics
class ThreadSafeVariable {
private var _value = ManagedAtomic(0)
var value: Int {
get {
return _value.load(ordering: .relaxed)
}
set {
_value.store(newValue, ordering: .relaxed)
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Это базовое понятие в объектно-ориентированном программировании (ООП). Это экземпляр класса, который может содержать данные и методы для работы с этими данными. В Swift, как и в большинстве ООП-языков, объекты играют ключевую роль в организации и структурировании кода.
Представлено данными или свойствами (properties) объекта. Например, объект
Car может иметь свойства color, model, и year.Определяется методами (methods) объекта. Например, объект
Car может иметь методы drive() и brake().Каждый объект имеет уникальную идентичность, которая отличает его от других объектов, даже если их состояния идентичны.
Это шаблон или чертеж для создания объектов. Он определяет свойства и методы, которые будут у объектов данного класса. Объект является экземпляром класса.
class Car {
var color: String
var model: String
var year: Int
init(color: String, model: String, year: Int) {
self.color = color
self.model = model
self.year = year
}
func drive() {
print("The \(color) \(model) is driving.")
}
func brake() {
print("The \(color) \(model) is braking.")
}
}Создание объекта:
let myCar = Car(color: "Red", model: "Toyota", year: 2020)
myCar.drive()
myCar.brake()
Объекты скрывают детали реализации и предоставляют интерфейс для взаимодействия. Это способствует защите данных и улучшению модульности.
Объекты могут наследовать свойства и методы от других классов, позволяя создавать иерархии классов и повторно использовать код.
Объекты могут быть обработаны через интерфейсы или базовые классы, что позволяет использовать один и тот же код для объектов разных типов.
В этом примере, свойство
age скрыто от внешнего доступа, и доступ к нему осуществляется через методы getAge и setAge.class Person {
private var age: Int
init(age: Int) {
self.age = age
}
func getAge() -> Int {
return age
}
func setAge(newAge: Int) {
if newAge > 0 {
age = newAge
}
}
}
let person = Person(age: 25)
print(person.getAge()) // 25
person.setAge(newAge: 30)
print(person.getAge()) // 30Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
1. Инкапсуляция: сокрытие внутренних деталей реализации объекта и объединение данных и методов, работающих с этими данными, в один объект.
2. Наследование: создание нового класса на основе существующего.
3. Полиморфизм: возможность обращаться с объектами, производными от одного базового класса, для выполнения методов, определенных в базовом классе, но переопределенных в производных.
4. Абстракция: определение интерфейса взаимодействия с объектом, отделяющего его функциональное поведение от конкретной реализации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Объект создается в момент инициализации экземпляра класса. В языке Swift это происходит при вызове конструктора (initializer) класса с использованием ключевого слова
init. Когда инициализатор вызывается, выделяется память для объекта, и его свойства устанавливаются значениями, указанными в инициализаторе.Память для нового объекта выделяется в heap (куче).
Все свойства объекта инициализируются значениями, указанными в конструкторе.
Конструктор устанавливает начальное состояние объекта.
class Car {
var color: String
var model: String
var year: Int
init(color: String, model: String, year: Int) {
self.color = color
self.model = model
self.year = year
}
func drive() {
print("The \(color) \(model) is driving.")
}
func brake() {
print("The \(color) \(model) is braking.")
}
}let myCar = Car(color: "Red", model: "Toyota", year: 2020)
Память для объекта
myCar выделяется в heap.Свойства
color, model и year инициализируются значениями "Red", "Toyota" и 2020 соответственно.Инициализатор
init(color:model:year:) устанавливает эти значения.Основные инициализаторы, которые инициализируют все свойства объекта.
Вспомогательные инициализаторы, которые вызывают другой инициализатор и могут задавать дополнительные параметры.
class Car {
var color: String
var model: String
var year: Int
init(color: String, model: String, year: Int) {
self.color = color
self.model = model
self.year = year
}
convenience init(model: String) {
self.init(color: "White", model: model, year: 2020)
}
}
let defaultCar = Car(model: "Honda")Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥3
Forwarded from Идущий к IT
Твое резюме на HeadHunter — ОК, если ты видишь это.
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
В языках программирования, таких как Kotlin, термин
companion object используется для обозначения особого объекта, который связан с определенным классом и позволяет хранить статические члены этого класса. В Swift нет прямого аналога companion object, но схожие концепции можно реализовать с помощью статических свойств и методов.Используется для определения статических членов класса. Они могут быть вызваны без создания экземпляра класса.
class MyClass {
companion object {
fun staticMethod() {
println("This is a static method")
}
}
}
// Вызов метода без создания экземпляра класса
MyClass.staticMethod()В Swift статические члены класса (свойства и методы) определяются с использованием ключевого слова
static. Статические члены принадлежат самому классу, а не его экземплярам.class MyClass {
static func staticMethod() {
print("This is a static method")
}
}
// Вызов метода без создания экземпляра класса
MyClass.staticMethod()Также можно использовать ключевое слово
class для определения методов класса, которые могут быть переопределены в подклассах. class MyClass {
class func classMethod() {
print("This is a class method")
}
}
class SubClass: MyClass {
override class func classMethod() {
print("This is an overridden class method")
}
}
// Вызов метода без создания экземпляра класса
MyClass.classMethod() // Output: This is a class method
SubClass.classMethod() // Output: This is an overridden class methodСтавь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Когда вы добавляете обычный объект внутри класса, вы создаете именованный объект, который является экземпляром анонимного класса. Он может содержать свойства и методы, и он создается один раз при создании экземпляра внешнего класса.
class MyClass {
let instanceProperty = "Instance Property"
struct MyObject {
static let objectProperty = "Object Property"
static func objectMethod() {
print("This is an object method")
}
}
}
// Использование
let myClassInstance = MyClass()
print(MyClass.MyObject.objectProperty) // Доступ к свойствам и методам объекта через имя объекта
MyClass.MyObject.objectMethod()Companion Object (компаньон-объект)
Companion object позволяет определить статические члены класса. Эти члены доступны без создания экземпляра класса. Вы можете использовать companion object для хранения статических методов и свойств, которые могут быть вызваны напрямую через имя класса. class MyClass {
let instanceProperty = "Instance Property"
companion object {
let companionProperty = "Companion Property"
func companionMethod() {
print("This is a companion object method")
}
}
}
// ИспользованиеОбычный объект: Доступ к свойствам и методам обычного объекта осуществляется через его имя. Companion Object: Доступ к свойствам и методам компаньон-объекта осуществляется через имя класса.
Обычный объект: Не привязан к конкретному экземпляру класса и создается один раз для всего класса. Companion Object: Также не привязан к конкретному экземпляру класса и создается один раз для всего класса, но служит для определения статических членов класса.
Обычный объект: Требует явного имени для доступа. Companion Object: Имеет неявное имя Companion, если не указано другое имя. Это позволяет получить доступ к его членам без явного указания имени.
class MyClass {
val instanceProperty = "Instance Property"
object MyObject {
val objectProperty = "Object Property"
fun objectMethod() {
println("This is an object method")
}
}
companion object {
val companionProperty = "Companion Property"
fun companionMethod() {
println("This is a companion object method")
}
}
}
// Доступ к свойствам и методам объекта через имя объекта
println(MyClass.MyObject.objectProperty)
MyClass.MyObject.objectMethod()
// Доступ к свойствам и методам компаньон-объекта через имя класса
println(MyClass.companionProperty)
MyClass.companionMethod()Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Модуль в iOS-разработке представляет собой логически изолированную часть приложения, включающую все необходимые компоненты для выполнения определённой функции. Вот пример модуля
User с использованием архитектурного шаблона VIPER:- Modules
- User
- View
- UserView.swift
- UserViewController.swift
- Interactor
- UserInteractor.swift
- Presenter
- UserPresenter.swift
- Entity
- UserEntity.swift
- Router
- UserRouter.swift
UserView.swift
import UIKit
protocol UserViewProtocol: AnyObject {
var presenter: UserPresenterProtocol? { get set }
func showUserData(_ user: UserEntity)
}
class UserView: UIViewController, UserViewProtocol {
var presenter: UserPresenterProtocol?
override func viewDidLoad() {
super.viewDidLoad()
presenter?.viewDidLoad()
}
func showUserData(_ user: UserEntity) {
// Обновление UI с данными пользователя
}
}
UserInteractor.swift
protocol UserInteractorProtocol: AnyObject {
var presenter: UserPresenterProtocol? { get set }
func fetchUserData()
}
class UserInteractor: UserInteractorProtocol {
weak var presenter: UserPresenterProtocol?
func fetchUserData() {
let user = UserEntity(name: "John Doe", age: 30)
presenter?.didFetchUserData(user)
}
}UserPresenter.swift
protocol UserPresenterProtocol: AnyObject {
var view: UserViewProtocol? { get set }
var interactor: UserInteractorProtocol? { get set }
var router: UserRouterProtocol? { get set }
func viewDidLoad()
func didFetchUserData(_ user: UserEntity)
}
class UserPresenter: UserPresenterProtocol {
weak var view: UserViewProtocol?
var interactor: UserInteractorProtocol?
var router: UserRouterProtocol?
func viewDidLoad() {
interactor?.fetchUserData()
}
func didFetchUserData(_ user: UserEntity) {
view?.showUserData(user)
}
}UserEntity.swift
struct UserEntity {
let name: String
let age: Int
}UserRouter.swift
protocol UserRouterProtocol: AnyObject {
static func createModule() -> UIViewController
}
class UserRouter: UserRouterProtocol {
static func createModule() -> UIViewController {
let view = UserView()
let presenter: UserPresenterProtocol & UserInteractorOutputProtocol = UserPresenter()
let interactor: UserInteractorProtocol = UserInteractor()
let router: UserRouterProtocol = UserRouter()
view.presenter = presenter
presenter.view = view
presenter.interactor = interactor
presenter.router = router
interactor.presenter = presenter
return view
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В iOS-проектах обычно хранятся и управляются с помощью CocoaPods, популярного менеджера зависимостей для проектов на Swift и Objective-C. Вот основные моменты и шаги, связанные с хранением и управлением Pod'ами:
Установите CocoaPods, если он ещё не установлен, используя команду
sudo gem install cocoapods
Перейдите в корневую директорию вашего проекта и создайте Podfile, если он ещё не создан, используя команду
pod init
Откройте Podfile и добавьте необходимые зависимости. Например:
platform :ios, '13.0'
target 'YourApp' do
use_frameworks!
# Подключение библиотек
pod 'Alamofire', '~> 5.4'
pod 'SwiftyJSON', '~> 5.0'
end
Установите Pod'ы, используя команду
pod install
После установки Pod'ов откройте сгенерированный файл
.xcworkspace вместо .xcodeproj для работы с проектомopen YourApp.xcworkspace
Pod'ы, указанные в Podfile, загружаются и устанавливаются в директорию
Pods, которая создаётся в корневой директории вашего проекта. Также CocoaPods создаёт или обновляет несколько файлов, таких как Podfile.lock, Pods/Manifest.lock и YourApp.xcworkspace.Директория, где хранятся все установленные зависимости и их файлы.
Файл, фиксирующий версии всех установленных Pod'ов, чтобы обеспечить согласованность между разработчиками.
Файл, используемый CocoaPods для синхронизации состояния Pod'ов.
Рабочая область, которая объединяет ваш проект и его зависимости.
Добавьте
Podfile и Podfile.lock в ваш репозиторий (например, Git), чтобы обеспечить согласованность зависимостей между разработчиками. git add Podfile Podfile.lock
git commit -m "Add Podfile and Podfile.lock"
Обычно директорию
Pods/ игнорируют в системе контроля версий, добавляя её в .gitignore. Pods/
При клонировании репозитория или при изменении зависимостей выполните
pod install, чтобы установить те же версии Pod'ов, что указаны в Podfile.lock.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Использование наследования для расширения класса может привести к жесткой связности и сложностям в поддержке кода. Вместо наследования можно использовать следующие альтернативы: композиция, протоколы (интерфейсы), категории (extensions) и делегирование. Эти подходы предлагают большую гибкость и модульность, уменьшая вероятность проблем, связанных с наследованием.
Композиция предполагает включение объектов других классов в качестве полей и делегирование им работы. Это позволяет комбинировать различные компоненты и изменять их поведение во время выполнения.
protocol Engine {
func start()
}
class Car {
private let engine: Engine
init(engine: Engine) {
self.engine = engine
}
func start() {
engine.start()
}
}
class ElectricEngine: Engine {
func start() {
print("Electric engine starting...")
}
}
class GasolineEngine: Engine {
func start() {
print("Gasoline engine starting...")
}
}
let electricCar = Car(engine: ElectricEngine())
let gasolineCar = Car(engine: GasolineEngine())
electricCar.start() // Electric engine starting...
gasolineCar.start() // Gasoline engine starting...Протоколы определяют набор методов и свойств, которые класс или структура должны реализовать. Это позволяет создавать гибкие и переиспользуемые компоненты.
protocol Drawable {
func draw()
}
class Circle: Drawable {
func draw() {
print("Drawing a circle")
}
}
class Square: Drawable {
func draw() {
print("Drawing a square")
}
}
func render(drawable: Drawable) {
drawable.draw()
}
let shapes: [Drawable] = [Circle(), Square()]
shapes.forEach { render(drawable: $0) }Расширения позволяют добавлять новые методы и свойства к существующим классам, структурам или перечислениям без необходимости наследования или изменения исходного кода.
extension String {
func reverse() -> String {
return String(self.reversed())
}
}
let original = "hello"
let reversed = original.reverse()
print(reversed) // "olleh"Делегирование предполагает передачу ответственности за выполнение определенных задач другому объекту. Это часто используется для создания гибких и переиспользуемых компонентов.
protocol PrinterDelegate: AnyObject {
func printerDidFinishPrinting(_ printer: Printer)
}
class Printer {
weak var delegate: PrinterDelegate?
func printDocument() {
// Печать документа
print("Printing document...")
// Уведомление делегата о завершении печати
delegate?.printerDidFinishPrinting(self)
}
}
class PrintManager: PrinterDelegate {
func printerDidFinishPrinting(_ printer: Printer) {
print("Document printing completed.")
}
}
let printer = Printer()
let manager = PrintManager()
printer.delegate = manager
printer.printDocument()
// "Printing document..."
// "Document printing completed."Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1