Проверка электронной почты и телефонов в Swift. Проверка свифт


ios - Проверка электронной почты и телефонов в Swift

Вы можете создать отдельный класс для проверки, как показано ниже:

enum AIValidationRule: Int { case EmptyCheck, MinMaxLength, FixedLength, EmailCheck, UpperCase, LowerCase, SpecialCharacter, DigitCheck, WhiteSpaces, None

}

let ValidationManager = AIValidationManager.sharedManager func validateTextField(txtField:AITextField, forRule rule:AIValidationRule, withMinimumChar minChar:Int, andMaximumChar maxChar:Int) -> (isValid:Bool, errMessage:String, txtFieldWhichFailedValidation:AITextField)? { switch rule { case .EmptyCheck: return (txtField.text?.characters.count == 0) ? (false,"Please enter \(txtField.placeholder!.lowercased())",txtField) : nil case .MinMaxLength: return (txtField.text!.characters.count < minChar || txtField.text!.characters.count > maxChar) ? (false,"\(txtField.placeholder!) should be of \(minChar) to \(maxChar) characters",txtField) : nil case .FixedLength: return (txtField.text!.characters.count != minChar) ? (false,"\(txtField.placeholder!) should be of \(minChar) characters",txtField) : nil case .EmailCheck: return (!(txtField.text?.isValidEmail())!) ? (false,"Please enter valid email",txtField) : nil case .UpperCase: return ((txtField.text! as NSString).rangeOfCharacter(from: NSCharacterSet.uppercaseLetters).location == NSNotFound) ? (false,"\(txtField.placeholder!) should contain atleast one uppercase letter",txtField) : nil case .LowerCase: return ((txtField.text! as NSString).rangeOfCharacter(from: NSCharacterSet.lowercaseLetters).location == NSNotFound) ? (false,"\(txtField.placeholder!) should contain atleast one lowercase letter",txtField) : nil case .SpecialCharacter: let symbolCharacterSet = NSMutableCharacterSet.symbol() symbolCharacterSet.formUnion(with: NSCharacterSet.punctuationCharacters) return ((txtField.text! as NSString).rangeOfCharacter(from: symbolCharacterSet as CharacterSet).location == NSNotFound) ? (false,"\(txtField.placeholder!) should contain atleast one special letter",txtField) : nil case .DigitCheck: return ((txtField.text! as NSString).rangeOfCharacter(from: NSCharacterSet(charactersIn: "0123456789") as CharacterSet).location == NSNotFound) ? (false,"\(txtField.placeholder!) should contain atleast one digit letter",txtField) : nil case .WhiteSpaces: return (txtField.text!.containsAdjacentSpaces() || txtField.text!.isLastCharcterAWhiteSpace()) ? (false,"\(txtField.placeholder!) seems to be invalid",txtField) : nil case .None: return nil } } func validateTextField(txtField:AITextField, forRules rules:[AIValidationRule]) -> (isValid:Bool, errMessage:String, txtFieldWhichFailedValidation:AITextField)? { return validateTextField(txtField: txtField, forRules: rules, withMinimumChar: 0, andMaximumChar: 0) } func validateTextField(txtField:AITextField, forRules rules:[AIValidationRule], withMinimumChar minChar:Int, andMaximumChar maxChar:Int) -> (isValid:Bool, errMessage:String, txtFieldWhichFailedValidation:AITextField)? { var strMessage:String = "" for eachRule in rules { if let result = validateTextField(txtField: txtField, forRule: eachRule, withMinimumChar: minChar, andMaximumChar: maxChar) { if(eachRule == AIValidationRule.EmptyCheck){ return result }else{ strMessage += "\(strMessage.characters.count == 0 ? "" : "\n\n") \(result.errMessage)" } } } return strMessage.characters.count > 0 ? (false,strMessage,txtField) : nil }

qaru.site

Проверка внедрения зависимостей на Swift / Блог компании Tinkoff.ru / Хабр

Проект с Dependency Injection похож на елочную гирлянду — он красив, радует детей и взрослых. Но если где-то не внедрить зависимость, отключится целый сегмент приложения. И, чтобы найти источник проблем, придется проверять все зависимости в этом сегменте.

В этой статье описаны несколько вариантов поиска пустых зависимостей. А в нашем репозитории есть небольшая библиотека, которая поможет в этом: TinkoffCreditSystems/InjectionsCheck

Внедрение зависимостей в Init

Объявить все зависимости как non-optional и внедрить их в Init — это самый надежный способ.

class TheObject: IObjectProtocol { var service: IService init( _ service: IService) { self.service = service } }

Плюсы:

  • Проект не соберется, если что-то забыли инициализировать.
  • Компилятор укажет, что и где забыли.

Минусы:

  • Невозможно использовать циклические зависимости.
  • Много параметров в Init.
  • Нельзя внедрить зависимости во ViewController и подобные объекты.

Проверка зависимостей в Тестах и DI-контейнере

Можно использовать тесты, чтобы проверить, все ли зависимости на месте. Но следить за ними сложнее, чем за объектами, поэтому нужен простой способ поддерживать такие тесты в актуальном состоянии. С этим поможет функция, которая проверяет все optional-свойства объекта и сообщает об ошибке, если находит nil.

Чтобы быть уверенными, что тесты не пропустят пустые зависимости, необходимо заставить их проверять всё, кроме зависимостей из списка исключений. Проще поддерживать список исключений, чем список свойств, которые надо проверять. Если исключение не будет прописано, тест провалится, и это будет заметно.

Плюсы:

  • Больше свободы во внедрении зависимостей.
  • Можно внедрять зависимости про протоколу.

Минусы:

  • Нужно запускать тесты, чтобы убедиться, что ничего не забыли.
  • Все проверяемые объекты должны быть в тестах.
  • Для зависимостей нужно использовать guard или service?.doSomething.

В Swift эту функцию можно создать с помощью рефлексии и класса Mirror. Он позволяет обойти все свойства и посмотреть их значения.

func checkInjections(of object: Any) { print(“Properties of \(String(reflecting: object))”) for child in Mirror(reflecting: object).children { print(“\t\(child.label) = \(child.value)”) } }

label: String — имя свойства,value: Any — значение, которое может быть nil.

Но есть одна неприятность:

if child.value == nil { // Ошибка компиляции }

Swift не дает сравнить Any с nil. Формально он прав, ведь «Any» и «Any?» — разные типы. Поэтому нужно снова воспользоваться классом Mirror, чтобы найти в Any финальный Optional и узнать, равен ли он nil.

fileprivate func unwrap<ObjectType: Any>(_ object: ObjectType) -> ObjectType? { let mirror = Mirror(reflecting: object) guard mirror.displayStyle == .optional else { return object } guard let child = mirror.children.first else { return nil } return unwrap(any: child.value) as? ObjectType }

Рекурсия используется из-за того, что в Any может быть вложенный Optional, например, IService??.. Результат этой функции выдаст обычный Optional, который можно сравнить с nil.

Список исключений для свойств

Для некоторых объектов не все свойства нужно проверять на nil, поэтому добавим список свойств-исключений. Из-за того, что child.label — это строка, задать исключения можно только так:

  • Массив имен свойств [String]
  • Массив селекторов #Selector(keypath:)(только для свойств с objc)
  • Массив ключей #keyPath()(только для свойств с objc)
Почему нельзя использовать Swift 4 KeyPath

Swift 4 KeyPath позволяет получить значение по ключу — объекту, а не строке. Сейчас невозможно получить имя свойства в виде строки. И нельзя получить полный список всех KeyPath, чтобы пройтись по ним.

Используем протокол SelectorName, чтобы поддержать все варианты без приведения типа, а также enum:

protocol SelectorName { var value: String } class TheObject: IObjectProtocol { var notService: INotService? enum SelectorsToIgnore: String, SelectorName { case notService } }Поддержка протокола SelectorName для String, Selector, и RawRepresentableextension String: SelectorName { var value: String { return self } } extension Selectoe: SelectorName { var value: String { return String(describing: self) } } extension SelectorName where Self: RawRepresentable, RawType == String { var valur: String { return self.rawValue } }

Итоговый код функции для проверки внедрения зависимостей будет выглядеть так:

func checkInjectionsenum InjectionCheckError: Error { case notInjected(properties: [String], in: Any) } public func checkInjections<ObjectType>( _ object: ObjectType, ignoring selectorsToIgnore: [SelectorName] = [] ) throws -> ObjectType { let selectorsSet = Set<String>(selectorsToIgnore.flatMap { $0.stringValue } ) let mirror = Mirror(reflecting: object) var uninjectedProperties: [String] = [] for child in mirror.children { guard let label = child.label, !selectorsSet.contains(label), unwrap(child.value) == nil else { continue } uninjectedProperties.append(label) } guard uninjectedProperties.count == 0 else { let error = InjectionCheckError.notInjected(properties: uninjectedProperties, in: object) throw error } return object }

Forced Unwrap зависимости

Зависимости можно объявить как Force unwraped:

class TheObject: IObjectProtocol { var service: IService! }

Плюсы:

  • Приложение сразу падает, если находится nil.
  • Лог ошибки указывает, что и где было nil.
  • Удобно использовать зависимости.

Минусы:

  • Приложение падает.
  • Можно пропустить в production код, который будет падать.
  • В приложении надо найти место с пустыми зависимостями, чтобы оно упало.

Падение приложения создает негативный пользовательский опыт. Как в примере с гирляндами: получится лампочка, которая ярко взрывается, если перегорает. Скорее всего, такая пустая зависимость пройдет мимо разработчика и тестировщика, если она отвечает за не очень важную или редко используемую функцию, а приложение способно работать, хоть и с ограниченной функциональностью.

Например, без форматировщика номера телефона в списке заказов приложение будет работоспособно, выведет остальную информацию, а не упадет. И, конечно же, сообщит разработчикам о проблеме.

Проверки на выходе из DI-контейнера + падение в debug-режиме

В Swift есть условная компиляция, что позволяет использовать философию Force unwrapped-зависимостей только в Debug-режиме. Условия компилятора позволяют сделать функцию, которая вызовет fatalError в режиме отладки, если найдет пустые зависимости. И ее удобно использовать на выходе из сервис-локатора, Assembly или фабрики.

Плюсы:

  • Работает без запуска тестов.
  • Приложение падает только в debug-режиме.
  • Лог ошибки укажет, что и где было nil.
  • Встроить в проект просто.

Минусы:

  • Все проверяемые объекты должны пройти через функцию.
  • Для зависимостей нужно использовать guard или service?.doSomething.
  • Тестирование релизной сборки может выявить ошибки только по логам.

Эта функция-обертка проверяет зависимости объекта и роняет его с ошибкой, если для компилятора задан флаг -DDEBUG или -DINJECTION_CHECK_ENABLED. В остальных случая тихо пишет в лог:

@discardableResult public func debugCheckInjections<ObjectType>( _ object: ObjectType, ignoring selectorsToIgnore: [IgnorableSelector] = [], errorClosure: (_ error: Error) -> Void = { fatalError("Injection check error: \($0)") }) -> ObjectType? { do { let object = try checkInjections(object, ignoring: selectorsToIgnore) return object } catch { #if DEBUG || INJECTION_CHECK_ENABLED errorClosure(error) #else print("Injection check error: \(error)") #endif return nil } }

Вместо заключения

У всех способов есть свои плюсы и минусы. В зависимости от проекта, команды, устоявшихся принципов работы будет лучше работать тот или иной способ.

Я предпочитаю не внедрять зависимости через Init, потому что так невозможно внедрить во ViewController зависимости, которые создаются из Storyboard. И это усложняет рефакторинг и внесение изменений.

Forced Unwrap не используется не только для управления зависимостями, но и в production вообще. У SwiftLint даже активировано правило ‘force_unwrapping’, которое не дает его использовать.

Проверка зависимостей в тестах хорошо работает для поддержки старого кода. Гарантирует, что старые зависимости не пропали, и все продолжает работать. Но неудобна для текущей разработки.

Поэтому я предпочитаю проверку на выходе из DI-контейнера с падением в Debug-режиме. Так быстрее всего можно обнаружить пустые зависимости и сразу их исправить.

Все представленные здесь функции есть в библиотеке:TinkoffCreditSystems/InjectionsCheck

habr.com

swift - Проверка соответствия класса Swift протоколу и реализации необязательной функции?

Вы все еще думаете в Objective-C, обнимаете Swift!

Предполагая, что ваш протокол выглядит следующим образом:

@objc protocol SKPhysicsContactDelegate { optional func didBeginContact() }

Попробуйте следующее:

if let delegate = gameScene as? SKPhysicsContactDelegate { delegate.didBeginContact?() }

Или один лайнер:

(gameScene as? SKPhysicsContactDelegate)?.didBeginContact?()

Обратите внимание на ? после имени метода в вызове? Это потому, что этот метод является необязательным, и он не будет вызван, если объект не реализует этот метод. А ветвь if let не будет выполнена, если объект не соответствует протоколу SKPhysicsContactDeletegate.

Проверить существование метода без вызова

Чтобы проверить существование самого метода перед вызовом, просто опустите вызов метода, чтобы получить ссылку на этот метод и проверьте его как любую другую переменную:

if let method = (gameScene as? SKPhysicsContactDelegate)?.didBeginContact { print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact") // Call it later whenever you want method() }

Если вам не нужно называть его позже, просто проверьте nil:

if (gameScene as? SKPhysicsContactDelegate)?.didBeginContact != nil { print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact") }

Проверить статические методы

Проверка методов optional static использует тот же подход, но требует объект класса вместо экземпляра класса:

if (GameScene.self as? OptionalProtocol.Type)?.staticMethod != nil { print("gameScene conforms to OptionalProtocol and implements staticMethod") }

Обратите внимание на GameScene.self для получения типа объекта и <protocol>.Type для передачи в класс протокола вместо экземпляра протокола.

Полный образец

Прикрепленный образец для игровых площадок, Swift script или любой онлайн Swift:

import Foundation @objc protocol OptionalProtocol { optional func instanceMethod() optional static func staticMethod() } class Nothing {} class Something: OptionalProtocol {} class Bar: NSObject, OptionalProtocol { func instanceMethod() { print("Instance method") } } class Foo: NSObject, OptionalProtocol { static func staticMethod() { print("Static method") } } // Cast instances to 'Any' and classes to 'AnyClass' let nothing: Any = Nothing() let nothingClass: AnyClass = Nothing.self let something: Any = Something() let somethingClass: AnyClass = Something.self let bar: Any = Bar() let barClass: AnyClass = Bar.self let foo: Any = Foo() let fooClass: AnyClass = Foo.self nothing is OptionalProtocol // false (nothing as? OptionalProtocol)?.instanceMethod != nil // false (nothing as? OptionalProtocol)?.instanceMethod?() // Does nothing (nothingClass as? OptionalProtocol.Type)?.staticMethod != nil // false (nothingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing something is OptionalProtocol // true (something as? OptionalProtocol)?.instanceMethod != nil // false (something as? OptionalProtocol)?.instanceMethod?() // Does nothing (somethingClass as? OptionalProtocol.Type)?.staticMethod != nil // false (somethingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing bar is OptionalProtocol // true (bar as? OptionalProtocol)?.instanceMethod != nil // true (bar as? OptionalProtocol)?.instanceMethod?() // Prints 'Instance method' (barClass as? OptionalProtocol.Type)?.staticMethod != nil // false (barClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing foo is OptionalProtocol // true (foo as? OptionalProtocol)?.instanceMethod != nil // false (foo as? OptionalProtocol)?.instanceMethod?() // Does nothing (fooClass as? OptionalProtocol.Type)?.staticMethod != nil // true (fooClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Prints 'Static method'

qaru.site

Контроль подлинности сообщений SWIFT

Контроль подлинности сообщений SWIFT

7 апреля в 11:00 по московскому времени Центр Финансовых Технологий проведет вебинар на тему «Контроль подлинности сообщений SWIFT».

На мероприятие приглашаются руководители и сотрудники Расчетного центра, ИТ-специалисты, банковские технологи и специалисты по информационной безопасности.

Одной из важнейших задач кредитной организации при проведении межбанковских расчетов по системе SWIFT является исключение несанкционированных изменений сообщений SWIFT.

В информационном комплексе ЦФТ-Банк реализована возможность контроля подлинности сообщений SWIFT и SWIFT-RUR методом LAU (local authentication). Данное решение позволяет выявлять переводы SWIFT и SWIFT-RUR, искаженные при передаче между ЦФТ-Банк и интерфейсом SWIFT Alliance Access, а также исключает обмен сообщениями в открытом виде. В качестве средства проверки подлинности используется контрольная сумма, рассчитываемая в ЦФТ-Банк и SWIFT Alliance Access по алгоритму HMAC-SHA256.

Список вопросов вебинара:

  • Управление параметрами безопасного обмена по системе SWIFT
  • Защита исходящего потока сообщений
  • Защита входящего потока сообщений

Докладчик на мероприятии – Татьяна Котова, ведущий инженер-технолог дирекции «Расчеты».

Продолжительность вебинара – 1-1,5 часа.

Просмотреть или скачать материалы мероприятия можно ниже: * Для просмотра записи нужен актуальный проигрыватель, скачать для Windows (формат *.arf или формат *.wrf) или скачать для Mac OS (формат *.arf или формат *.wrf).

При возникновении вопросов просьба обращаться по адресу [email protected]

www.cft.ru