Краткий ответ: ваш метод 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
.
Из примечаний к выпуску Xcode 6.3 (выделено мной):
Улучшения языка Swift
... Теперь можно экспортировать Swift enums к Objective-C, используя атрибут @objc. @objc enums должны объявлять целочисленный тип raw и не могут быть общими или использовать связанные значения. Поскольку перечисления Objective-C не заменяются именами, случаи перечисления импортируются в Objective-C как конкатенация имени перечисления и имени.
blockquote>
Вот работа, если вы действительно хотите достичь цели. Однако вы можете получить доступ к значениям перечисления в объектах, которые 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]
Это мой прецедент:
. Вот мое решение, которое вообще не содержит жестко закодированных строк, поддерживает отсутствующие значения и может использоваться элегантно в обоих 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
}
}
}
Вот что я придумал. В моем случае это перечисление было в контексте, предоставляющем информацию для определенного класса, 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];
Вот решение, которое работает.
@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"
}
}
}
У меня был прецедент, где мне все еще нужно было связать строковое значение со стороны Swift. Я написал о моем решении здесь: https://medium.com/@oscarcortes/using-swift-string-enums-in-objective-c-f6683da5b92e По существу, вы можете добавить метод в Swift enum, который возвращает строку, основанную на текущем значении перечисления.
Вы можете создать частное 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
}
}
}
}
Одно из решений заключается в использовании протокола 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
}
}
}
Если вы не возражаете определить значения в (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
Код для 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"
}
}
}