Swift | Вопросы собесов
2.13K subscribers
28 photos
948 links
Download Telegram
🤔 Какую проблему решает реактивное программирование?

🟠Управление асинхронностью
Реактивное программирование упрощает координацию асинхронных операций, избегая "callback hell".
До:
fetchData { data in
process(data) { processedData in
save(processedData) { success in
print("Data saved: \(success)")
}
}
}


После:
fetchData()
.flatMap { process($0) }
.flatMap { save($0) }
.subscribe(onNext: { success in
print("Data saved: \(success)")
})


🟠Обработка событий и управление состоянием
Обеспечивает простое и автоматическое обновление UI при изменении данных.
data.asObservable()
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}
.disposed(by: disposeBag)


🟠Композиция и повторное использование кода
Позволяет легко объединять данные из разных источников.
Observable.zip(loadUser(), loadPosts())
.subscribe(onNext: { user, posts in
display(posts)
})


🟠Управление ошибками
Централизованная обработка ошибок в асинхронных цепочках.
fetchData()
.flatMap { process($0) }
.flatMap { save($0) }
.subscribe(onNext: { success in
print("Data saved: \(success)")
}, onError: { error in
print("Error: \(error)")
})


🟠Реактивные пользовательские интерфейсы
Автоматическая привязка данных к элементам UI.
usernameObservable
.bind(to: usernameLabel.rx.text)
.disposed(by: disposeBag)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что такое многопоточность?

Многопоточность — это возможность выполнения нескольких задач одновременно в разных потоках, что позволяет программам эффективно использовать ресурсы процессора. В Swift многопоточность реализуется с помощью GCD (Grand Central Dispatch) и NSOperationQueue, которые позволяют управлять параллельным выполнением задач. Многопоточность используется для разделения вычислительно затратных операций на несколько потоков, чтобы не блокировать основной поток интерфейса пользователя. Это улучшает производительность и отзывчивость приложений.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Почему плохо загружать главный поток и какие есть способы этого не делать?

Главный поток отвечает за обновление пользовательского интерфейса (UI) и обработку взаимодействия с пользователем. Если этот поток блокируется, приложение может стать неотзывчивым, что вызывает задержки в интерфейсе или даже его полную заморозку.

🚩Проблемы при загрузке

🟠Замораживание интерфейса
Если главный поток занят выполнением длительных операций, UI не будет обновляться, что приведет к замораживанию или задержке интерфейса.
🟠Плохой пользовательский опыт
Задержки и лаги при взаимодействии с приложением вызывают неудовлетворенность пользователей и могут привести к негативным отзывам.
🟠Возможные аварийные завершения
Длительная блокировка главного потока может привести к тому, что система iOS решит завершить приложение, считая его неотзывчивым.

🚩Способы предотвращения загрузки

🟠Использование Grand Central Dispatch (GCD)
GCD предоставляет простой способ выполнения асинхронных задач в фоновом режиме.
DispatchQueue.global(qos: .background).async {
// Длительная задача
let result = performHeavyComputation()

DispatchQueue.main.async {
// Обновление UI с результатом
updateUI(with: result)
}
}


🟠OperationQueue
OperationQueue предлагает более высокоуровневый интерфейс для управления асинхронными задачами с возможностью задания приоритетов и зависимостей.
let backgroundQueue = OperationQueue()
backgroundQueue.addOperation {
// Длительная задача
let result = performHeavyComputation()

OperationQueue.main.addOperation {
// Обновление UI с результатом
updateUI(with: result)
}
}


🟠URLSession для сетевых запросов
URLSession автоматически выполняет сетевые запросы в фоновом режиме.
let url = URL(string: "https://example.com/data")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
// Обработка данных

DispatchQueue.main.async {
// Обновление UI
updateUI(with: data)
}
}
task.resume()


🟠Core Data
Для выполнения запросов к базе данных можно использовать фоновые контексты (background contexts).
let backgroundContext = persistentContainer.newBackgroundContext()
backgroundContext.perform {
let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest()
let results = try? backgroundContext.fetch(fetchRequest)

DispatchQueue.main.async {
// Обновление UI с результатами
updateUI(with: results)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как решить проблему race condition?

Race condition — это ошибка, возникающая при одновременном доступе нескольких потоков к одним и тем же данным без должной синхронизации. Для решения проблемы race condition в Swift используются механизмы синхронизации, такие как блокировки (locks), семафоры или серийные очереди GCD. Эти инструменты позволяют ограничить доступ к общим ресурсам, чтобы только один поток мог их изменять в любой момент времени. Это предотвращает непредсказуемое поведение программы и ошибки при многопоточном доступе к данным.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Почему нельзя записать пример ячейки?

Может быть сложным для реализации из-за необходимости создания множества компонентов даже для простых задач.

🚩Пример реализации ячейки

Создание пользовательской ячейки
import UIKit

class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!

func configure(with text: String) {
titleLabel.text = text
}
}


View
import UIKit

protocol TableViewProtocol: AnyObject {
func updateTableView()
}

class TableViewController: UIViewController, TableViewProtocol {
@IBOutlet weak var tableView: UITableView!
var presenter: TableViewPresenterProtocol?

override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
presenter?.viewDidLoad()
}

func updateTableView() {
tableView.reloadData()
}
}

extension TableViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return presenter?.numberOfRows() ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
if let text = presenter?.textForRow(at: indexPath) {
cell.configure(with: text)
}
return cell
}
}


Presenter
protocol TableViewPresenterProtocol: AnyObject {
func viewDidLoad()
func numberOfRows() -> Int
func textForRow(at indexPath: IndexPath) -> String
}

class TableViewPresenter: TableViewPresenterProtocol {
weak var view: TableViewProtocol?
var interactor: TableViewInteractorProtocol?

func viewDidLoad() {
interactor?.fetchData()
}

func numberOfRows() -> Int {
return interactor?.data.count ?? 0
}

func textForRow(at indexPath: IndexPath) -> String {
return interactor?.data[indexPath.row] ?? ""
}
}


Interactor
protocol TableViewInteractorProtocol: AnyObject {
var data: [String] { get }
func fetchData()
}

class TableViewInteractor: TableViewInteractorProtocol {
var data: [String] = []

func fetchData() {
data = ["Item 1", "Item 2", "Item 3"]
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3
🤔 Расскажи про RC?

RC (Reference Counting) в Swift — это механизм управления памятью, который автоматически отслеживает количество ссылок на объекты в памяти. Когда количество ссылок на объект достигает нуля, объект освобождается, и его память становится доступной для повторного использования. ARC (Automatic Reference Counting) управляет ссылками на объекты в фоновом режиме, что позволяет избежать утечек памяти. Однако при работе с циклическими ссылками может потребоваться использовать слабые (`weak`) или необладания (`unowned`) ссылки, чтобы избежать утечек памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Есть ли в функциях моменты, когда используется свойство класса?

Да, в функциях часто используются свойства класса. Функции, методы и замыкания могут взаимодействовать со свойствами класса или структуры, чтобы получить доступ к данным или изменить их.

🚩Примеры использования

🟠Методы класса
Могут использовать свойства класса для чтения или изменения данных. В этом примере метод celebrateBirthday использует свойства name и age для обновления возраста и печати сообщения.
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}

func celebrateBirthday() {
age += 1
print("Happy Birthday, \(name)! You are now \(age) years old.")
}
}

let person = Person(name: "Alice", age: 30)
person.celebrateBirthday()
// Output: "Happy Birthday, Alice! You are now 31 years old."


🟠Инициализаторы
Используют свойства класса для установки начальных значений при создании экземпляра класса.
class Car {
var model: String
var year: Int

init(model: String, year: Int) {
self.model = model
self.year = year
}

func displayInfo() {
print("Car model: \(model), year: \(year)")
}
}

let car = Car(model: "Toyota", year: 2022)
car.displayInfo()
// Output: "Car model: Toyota, year: 2022"


🟠Замыкания (closures)
Могут захватывать и использовать свойства класса. Это часто используется в асинхронных операциях, таких как сетевые запросы.
class Downloader {
var url: String

init(url: String) {
self.url = url
}

func download(completion: @escaping () -> Void) {
print("Downloading from \(url)...")
DispatchQueue.global().async {
// Симуляция загрузки
sleep(2)
DispatchQueue.main.async {
completion()
}
}
}
}

let downloader = Downloader(url: "https://example.com/file")
downloader.download {
print("Download completed.")
}
// Output:
// "Downloading from https://example.com/file..."
// (2 секунды спустя)
// "Download completed."


🟠Статические свойства и методы
Используются для данных или функций, которые относятся ко всему классу, а не к конкретному экземпляру. В этом примере статическое свойство count используется для отслеживания количества созданных экземпляров класса.
class Counter {
static var count = 0

init() {
Counter.count += 1
}

static func displayCount() {
print("Number of instances: \(count)")
}
}

let counter1 = Counter()
let counter2 = Counter()
Counter.displayCount()
// Output: "Number of instances: 2"


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Что такое Stack и куча?

Стек (Stack) — это область памяти, которая используется для хранения локальных переменных и вызовов функций. Он организован по принципу LIFO (Last In, First Out), и данные в стеке автоматически освобождаются при завершении вызова функции. Куча (Heap) — это область памяти, используемая для динамического выделения памяти, где объекты хранятся до тех пор, пока на них существуют ссылки. В Swift объекты классов размещаются в куче, а структуры и примитивные типы — в стеке, что влияет на производительность и управление памятью.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1
🤔 Может ли быть в языке Swift, что существует сильная ссылка на объект и при этом его не существует?

Объект может быть освобожден из памяти, даже если на него существует сильная ссылка, при использовании ключевого слова unowned в некоторых специфических обстоятельствах.

🚩Unowned References

Неустранимые ссылки (unowned) не увеличивают счетчик ссылок на объект, к которому они относятся. В отличие от слабых ссылок (weak), unowned ссылки не обнуляются автоматически, когда объект освобождается. Это означает, что если вы попытаетесь обратиться к объекту через unowned ссылку после его освобождения, это приведет к аварийному завершению программы (runtime crash).Если бы вы попытались обратиться к owner после освобождения john, это привело бы к аварийному завершению программы, так как unowned ссылка не обнуляется и остается указателем на освобожденный объект.
class Person {
var name: String
var creditCard: CreditCard?

init(name: String) {
self.name = name
}

deinit {
print("\(name) is being deinitialized")
}
}

class CreditCard {
var number: Int
unowned var owner: Person

init(number: Int, owner: Person) {
self.number = number
self.owner = owner
}

deinit {
print("CreditCard #\(number) is being deinitialized")
}
}

var john: Person? = Person(name: "John")
john!.creditCard = CreditCard(number: 1234, owner: john!)

john = nil
// Output:
// John is being deinitialized
// CreditCard #1234 is being deinitialized


1⃣Создается объект Person с именем "John" и сильной ссылкой john.
2⃣Создается объект CreditCard, который имеет неустранимую ссылку owner на john.
3⃣Когда john освобождается (при установке john в nil), также освобождается и объект CreditCard.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 В чем разница между синхронными и асинхронными запросами?

Синхронные запросы блокируют выполнение программы до получения ответа, что может замедлить работу приложения, особенно если запрос занимает длительное время. Асинхронные запросы, напротив, не блокируют основной поток и позволяют программе продолжать выполнение других задач, пока ожидается ответ от сервера или другой операции. Асинхронные запросы часто используются для работы с сетью или файловой системой, чтобы улучшить отзывчивость и производительность программ. В Swift асинхронные операции реализуются через GCD или `async/await`.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Расскажи про проблемы работы с Self'ом?

Может вызывать проблемы, особенно в контексте замыканий, циклических ссылок и асинхронных операций.

🚩Проблемы

🟠Циклические ссылки (Retain Cycles)
Возникают, когда два объекта удерживают друг друга сильными ссылками. Решение: Использовать weak или unowned ссылки.
class Person {
var name: String
var apartment: Apartment?

init(name: String) {
self.name = name
}
}

class Apartment {
var unit: String
weak var tenant: Person? // Используем weak

init(unit: String) {
self.unit = unit
}
}


🟠Захват `self` в замыканиях
Может привести к циклическим ссылкам и утечкам памяти. Решение: Использовать списки захвата (capture lists) с weak или unowned.
class MyViewController: UIViewController {
func loadData() {
someAsyncMethod { [weak self] in
guard let self = self else { return }
print(self.name)
}
}
}


🟠Асинхронные операции
Могут завершиться после освобождения объекта, вызвавшего их. Решение: Использовать weak или unowned ссылки внутри замыканий.
class MyViewController: UIViewController {
func fetchData() {
DispatchQueue.global().async { [weak self] in
sleep(2)
DispatchQueue.main.async {
self?.updateUI()
}
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Что лучше NSOperationQueue или GCD?

NSOperationQueue и GCD оба являются инструментами для управления многозадачностью в Swift, но они имеют разные преимущества. GCD (Grand Central Dispatch) более низкоуровневый и предоставляет простой синтаксис для выполнения задач асинхронно, с меньшими накладными расходами, что делает его более производительным для простых задач. NSOperationQueue, с другой стороны, предлагает более высокоуровневый интерфейс с возможностью управления зависимостями между операциями, приоритетами и отменой задач. NSOperationQueue лучше подходит для сложных сценариев, требующих большей гибкости и контроля над выполнением задач, тогда как GCD предпочтителен для простоты и скорости.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что делает Unowned?

Это ключевое слово, которое используется для создания неустранимых ссылок. Неустранимая ссылка (unowned) не увеличивает счётчик ссылок на объект, к которому она относится, и, в отличие от слабых ссылок (weak), не обнуляется автоматически, когда объект освобождается из памяти. Использование unowned ссылок полезно в тех случаях, когда вы уверены, что объект, на который ссылается unowned ссылка, будет существовать на протяжении всей жизни ссылки.

🚩Особенности

🟠Не увеличивает счётчик ссылок
Unowned ссылки не удерживают объект в памяти, что предотвращает циклические ссылки.
🟠Не обнуляется автоматически
Если объект, на который ссылается unowned ссылка, освобождается из памяти, попытка доступа к этой ссылке приведёт к ошибке времени выполнения (runtime crash).
🟠Использование в ситуациях гарантированного существования
Unowned ссылки следует использовать только тогда, когда вы уверены, что объект будет существовать на протяжении всей жизни ссылки.

🚩Пример использования

class Person {
var name: String
var creditCard: CreditCard?

init(name: String) {
self.name = name
}

deinit {
print("\(name) is being deinitialized")
}
}

class CreditCard {
var number: Int
unowned var owner: Person

init(number: Int, owner: Person) {
self.number = number
self.owner = owner
}

deinit {
print("CreditCard #\(number) is being deinitialized")
}
}

var john: Person? = Person(name: "John")
john!.creditCard = CreditCard(number: 1234, owner: john!)

john = nil
// Output:
// John is being deinitialized
// CreditCard #1234 is being deinitialized


1⃣Создаётся объект Person с именем "John".
2⃣Создаётся объект CreditCard, который имеет unowned ссылку owner на john.
3⃣Когда объект john освобождается (при присвоении nil), также освобождается и объект CreditCard. Случаи использования unowned

🚩Когда использовать

🟠Гарантированное существование объекта
Вы уверены, что объект будет существовать на протяжении всей жизни ссылки.
🟠Избежание ненужной опциональности: Если объект гарантированно существует, использование unowned позволяет избежать использования опционалов (Optional), что упрощает код.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
🤔 Чем отличается frame от bounds?

Frame определяет положение и размер представления (view) относительно его родительского координатного пространства в iOS. Bounds определяет внутренний прямоугольник представления, используемый для рисования и взаимодействия, и всегда задается относительно собственных координат представления (его левый верхний угол всегда (0,0)).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
🤔 Как работает UITableView?

Используется для отображения списков данных и оптимизирует производительность с помощью повторного использования ячеек.

🚩Компоненты

🟠Data Source (Источник данных)
tableView(_:numberOfRowsInSection:): Количество строк.
tableView(_:cellForRowAt:): Конфигурация ячеек.
🟠Delegate (Делегат)
tableView(_:didSelectRowAt:): Обработка выбора строки.
tableView(_:heightForRowAt:): Настройка высоты строки.
🟠Cells (Ячейки)
Ячейки (UITableViewCell) отображают контент.

🚩Настройка `UITableView`

1⃣Создание проекта и добавление таблицы
Добавьте UITableView в ViewController через Interface Builder или программно. Подключите UITableView как IBOutlet.
2⃣Настройка Data Source и Delegate
Назначьте ViewController источником данных и делегатом таблицы. Реализуйте методы протоколов.
import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000 // Количество строк
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected row: \(indexPath.row)")
}
}


🟠Повторное использование ячеек
Используйте dequeueReusableCell(withIdentifier:for:) для повторного использования ячеек.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
🤔 Жизненный цикл UIViewController

Жизненный цикл UIViewController включает несколько ключевых этапов:
1. `loadView` создает представление, которое контроллер управляет.
2. `viewDidLoad` вызывается после загрузки представления контроллера в память.
3. `viewWillAppear` выполняется перед тем, как представление станет видимым.
4. `viewDidAppear` вызывается после того, как представление появилось на экране.
5. `viewWillDisappear` и `viewDidDisappear` вызываются перед и после того, как представление было удалено с экрана.
6. `deinit` вызывается перед освобождением экземпляра контроллера из памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Как сделано VVM?

Модель представляет данные и бизнес-логику, представление отвечает за отображение данных и взаимодействие с пользователем, а ViewModel связывает модель и представление, управляя состоянием и логикой представления.

🚩Структура проекта

- Models
- User.swift
- Views
- UserView.swift
- ViewModels
- UserViewModel.swift


🚩Полный пример реализации

🟠Model
Модель представляет данные и бизнес-логику. Например, это может быть структура User.
struct User {
let name: String
let age: Int
}


🟠ViewModel
ViewModel связывает модель и представление, управляя состоянием и логикой представления. Он использует @Published для обновления представления при изменении данных.
import Combine

class UserViewModel: ObservableObject {
@Published var user: User?

func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}


🟠View
Представление отвечает за отображение данных и взаимодействие с пользователем. В SwiftUI представление использует @StateObject или @ObservedObject для наблюдения за изменениями данных в ViewModel.
import SwiftUI

struct UserView: View {
@StateObject var viewModel = UserViewModel()

var body: some View {
VStack {
if let user = viewModel.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
viewModel.fetchUser()
}
}
}

struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}


🚩Полный пример

User.swift
struct User {
let name: String
let age: Int
}


UserViewModel.swift
import Combine

class UserViewModel: ObservableObject {
@Published var user: User?

func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}


UserView.swift
import SwiftUI

struct UserView: View {
@StateObject var viewModel = UserViewModel()

var body: some View {
VStack {
if let user = viewModel.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
viewModel.fetchUser()
}
}
}

struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 Что такое enum, raw value и associated value в Swift?

Enum (перечисление) позволяет группировать связанные значения под общим типом с возможностью проверки типа. Raw value представляет постоянное значение каждого случая enum, например, строки или числа. Associated values позволяют хранить дополнительные пользовательские данные для каждого случая enum, поддерживая разные типы данных для разных случаев enum.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🤔 Как расшифровывается СA?

Расшифровывается как Core Animation. Это фреймворк, используемый в iOS и macOS для создания анимаций. Core Animation предоставляет высокоуровневый API для работы с анимациями, которые могут быть применены к слоям (CALayer). Он позволяет разработчикам создавать плавные и эффективные анимации с минимальными усилиями.

🚩Возможности

🟠Основные анимации (CABasicAnimation)
Анимация изменения свойств слоя, таких как позиция, масштаб, поворот, прозрачность и т.д.
🟠Ключевые кадры (CAKeyframeAnimation)
Создание сложных анимаций с использованием ключевых кадров, позволяющих анимировать свойства слоя по нескольким значениям.
🟠Групповые анимации (CAAnimationGroup)
Одновременное выполнение нескольких анимаций, объединенных в одну группу.
🟠Переходы (CATransition)
Анимация переходов между состояниями слоев, таких как изменение содержимого или структуры слоя.
🟠Слоистая модель (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