Некоторые полезные фрагменты кода, которые я постоянно использую в проектах
По мере того, как мы приближаемся к WWDC 2022 и, возможно, к версии 4.0 SwiftUI, фреймворка, с которым мне посчастливилось играть почти столько же, сколько он существует, я подумал, что могу опубликовать небольшую коллекцию расширений, которые я использую снова и снова. . Я надеюсь, что некоторые из них войдут в следующий выпуск.
1. Скрыть
Это модификатор представления, который позволяет отображать или скрывать представления, которые обычно недоступны. Стоит отметить, что модификатор представления — очень полезный паттерн, который вам не мешало бы запомнить.
Это вы используете просто как модификатор в своем представлении, переменная условия - это просто логическое значение.
.modifier(Show(isVisible: condition))
Это работает хорошо, но, как вы заметите, освобождает место на view
и вызывает перерисовку — так что это удар по производительности. Кроме того, вы всегда можете использовать вкладку opacity
, чтобы получить аналогичный эффект. Он будет работать быстрее, но не освободит место, которое вы использовали.
2. Филиал
Этот модификатор, с которым я столкнулся, является идеальным решением для управления включением/исключением атрибутов.
extension View { @ViewBuilder func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View { if condition { transform(self) } else { self } } }
Код, который вы используете таким образом, опять же с переменной, окрашенной в этом примере.
.if(colored) { view in view.background(Color.blue) }
3. Печать
Если вы новичок в SwiftUI, первое, что вас зацепит, это print
. Это может быть динозавр методов отладки, но они все еще преподают его в классах, и обнаружить, что вы не можете использовать его в представлениях SwiftUI, болезненно. Итак, этот фрагмент кода бесценен.
extension View {
func Print(_ vars: Any...) -> some View {
for v in vars { print(v) }
return EmptyView()
}
}
Это позволяет вам использовать подобный оператор в вашем коде.
self.Print("Inside ForEach", varOne, varTwo ...)
4. Задержка
Это только что изменилось в iOS15, и, хотя это не SwiftUI как таковой, это определенно то, что вы делаете в своем коде.
extension Task where Success == Never, Failure == Never { static func sleep(seconds: Double) async throws { let duration = UInt64(seconds * 1000_000_000) try await sleep(nanoseconds: duration) } }
Конечно, код, который вы хотите запустить после задержки, должен следовать Task
, который сам создает задержку.
Task { try! await Task.sleep(seconds: 0.5) }
5. PassThruSubjects
Когда я начал использовать Combine
со SwiftUI, я обнаружил, что PassThroughSubjects
очень полезный способ связать старое с новым. Я написал статью об их использовании с покупками в приложении, но они не идеальны, и я часто срабатываю более одного раза, когда вы отправляете их. Этот код может помочь вам решить эту проблему.
let changeColor = PassthroughSubject<Int,Never>()
Код, который вы используете, выглядит следующим образом:
.onReceive(signalButton .eraseToAnyPublisher() .throttle(for: .milliseconds(10), scheduler: RunLoop.main, latest: true)) { value in if value == 2 { button2 = true levelColor = Color.red } }
В данном случае с подпрограммой calling
число, используемое здесь, позволяет мне назвать одну тему, чтобы я мог запускать несколько ветвей в одном и том же коде SwiftUI.
changeColor.send(3)
6. Подписки
Еще одна альтернатива запуску кода, хотя и не SwiftUI, — бесценный элемент, который я неоднократно использовал в своем коде SwiftUI. Вы настраиваете его с помощью этого кода:
let cameraGesture = PassthroughSubject<cameraActions,Never>() var cameraSubscription:AnyCancellable? = nil
Затем используются два объявления combine
следующим образом:
cameraSubscription = cameraGesture .eraseToAnyPublisher() .throttle(for: .milliseconds(10), scheduler: RunLoop.main, latest: true) .sink(receiveValue: { value in // do something with the value })
Отправив сообщение combine
, как и раньше.
cameraGesture.send(._1orbitTurntable)
7. Таймер
publisher
— отличный способ создать таймер. Я обнаружил, что использую его почти в каждом проекте, который придумываю.
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
Вот код.
Примечание. У меня есть значение времени в переменной _ unused
. Это, в отличие от send
, работает более надежно, так как отправляет одно сообщение, а не кучу.
.onReceive(timer) { _ in // do something }
8. Координаты/размер
Я никак не могу вспомнить, что я имел в виду, поэтому вот пример. Это также немного сложно, потому что размер, который он возвращает, является родительским, а не дочерним, в котором вы его используете.
Таким образом, вы обычно используете его в качестве фона. Вот как вернуть размер представления с помощью этой команды:
.background(returnSize())
9. Строки атрибутов
Супер полезное расширение, которое я наткнулся на Stack Overflow; он применяется к атрибутам в объектах Text
iOS 15.
Вы можете использовать приведенные выше фрагменты следующим образом:
Text("GAME OVER") { $0.kern = CGFloat(2) }
С такого рода параметрами вы можете подробно дополнить эту статью.
10. Любой вид
Далее идет исправление для этого сообщения SwiftUI, жалующегося на несовпадающие представления. Хотя я обычно не рекомендую использовать AnyView
, иногда кажется, что другого решения просто нет.
extension View {
func eraseToAnyView() -> AnyView {
AnyView(self)
}
}
Вот пример расширения, в котором я хочу вернуть текстовый элемент или изображение:
11. Подстрочный индекс
Это расширение позволяет вам индексировать строку; он использует стандарт, который существует уже давно
Вы можете использовать код так же, как и на других языках.
let word = "Start" for i in 0..<word.length { print(word[i]) }
12. Обнаружение сотрясения
Я постоянно ищу этот код Google. Кто помнит эту последовательность?
Вы можете создать расширение следующим образом:
.onShake { print("stop it shaking") }
13. Сделайте снимок вида
Этот драгоценный камень взят с веб-сайта HWS; это отличный источник всего, что происходит на скорую руку.
Вы можете использовать его следующим образом:
let image = textView.snapshot().ignoresSafeArea
14. Сохранение/загрузка изображений
Если вы нашли это на портале разработчиков Apple; это пригодится.
В расширении вы можете использовать такой код:
@State private var image = UIImage(systemName: "xmark")! private var url: URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0].appendingPathComponent("image.jpg")} var body: some View { Image(uiImage: image) .onAppear { url.load(&image) } .onTapGesture { url.save(image) } }
15. Список шрифтов
Почти в конце. Этот следующий полезен.
let fontFamilyNames = UIFont.familyNames for familyName in fontFamilyNames { print("Font Family Name = [\(familyName)]") let names = UIFont.fontNames(forFamilyName: familyName) print("Font Names = [\(names)]") }
С кодом SwiftUI вы можете найти такие шрифты:
struct Fonts { static func avenirNextCondensedBold (size: CGFloat) -> Font { return Font.custom("AvenirNextCondensed-Bold", size: size) }
Вы вызовете эту конструкцию, чтобы использовать код:
.font(Fonts.avenirNextCondensedBold(size: 12))
16. Тернарный оператор
Это последнее расширение можно использовать во многих областях SwiftUI, но я никак не могу вспомнить синтаксис.
Здесь тернарный оператор оценивает condition
и
- если
condition
равноtrue
, выполняетсяexpression1
. - если
condition
равноfalse
, выполняетсяexpression2
.
Тернарный оператор принимает три операнда (condition
, expression1
и expression2
). Отсюда и название тернарный оператор.
flipColor = flipColor == .blue ? .green : .blue
Итак, если flipColor
равно blue
, я получу обратно green
, а если flipColor
равно green
, я получу обратно blue
.
Все это подводит меня к концу этого списка. Надеюсь, вы нашли здесь несколько полезных фрагментов.
Спасибо за прочтение!