Объект создается в момент инициализации экземпляра класса. В языке 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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👾5😁2
Это архитектурный шаблон, который разделяет логику приложения на три компонента: Model, View и Presenter. Несмотря на то, что SwiftUI тесно интегрирован с архитектурой MVVM (Model-View-ViewModel), можно адаптировать его для использования с MVP. В этом примере я покажу, как можно реализовать MVP со SwiftUI.
- Models
- User.swift
- Views
- UserView.swift
- Presenters
- UserPresenter.swift
Модель представляет данные и бизнес-логику. В нашем примере это будет простая структура
User. struct User {
let name: String
let age: Int
}Презентер управляет логикой представления и взаимодействует с моделью. Он обновляет представление в ответ на изменения данных.
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}
class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?
func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}Представление отвечает за отображение данных и взаимодействие с пользователем. В SwiftUI представление использует
@StateObject или @ObservedObject для наблюдения за изменениями данных в презентере. import SwiftUI
struct UserView: View {
@StateObject var presenter = UserPresenter()
var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}
struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}
User.swift
struct User {
let name: String
let age: Int
}UserPresenter.swift
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}
class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?
func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}UserView.swift
import SwiftUI
struct UserView: View {
@StateObject var presenter = UserPresenter()
var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}
struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👀1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🤯1
Synchronized в программировании используется для управления доступом к ресурсам в многопоточном окружении, чтобы предотвратить состояние гонки (race condition). В контексте iOS и Swift, Synchronized гарантирует, что только один поток может выполнять определенный блок кода в любой момент времени.В данном примере,
NSLock используется для синхронизации доступа к переменной internalState. Метод increment() увеличивает значение переменной на единицу, и блок lock/unlock гарантирует, что этот код выполнится атомарно, то есть только один поток сможет его выполнять в один момент времени. Тоже самое относится к методу getState(), который возвращает текущее значение переменной.class 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
}
}В этом примере
DispatchQueue с атрибутом sync используется для обеспечения того, что блок кода внутри будет выполнен синхронно, то есть только один поток сможет выполнить его в данный момент времени.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
}
}
}Здесь
objc_sync_enter(self) и objc_sync_exit(self) обеспечивают блокировку и разблокировку доступа к ресурсу.class 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
❤1
Статические инициализаторы (`static`) выполняются один раз при загрузке класса и инициализируют статические переменные.
Нестатические инициализаторы выполняются при создании каждого экземпляра класса и используются для инициализации нестатических переменных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Использование наследования может привести к жесткой связности и сложностям в поддержке кода. Альтернативы наследованию: композиция, протоколы (интерфейсы), расширения (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()
gasolineCar.start()Протоколы определяют набор методов и свойств, которые класс или структура должны реализовать, обеспечивая гибкость и переиспользуемость компонентов.
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()Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Reference type (ссылочный тип) хранит ссылку на область памяти, где находятся данные, и при копировании копируется только ссылка, а не сами данные. Например, объекты классов разделяют одну и ту же память.
Разница проявляется при изменении данных: value type остаётся неизменным в копиях, а reference type отражает изменения во всех ссылках.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В объектно-ориентированном программировании классы могут выполнять различные роли в зависимости от их назначения и использования. Классы, условно названные
User и Data, могут иметь существенные различия в своей реализации и предназначении. Класс
User обычно представляет сущность пользователя в системе. Он может включать свойства и методы, специфичные для пользователя, такие как идентификатор, имя, адрес электронной почты и методы для управления этими данными.class User {
var id: Int
var name: String
var email: String
init(id: Int, name: String, email: String) {
self.id = id
self.name = name
self.email = email
}
func updateEmail(newEmail: String) {
self.email = newEmail
}
}Класс
Data чаще всего используется для представления необработанных данных или байтов. В Swift, например, Data — это структура из Foundation, которая предоставляет интерфейс для работы с бинарными данными.import Foundation
let string = "Hello, World!"
if let data = string.data(using: .utf8) {
// Преобразование строки в Data
print(data)
}
let jsonString = "{\"name\": \"John\", \"age\": 30}"
if let jsonData = jsonString.data(using: .utf8) {
// Преобразование JSON-строки в Data
do {
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
print(jsonObject)
}
} catch {
print("Ошибка парсинга JSON: \(error)")
}
}
User: Представляет конкретную сущность пользователя в системе. Используется для управления и хранения данных о пользователе.
Data: Представляет необработанные данные или байты. Используется для операций с бинарными данными, таких как чтение и запись файлов, сетевые операции и сериализация.
User: Обычно содержит несколько свойств, специфичных для пользователя, и методы для управления этими данными.
Data: Является универсальным контейнером для байтов, предоставляя методы для работы с этими данными.
User: Включен в бизнес-логику, тесно связан с функциональностью приложения, связанной с пользователями.
Data: Используется для низкоуровневых операций с данными, часто не связан напрямую с бизнес-логикой.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1😁1