Мы рады поделиться еще одним релизом Swiftify, который сделает вашу жизнь немного проще. На этот раз мы рассмотрим различия между тем, как Objective-C и Swift обрабатывают типы.

Введите приведение для объявлений цикла

Objective-C накладывает очень мало ограничений на приведение типов. При попытке выполнить операции над объектами в NSArray вы можете сделать что-то вроде этого:

- (void)loopOverStrings:(nonnull NSArray *)stringArray {
    for (NSString *string in stringArray) {
        [self doWorkOnString:string];
    }
}
 
- (void)doWorkOnString:(NSString *)string {
 // ...   
}

В этом коде нигде не говорится, что stringArray на самом деле является массивом строк. Но Objective-C по-прежнему позволит вам преобразовывать объекты в stringArray в NSString.

Swift не допускает такого рода неявное преобразование. Попытка привести объекты в stringArray к типу String вернет необязательное значение, если это не удастся. Наш последний релиз обрабатывает приведение типов следующим образом:

func loopOverStrings(_ stringArray: [Any]) {
    for string: String in stringArray as? [String] ?? [String]() {
        doWork(on: string)
    }
}
func doWork(on string: String?) {
}

Обратите внимание, что поскольку Objective-C stringArray не указывает тип своих объектов, версия Swift — [Any]. В объявлении цикла for мы приводим массив к [String].

Вы можете поиграть с этим примером здесь:



Неявное приведение к логическому значению

Что общего между 0, NO и nil в Objective-C?

Все они эквивалентны логическому значению false.

Это немного упрощение, но оно работает для следующей проблемы:

NSInteger var1 = -512;
NSInteger var2 = 512;
if (var1 + var2) {
   NSLog(@"Sum is not zero");
}

Тело оператора if не будет выполнено, поскольку var1 + var2 == 0. 0 в Objective-C эквивалентен false, поэтому тело не выполняется. Если бы значение было отрицательным или положительным, оно равнялось бы true.

Мы исправляем эту причуду в последней версии:

var var1: Int = -512
var var2: Int = 512
if var1 + var2 != 0 {
    print("Sum is not zero")
}

Это доступно для вас, чтобы попробовать на нашем сайте.



В том же духе мы можем проверить, является ли объект нулевым в Objective-C, следующим образом:

- (NSString *)resultMessageForData:(NSData *)data {
    return data ? @"Operation succeeded!" : @"Operation failed.";
}

Если data не равно нулю, метод вернет «Операция выполнена успешно!». Если он равен нулю, вместо этого будет возвращено «Операция не удалась».

В преобразовании Swift нам нужно напрямую сравнить data с nil, потому что Swift не сделает этого за нас.

func resultMessage(for data: Data?) -> String? {
    return data != nil ? "Operation succeeded!" : "Operation failed."
}

Попробуйте здесь:



Необязательные параметры в интерполированных строках

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

func logDate(date: Date?) {
  print("The date is \(date)")
}

Вы можете ожидать такой вывод:

The date is 2018-04-16 11:40:36 +0000

Но Swift не делает никаких предположений о типе объектов: вы передаете ему необязательное значение, и он печатает его как таковое.

The date is Optional(2018-04-16 11:40:36 +0000)

Когда наш преобразователь увидит такой код:

- (NSString *)greetingForName:(NSString *)name {
    return [NSString stringWithFormat: @"Hello there, %@.", name];
}

Это разумно развернет необязательный для вас.

func greeting(forName name: String?) -> String? {
    return "Hello there, \(name ?? "")."
}

Попробуйте:



Что бы вы хотели видеть от Swiftify?

Видели ли вы какие-либо дела, которые хотели бы автоматизировать с помощью Swiftify? Дайте нам знать в комментариях ниже!