Быстрые перечисления с объективом-c [дубликат]

Краткий ответ: ваш метод foo() возвращается немедленно, а вызов $ajax() выполняется асинхронно после возврата функции . Проблема заключается в том, как и где сохранить результаты, полученные при вызове async, после его возврата.

В этом потоке было задано несколько решений. Возможно, самый простой способ - передать объект методу foo() и сохранить результаты в члене этого объекта после завершения асинхронного вызова.

function foo(result) {
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;   // Store the async result
        }
    });
}

var result = { response: null };   // Object to hold the async result
foo(result);                       // Returns before the async completes

Обратите внимание, что вызов foo() ] все равно не вернут ничего полезного. Однако результат асинхронного вызова теперь будет сохранен в result.response.

38
задан nhgrif 27 May 2015 в 11:49
поделиться

10 ответов

Из примечаний к выпуску Xcode 6.3 (выделено мной):

Улучшения языка Swift

... Теперь можно экспортировать Swift enums к Objective-C, используя атрибут @objc. @objc enums должны объявлять целочисленный тип raw и не могут быть общими или использовать связанные значения. Поскольку перечисления Objective-C не заменяются именами, случаи перечисления импортируются в Objective-C как конкатенация имени перечисления и имени.

39
ответ дан Martin R 27 August 2018 в 12:59
поделиться

Вот работа, если вы действительно хотите достичь цели. Однако вы можете получить доступ к значениям перечисления в объектах, которые Objective C принимает, а не как действительные значения enum.

enum LogSeverity : String {

    case Debug = "DEBUG"
    case Info = "INFO"
    case Warn = "WARN"
    case Error = "ERROR"

    private func string() -> String {
        return self.rawValue
    }
}

@objc
class LogSeverityBridge: NSObject {

    class func Debug() -> NSString {
        return LogSeverity.Debug.string()
    }

    class func Info() -> NSString {
        return LogSeverity.Info.string()
    }

    class func Warn() -> NSString {
        return LogSeverity.Warn.string()
    }

    class func Error() -> NSString {
        return LogSeverity.Error.string()
    }
}

Для вызова:

NSString *debugRawValue = [LogSeverityBridge Debug]
5
ответ дан BLC 27 August 2018 в 12:59
поделиться

Это мой прецедент:

  • Я избегаю жестко закодированных строк, когда могу, поэтому я получаю предупреждения компиляции, когда я что-то меняю
  • У меня есть фиксированный список значений String, исходящих из задней части, что также может быть nil

. Вот мое решение, которое вообще не содержит жестко закодированных строк, поддерживает отсутствующие значения и может использоваться элегантно в обоих Swift и Obj-C:

@objc enum InventoryItemType: Int {
    private enum StringInventoryItemType: String {
        case vial
        case syringe
        case crystalloid
        case bloodProduct
        case supplies
    }

    case vial
    case syringe
    case crystalloid
    case bloodProduct
    case supplies
    case unknown

    static func fromString(_ string: String?) -> InventoryItemType {
        guard let string = string else {
            return .unknown
        }
        guard let stringType = StringInventoryItemType(rawValue: string) else {
            return .unknown
        }
        switch stringType {
        case .vial:
            return .vial
        case .syringe:
            return .syringe
        case .crystalloid:
            return .crystalloid
        case .bloodProduct:
            return .bloodProduct
        case .supplies:
            return .supplies
        }
    }

    var stringValue: String? {
        switch self {
        case .vial:
            return StringInventoryItemType.vial.rawValue
        case .syringe:
            return StringInventoryItemType.syringe.rawValue
        case .crystalloid:
            return StringInventoryItemType.crystalloid.rawValue
        case .bloodProduct:
            return StringInventoryItemType.bloodProduct.rawValue
        case .supplies:
            return StringInventoryItemType.supplies.rawValue
        case .unknown:
            return nil
        }
    }
}
0
ответ дан Chris Garrett 27 August 2018 в 12:59
поделиться

Вот что я придумал. В моем случае это перечисление было в контексте, предоставляющем информацию для определенного класса, ServiceProvider.

class ServiceProvider {
    @objc enum FieldName : Int {
        case CITY
        case LATITUDE
        case LONGITUDE
        case NAME
        case GRADE
        case POSTAL_CODE
        case STATE
        case REVIEW_COUNT
        case COORDINATES

        var string: String {
            return ServiceProvider.FieldNameToString(self)
        }
    }

    class func FieldNameToString(fieldName:FieldName) -> String {
        switch fieldName {
        case .CITY:         return "city"
        case .LATITUDE:     return "latitude"
        case .LONGITUDE:    return "longitude"
        case .NAME:         return "name"
        case .GRADE:        return "overallGrade"
        case .POSTAL_CODE:  return "postalCode"
        case .STATE:        return "state"
        case .REVIEW_COUNT: return "reviewCount"
        case .COORDINATES:  return "coordinates"
        }
    }
}

Из Swift вы можете использовать .string в перечислении (аналогично .rawValue), , Из Objective-C вы можете использовать [ServiceProvider FieldNameToString:enumValue];

1
ответ дан Chris Prince 27 August 2018 в 12:59
поделиться

Вот решение, которое работает.

@objc public enum ConnectivityStatus: Int {
    case Wifi
    case Mobile
    case Ethernet
    case Off

    func name() -> String {
        switch self {
        case .Wifi: return "wifi"
        case .Mobile: return "mobile"
        case .Ethernet: return "ethernet"
        case .Off: return "off"
        }
    }
}
20
ответ дан David 27 August 2018 в 12:59
поделиться

У меня был прецедент, где мне все еще нужно было связать строковое значение со стороны Swift. Я написал о моем решении здесь: https://medium.com/@oscarcortes/using-swift-string-enums-in-objective-c-f6683da5b92e По существу, вы можете добавить метод в Swift enum, который возвращает строку, основанную на текущем значении перечисления.

0
ответ дан Oscar Cortes 27 August 2018 в 12:59
поделиться

Вы можете создать частное Inner перечисление. Реализация немного повторяема, но понятна и проста. 1 строка rawValue, 2 строки init, которые всегда выглядят одинаково. Inner имеет метод, возвращающий «внешний» эквивалент, и наоборот.

Имеет ли дополнительное преимущество то, что вы можете напрямую сопоставить случай перечисления с String, в отличие от других ответов здесь.

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

@objc enum MyEnum: NSInteger, RawRepresentable, Equatable {
    case
    option1,
    option2,
    option3

    // MARK: RawRepresentable

    var rawValue: String {
        return toInner().rawValue
    }

    init?(rawValue: String) {
        guard let value = Inner(rawValue: rawValue)?.toOuter() else { return nil }
        self = value
    }

    // MARK: Obj-C support

    private func toInner() -> Inner {
        switch self {
        case .option1: return .option1
        case .option3: return .option3
        case .option2: return .option2
        }
    }

    private enum Inner: String {
        case
        option1 = "option_1",
        option2 = "option_2",
        option3 = "option_3"

        func toOuter() -> MyEnum {
            switch self {
            case .option1: return .option1
            case .option3: return .option3
            case .option2: return .option2
            }
        }
    }
}
1
ответ дан paewel 27 August 2018 в 12:59
поделиться

Одно из решений заключается в использовании протокола RawRepresentable.

Не рекомендуется писать методы init и rawValue, но это позволяет вам использовать это перечисление, как обычно, в Swift и Objective-C.

@objc public enum LogSeverity: Int, RawRepresentable {
    case Debug
    case Info
    case Warn
    case Error

    public typealias RawValue = String

    public var rawValue: RawValue {
        switch self {
            case .Debug:
                return "DEBUG"
            case .Info:
                return "INFO"
            case .Warn:
                return "WARN"
            case .Error:
                return "ERROR"
        }
    }

    public init?(rawValue: RawValue) {
        switch rawValue {
            case "DEBUG":
                self = .Debug
            case "INFO":
                self = .Info
            case "WARN":
                self = .Warn
            case "ERROR":
                self = .Error
            default:
                self = .Debug
        }
    }
}
32
ответ дан Remy Cilia 27 August 2018 в 12:59
поделиться

Если вы не возражаете определить значения в (Objective) C, вы можете использовать макрос NS_TYPED_ENUM для импорта констант в Swift.

Например:

.h file

typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM;

FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;

.m file

ProgrammingLanguage ProgrammingLanguageSwift = "Swift";
ProgrammingLanguage ProgrammingLanguageObjectiveC = "ObjectiveC";

В Swift это импортируется как struct как таковое:

struct ProgrammingLanguage: RawRepresentable, Equatable, Hashable {
    typealias RawValue = String

    init(rawValue: RawValue)
    var rawValue: RawValue { get }

    static var swift: ProgrammingLanguage { get }
    static var objectiveC: ProgrammingLanguage { get }
}

Несмотря на то, что тип не соединяется с enum, он очень похож на тот, когда он используется в коде Swift.

Вы можете узнать больше об этом методе в разделе «Взаимодействие с API-интерфейсами C» в Использование Swift с документацией Cocoa и Objective-C

2
ответ дан RvdB 27 August 2018 в 12:59
поделиться

Код для Xcode 8, используя тот факт, что Int работает, но другие методы не подвергаются Objective-C. Это довольно ужасно, поскольку оно стоит ...

class EnumSupport : NSObject {
    class func textFor(logSeverity severity: LogSeverity) -> String {
        return severity.text()
    }
}

@objc public enum LogSeverity: Int {
    case Debug
    case Info
    case Warn
    case Error

    func text() -> String {
        switch self {
            case .Debug: return "debug"
            case .Info: return "info"
            case .Warn: return "warn"
            case .Error: return "error"
        }
    }
}
3
ответ дан shim 27 August 2018 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: