Выбор архитектурного паттерна для разработки приложения зависит от множества факторов, таких как специфика проекта, опыт команды и особенности используемой платформы.
MVP разделяет логику интерфейса пользователя и бизнес-логику, что делает код более модульным и управляемым.
Легче тестировать Presenter отдельно от View, что улучшает покрытие тестами и упрощает отладку.
Presenter управляет всей логикой взаимодействия с View, что делает структуру кода понятной и предсказуемой.
MVP хорошо подходит для проектов с сложной логикой UI, где требуется много взаимодействий между пользовательским интерфейсом и бизнес-логикой.
ViewModel не знает о View, что уменьшает связанность и улучшает тестируемость.
MVVM особенно хорошо работает с фреймворками, поддерживающими привязки данных, такими как SwiftUI или RxSwift. Это упрощает синхронизацию данных между View и ViewModel.
ViewModel формирует данные для View, что упрощает логику представления и делает код более чистым.
ViewModel легко тестируется, поскольку не зависит от конкретной реализации View, что улучшает модульное тестирование.
Использование MVVM в SwiftUI позволяет легко управлять состоянием приложения и автоматически обновлять интерфейс при изменении данных.
MVVM отлично сочетается с реактивным программированием, предоставляя мощные возможности для управления асинхронными операциями.
import SwiftUI
class Model {
var data: String = "Hello, MVVM"
}
class ViewModel: ObservableObject {
@Published var displayData: String = ""
private var model: Model
init(model: Model) {
self.model = model
self.displayData = model.data
}
func updateData(newData: String) {
model.data = newData
self.displayData = newData
}
}
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Text(viewModel.displayData)
}
}
MVP используется для четкого разделения логики представления и бизнес-логики в сложных проектах на UIKit.
protocol View: AnyObject {
func updateUI(with data: String)
}
class Model {
var data: String = "Hello, MVP"
}
class Presenter {
private weak var view: View?
private var model: Model
init(view: View, model: Model) {
self.view = view
self.model = model
}
func loadData() {
view?.updateUI(with: model.data)
}
}
class ViewController: UIViewController, View {
private var presenter: Presenter!
override func viewDidLoad() {
super.viewDidLoad()
presenter = Presenter(view: self, model: Model())
presenter.loadData()
}
func updateUI(with data: String) {
// Обновление интерфейса
print(data)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В программировании существуют различные типы ссылок, которые определяют, как объекты управляются и удерживаются в памяти.
По умолчанию в Swift все ссылки являются сильными. Сильная ссылка удерживает объект в памяти до тех пор, пока существует хотя бы одна сильная ссылка на него. Для стандартного владения объектами.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
var person1: Person? = Person(name: "Alice")
var person2 = person1 // person2 также является сильной ссылкой на тот же объект Слабая ссылка не удерживает объект в памяти. Если все сильные ссылки на объект удаляются, объект освобождается, и слабая ссылка автоматически становится nil. Для предотвращения циклов удержания, особенно в делегатах и замыканиях.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Apartment {
weak var tenant: Person?
}
var alice: Person? = Person(name: "Alice")
var apt = Apartment()
apt.tenant = alice // Слабая ссылка на alice Неактивная ссылка, как и слабая, не удерживает объект в памяти, но в отличие от слабой ссылки, она не может быть nil. Используется, когда объект гарантированно существует на протяжении всего жизненного цикла. Для циклических зависимостей, где одна сторона всегда будет существовать.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Apartment {
unowned var tenant: Person
init(tenant: Person) {
self.tenant = tenant
}
}
var alice: Person? = Person(name: "Alice")
var apt = Apartment(tenant: alice!) // Неактивная ссылка на alice Предоставляют прямой доступ к объекту без автоматического управления памятью. Используется редко и требует ручного управления памятью. Для специфических задач, где необходим контроль над управлением памятью.
import Foundation
let unmanagedReference = Unmanaged.passRetained(NSObject())
let retainedObject = unmanagedReference.takeRetainedValue()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
В iOS-разработке существует несколько способов создания и управления макетами (layouts) пользовательского интерфейса.
Визуальный редактор, встроенный в Xcode, который позволяет разрабатывать пользовательский интерфейс с помощью перетаскивания элементов. Удобный графический интерфейс, быстрый просмотр изменений, поддержка Auto Layout. Меньшая гибкость по сравнению с программным кодом. Создание и настройка интерфейса с помощью storyboard или xib файлов.
Система ограничений (constraints), которая позволяет определять правила расположения и размеров элементов интерфейса. Адаптивные интерфейсы для различных устройств и ориентаций, мощные инструменты для сложных макетов. Может быть сложно освоить, особенно для сложных макетов.
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
Создание и настройка элементов интерфейса полностью через код, без использования Interface Builder. Полный контроль над процессом создания интерфейса, легко управлять версиями. Требует больше времени и усилий для настройки, особенно для сложных макетов.
let label = UILabel(frame: CGRect(x: 50, y: 50, width: 200, height: 50))
label.text = "Hello, World!"
view.addSubview(label)
Компоненты интерфейса, которые автоматически располагают и масштабируют свои подвиды (subviews) в вертикальном или горизонтальном направлении. Упрощает создание и управление сложными макетами, поддержка Auto Layout.: Ограниченная гибкость для некоторых типов макетов.
let stackView = UIStackView(arrangedSubviews: [label, button])
stackView.axis = .vertical
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
Новый декларативный фреймворк для создания пользовательских интерфейсов, представленный Apple в 2019 году. Декларативный синтаксис, простой в использовании, интеграция с Swift, поддержка различных платформ (iOS, macOS, watchOS, tvOS). Требует iOS 13 и выше, меньшая поддержка старых устройств.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, World!")
Button(action: {
print("Button tapped")
}) {
Text("Tap me")
}
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Каждый способ создания макетов (layout'а) в iOS-разработке имеет свои преимущества и недостатки.
Удобный графический интерфейс для быстрой настройки и визуального просмотра изменений.
Простая настройка ограничений (constraints) для адаптивного интерфейса.
Возможность быстрого создания и изменения макетов без написания кода.
Ограниченные возможности для создания сложных и динамических макетов.
Трудности при слиянии изменений в storyboard или xib файлах в больших командах.
Более медленное время загрузки по сравнению с программными подходами.
Поддержка различных устройств и ориентаций экрана.
Возможность создания сложных и адаптивных макетов с помощью ограничений.
Упрощенная настройка ограничений через визуальный интерфейс.
Может быть сложно освоить, особенно для новичков.
Требует тщательного планирования и может стать сложным при работе с большим количеством ограничений.
Возможность точной настройки макета с помощью кода.
Легкость создания динамических и условных макетов.
Легче управлять изменениями в коде по сравнению с визуальными файлами.
Требует больше времени и усилий для настройки, особенно для сложных макетов.
Отсутствие визуального редактора может затруднить представление конечного результата.
Легкость создания и управления сложными макетами с минимальными усилиями.
Автоматическое управление ограничениями для вложенных элементов.
Поддержка различных ориентаций и размеров экранов.
Менее гибкие по сравнению с чистым Auto Layout или программными подходами.
Не всегда подходят для всех типов макетов, особенно для более сложных компоновок.
Простота и понятность кода благодаря декларативному подходу.
Мгновенное обновление интерфейса при изменении кода.
Современные возможности языка и тесная интеграция с экосистемой Apple.
Поддержка различных платформ (iOS, macOS, watchOS, tvOS).
Поддержка только iOS 13 и выше, что может ограничить использование на старых устройствах.
Некоторые функции еще находятся в стадии разработки, и могут быть ограничены возможности по сравнению с UIKit.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Являются важным механизмом управления памятью в Swift и других языках программирования с автоматическим управлением памятью.
Сильные ссылки гарантируют, что объект остается в памяти, пока на него существует хотя бы одна сильная ссылка. Без сильных ссылок объекты могли бы быть автоматически удалены сборщиком мусора, даже если они все еще нужны.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
var person1: Person? = Person(name: "Alice")
var person2 = person1 // person2 теперь также держит сильную ссылку на объектСильные ссылки контролируют время жизни объектов, предотвращая их преждевременное удаление из памяти. Объекты остаются живыми, пока они нужны, и удаляются только тогда, когда все сильные ссылки на них удаляются.
var person1: Person? = Person(name: "Alice")
person1 = nil // Объект "Alice" удаляется, если нет других сильных ссылок на него
Сильные ссылки часто используются для указания владения объектами. Владеющий объект держит сильную ссылку на подчиненный объект, обеспечивая его существование. ViewController держит сильные ссылки на UI-элементы, гарантируя, что они остаются в памяти, пока ViewController активен.
class ViewController {
var button: UIButton?
init() {
button = UIButton()
}
}
var viewController: ViewController? = ViewController()Сильные ссылки являются стандартным способом управления памятью и не требуют дополнительного кода для их создания и управления.
Они предотвращают утечки памяти, гарантируя, что объекты удаляются, когда на них больше нет ссылок.
Сильные ссылки делают код более предсказуемым, так как объекты остаются в памяти, пока они нужны.
Если два объекта имеют сильные ссылки друг на друга, они никогда не будут освобождены, что приведет к утечкам памяти. Это решается использованием слабых (weak) или неактивных (unowned) ссылок.
class Person {
var name: String
var friend: Person?
init(name: String) {
self.name = name
}
}
var alice: Person? = Person(name: "Alice")
var bob: Person? = Person(name: "Bob")
alice?.friend = bob
bob?.friend = alice
// Объекты alice и bob никогда не будут освобождены из памятиИспользование слабых (weak) или неактивных (unowned) ссылок для разрыва циклов сильных ссылок:
class Person {
var name: String
weak var friend: Person?
init(name: String) {
self.name = name
}
}
var alice: Person? = Person(name: "Alice")
var bob: Person? = Person(name: "Bob")
alice?.friend = bob
bob?.friend = alice
// Объекты alice и bob будут освобождены, когда на них не будет сильных ссылокСтавь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Слабые ссылки (weak references) играют важную роль в управлении памятью, особенно когда нужно предотвратить циклы сильных ссылок (retain cycles) и утечки памяти.
Циклы сильных ссылок возникают, когда два объекта держат сильные ссылки друг на друга, что препятствует их освобождению из памяти. Слабые ссылки разрывают этот цикл, позволяя одному из объектов освобождаться.
class Person {
var name: String
weak var friend: Person?
init(name: String) {
self.name = name
}
}
var alice: Person? = Person(name: "Alice")
var bob: Person? = Person(name: "Bob")
alice?.friend = bob
bob?.friend = alice
alice = nil // Теперь объекты могут быть освобождены
bob = nil Утечки памяти происходят, когда объекты, которые больше не нужны, не освобождаются из памяти. Слабые ссылки помогают избежать этих утечек, обеспечивая правильное освобождение памяти. Делегаты часто объявляются как слабые ссылки, чтобы избежать утечек памяти.
protocol TaskDelegate: AnyObject {
func taskDidFinish()
}
class Task {
weak var delegate: TaskDelegate?
func complete() {
delegate?.taskDidFinish()
}
}
class ViewController: TaskDelegate {
var task = Task()
init() {
task.delegate = self
}
func taskDidFinish() {
print("Task finished")
}
} Слабые ссылки удобны для временных зависимостей, когда объект не должен удерживаться в памяти, если нет других сильных ссылок. Использование слабых ссылок для временных объектов.
class Cache {
weak var temporaryObject: SomeClass?
}
class SomeClass {
// Код класса
}
var cache = Cache()
var object = SomeClass()
cache.temporaryObject = object
object = SomeClass() // Старый объект удаляется, так как на него нет сильных ссылок Основное преимущество слабых ссылок заключается в их способности разрывать циклы ссылок, предотвращая утечки памяти.
Слабые ссылки позволяют объектам освобождаться из памяти, когда на них больше нет сильных ссылок, что улучшает управление ресурсами.
Использование слабых ссылок обеспечивает более гибкое и безопасное управление зависимостями между объектами.
Необходимо учитывать, что слабые ссылки могут стать nil в любой момент, поэтому требуется дополнительная проверка.
Требуется хорошее понимание жизненного цикла объектов и управления памятью, чтобы правильно использовать слабые ссылки.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Нужен человек, для сбора вопросов из собеседований на должность iOS разработчик.
Что надо делать:
1. Смотреть записи собеседований (список будет дан)
2. Выписывать вопросы, которые задают кандидату
Ставка: 450 руб. / час
Примерная ЗП: 54 000 руб. / месяц (4 часа в день)
Если интересно и можешь уделять работе от 4 часов / день, то отправь сообщение и сразу напиши какие языки программирования знаешь и какие лучше всего?
Что надо делать:
1. Смотреть записи собеседований (список будет дан)
2. Выписывать вопросы, которые задают кандидату
Ставка: 450 руб. / час
Примерная ЗП: 54 000 руб. / месяц (4 часа в день)
Если интересно и можешь уделять работе от 4 часов / день, то отправь сообщение и сразу напиши какие языки программирования знаешь и какие лучше всего?
В разработке и программировании в целом
Message (или Message Passing) может использоваться в различных контекстах, не только при тестировании. Передача сообщений используется для имитации взаимодействий между объектами, проверки их поведения и создания мок-объектов. Использование XCTest для создания мок-объектов и проверки вызова методов.
class MockService: Service {
var didCallMethod = false
func someMethod() {
didCallMethod = true
}
} Используется для передачи сообщений от одного объекта к другому, часто через протоколы. Это позволяет одному объекту уведомлять другой о произошедших событиях. Использование делегатов в UITableView.
protocol TableViewDelegate: AnyObject {
func didSelectRow(at indexPath: IndexPath)
}
class TableView: UIView {
weak var delegate: TableViewDelegate?
// код для обработки выбора строки
} Используется для передачи сообщений между различными частями приложения. Это позволяет объектам взаимодействовать, не зная друг о друге. Отправка и получение уведомлений.
NotificationCenter.default.post(name: .someNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .someNotification, object: nil)
Позволяют передавать логические блоки кода как аргументы функций или методов. Это часто используется для обратных вызовов. Использование клоужеров для асинхронных операций.
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
// код для получения данных
completion(.success(data))
} Передача сообщений между различными процессами или приложениями, часто через специфические API и фреймворки. Использование XPC для общения между процессами.
let connection = NSXPCConnection(serviceName: "com.example.service")
connection.remoteObjectInterface = NSXPCInterface(with: ExampleProtocol.self)
Использование акторов и очередей для безопасной передачи сообщений между потоками. Использование DispatchQueue для выполнения задач асинхронно.
DispatchQueue.global().async {
// Асинхронная задача
DispatchQueue.main.async {
// Обновление UI
}
} Передача сообщений между клиентом и сервером с использованием протоколов HTTP, WebSocket и т.д. Использование URLSession для выполнения сетевых запросов.
let url = URL(string: "https://example.com/api")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// обработка ответа
}
task.resume()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Это концепция в разработке на платформе Apple (iOS, macOS), которая позволяет бесшовно использовать объекты из Core Foundation (C) в Swift или Objective-C и наоборот без затрат на преобразование. Это означает, что определенные типы данных из Core Foundation и соответствующие классы Foundation взаимозаменяемы.
Core Foundation: Фреймворк C, предоставляющий основные типы данных и службы.
Foundation: Фреймворк Objective-C и Swift, предоставляющий более высокоуровневые API.
Позволяет использовать объекты Core Foundation в API, ожидающих объекты Foundation, и наоборот.
Эти типы взаимозаменяемы, что позволяет использовать их взаимозаменяемо в функциях и методах.
let cfString: CFString = "Hello, World!" as CFString
let nsString: NSString = cfString as NSString
Эти типы также могут использоваться взаимозаменяемо.
let cfArray: CFArray = ["One", "Two", "Three"] as CFArray
let nsArray: NSArray = cfArray as NSArray
Взаимозаменяемость этих типов позволяет легко переключаться между ними.
let cfDictionary: CFDictionary = ["key": "value"] as CFDictionary
let nsDictionary: NSDictionary = cfDictionary as NSDictionary
Упрощает использование и интеграцию старых API Core Foundation с новыми API Foundation.
Отсутствие затрат на преобразование типов улучшает производительность.
Обеспечивает совместимость между кодом, написанным на C, Objective-C и Swift.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Это файл, содержащий отладочную информацию, используемую для сопоставления адресов в машинном коде с исходным кодом. В iOS и macOS разработке dSYM-файлы играют важную роль в процессе отладки и анализа сбоев (crash reports).
dSYM-файл содержит символы отладки, такие как имена методов и классов, которые соответствуют машинному коду скомпилированного приложения. Эта информация позволяет разработчикам интерпретировать сбои и ошибки, связывая их с исходным кодом.
dSYM-файлы автоматически создаются Xcode при сборке приложения. Они хранятся в специальной директории и могут быть включены в архив сборки (archive) для последующей загрузки в инструменты анализа сбоев.
Декодирование отчетов о сбоях: При сбое приложения, отчет о сбое содержит машинные адреса, которые трудно интерпретировать без символов отладки. dSYM-файл помогает преобразовать эти адреса в понятные строки исходного кода.
Инструменты анализа: Инструменты, такие как Xcode, Crashlytics, или другие платформы сбора и анализа сбоев, используют dSYM-файлы для декодирования и анализа отчетов о сбоях.
Отчеты о сбоях можно получить из Xcode, TestFlight, App Store Connect, или от пользователей.
Сервис анализа сбоев, такой как Crashlytics, запрашивает загрузку соответствующего dSYM-файла для декодирования отчетов. Обычно это можно сделать через интерфейс разработчика или автоматически при настройке сборочного процесса.
С помощью dSYM-файла отчет о сбое преобразуется в читаемый формат, содержащий строки исходного кода, где произошел сбой.
Всегда сохраняйте dSYM-файлы для каждой версии вашего приложения, так как они уникальны для каждой сборки.
Храните dSYM-файлы в безопасном месте (например, в системе управления версиями), чтобы всегда иметь доступ к нужной информации для анализа сбоев.
Убедитесь, что используемый dSYM-файл соответствует версии приложения, из которой получен отчет о сбое.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Sitable появляется в качестве новой функции, когда объект или пространство становится подходящим для использования. Это происходит благодаря изменению условий, которые делают его удобным или доступным. Например, помещение может стать sitable после установки мебели или проведения ремонта.
Файл с отладочной информацией для декодирования отчетов о сбоях. Он связывает машинный код с исходным кодом.
Имена методов и классов.
Декодирование отчетов о сбоях.
Пример:
Взаимозаменяемое использование объектов Core Foundation и Foundation в Swift и Objective-C без преобразования.
Связь: Использование объектов Core Foundation и Foundation.
Примеры:
CFStringRef и NSStringCFArrayRef и NSArrayCFDictionaryRef и NSDictionaryUITableView
let tableView = UITableView()
tableView.dataSource = self
UICollectionView
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.dataSource = self
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM