Да, в функциях часто используются свойства класса. Функции, методы и замыкания могут взаимодействовать со свойствами класса или структуры, чтобы получить доступ к данным или изменить их.
Могут использовать свойства класса для чтения или изменения данных. В этом примере метод
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"Могут захватывать и использовать свойства класса. Это часто используется в асинхронных операциях, таких как сетевые запросы.
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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍1
Объект может быть освобожден из памяти, даже если на него существует сильная ссылка, при использовании ключевого слова
unowned в некоторых специфических обстоятельствах. Неустранимые ссылки (
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 deinitializedPerson с именем "John" и сильной ссылкой john.CreditCard, который имеет неустранимую ссылку owner на john.john освобождается (при установке john в nil), также освобождается и объект CreditCard.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Может вызывать проблемы, особенно в контексте замыканий, циклических ссылок и асинхронных операций.
Возникают, когда два объекта удерживают друг друга сильными ссылками. Решение: Использовать
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
}
}Может привести к циклическим ссылкам и утечкам памяти. Решение: Использовать списки захвата (
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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это ключевое слово, которое используется для создания неустранимых ссылок. Неустранимая ссылка (
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 deinitializedPerson с именем "John".CreditCard, который имеет unowned ссылку owner на john.john освобождается (при присвоении nil), также освобождается и объект CreditCard. Случаи использования unownedВы уверены, что объект будет существовать на протяжении всей жизни ссылки.
unowned позволяет избежать использования опционалов (Optional), что упрощает код.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
Используется для отображения списков данных и оптимизирует производительность с помощью повторного использования ячеек.
tableView(_:numberOfRowsInSection:): Количество строк.tableView(_:cellForRowAt:): Конфигурация ячеек.tableView(_:didSelectRowAt:): Обработка выбора строки.tableView(_:heightForRowAt:): Настройка высоты строки.Ячейки (
UITableViewCell) отображают контент.Добавьте
UITableView в ViewController через Interface Builder или программно. Подключите UITableView как IBOutlet.Назначьте
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
1. `loadView` создает представление, которое контроллер управляет.
2. `viewDidLoad` вызывается после загрузки представления контроллера в память.
3. `viewWillAppear` выполняется перед тем, как представление станет видимым.
4. `viewDidAppear` вызывается после того, как представление появилось на экране.
5. `viewWillDisappear` и `viewDidDisappear` вызываются перед и после того, как представление было удалено с экрана.
6. `deinit` вызывается перед освобождением экземпляра контроллера из памяти.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Модель представляет данные и бизнес-логику, представление отвечает за отображение данных и взаимодействие с пользователем, а ViewModel связывает модель и представление, управляя состоянием и логикой представления.
- Models
- User.swift
- Views
- UserView.swift
- ViewModels
- UserViewModel.swift
Модель представляет данные и бизнес-логику. Например, это может быть структура
User. struct User {
let name: String
let age: Int
}ViewModel связывает модель и представление, управляя состоянием и логикой представления. Он использует
@Published для обновления представления при изменении данных. import Combine
class UserViewModel: ObservableObject {
@Published var user: User?
func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}
Представление отвечает за отображение данных и взаимодействие с пользователем. В 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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Расшифровывается как 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