如何将iPhone OSStatus代码转换为有用的东西?

mat*_*att 65 macos error-handling cocoa cocoa-touch ios

我对这款iPhone SDK及其文档感到有点不舒服......

我打电话给AudioConverterNew

在返回下的文档中:它说"返回状态代码"......真的......

到目前为止,通过玩这些参数我只能得到两个不同的错误,这两个错误都没有列在音频转换器参考的底部.

它们是'mrep'和'?tmf'(将OSStatus转换为char数组)但具体代码并不是真正重要的.

据我所知,随机错误代码是在随机文件中定义的,因此您不能只搜索一个文件,我找不到只是让您搜索错误代码以获取更多信息的帮助文档,并且我可以告诉你,在OS X中,你可以使用GetMacOSStatusErrorString()将错误转换为有用的东西,但没有iPhone等价?

任何帮助将不胜感激.

编辑:

好的,所以投射它们反过来(我检查'mrep',但不是那里的任何一种方式),fmt?在音频转换器api的列表中,如果有点模糊,但是很公平,仍然'perm'不存在(尽管它可能与模拟器不支持aac解码有关)和我的一般问题仍然存在.

tom*_*omk 88

OSStatus是带符号的整数值.您无法将其转换或"转换"为字符串.您可以将它转换为NSError,如下所示:

NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil];

  • 这个问题很老,但我会说这是正确的答案.然后你可以获得一个令人满意的字符串,例如`2012-11-05 22:28:52.338 foo [7300:707]错误域= NSOSStatusErrorDomain代码= -43"操作无法完成.(OSStatus错误-43.) "(fnfErr:找不到档案)` (6认同)
  • 对于许多错误,您无法获得超出"操作无法完成"的任何内容.这个答案和被接受的答案的组合效果很好. (5认同)

ken*_*ytm 30

不,不完全.

一些OSStatus是四字符代码,因此您可以使用(从iPhone SDK的示例代码" CAXException.h"中提取)

static char *FormatError(char *str, OSStatus error)
{
    // see if it appears to be a 4-char-code
    *(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error);
    if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
        str[0] = str[5] = '\'';
        str[6] = '\0';
    } else {
        // no, format it as an integer
        sprintf(str, "%d", (int)error);
    }
    return str;
}
Run Code Online (Sandbox Code Playgroud)

(参见iOS/C:将"整数"转换为四个字符串,以获得将fourcc转换为字符串的更多方法,包括Swift)

NSError的NSOSStatusErrorDomain能够解码一些操作系统错误.请参阅@ tomk的回答.

如果您不需要为用户解码程序中的数字,您可以使用该macerror脚本手动找出其含义,如@ lros的答案中所述.支持的OSStatus列表可以从其源代码中找到/System/Library/Perl/Extras/5.18/Mac/Errors.pm.

还有一个在线服务http://osstatus.com/收集所有公共框架的错误.它们仍然不完整,例如-12792缺少评论中提到的映射.可能它是来自私有框架的代码.

  • @tomk:(1)您是否意识到这段代码来自[官方Apple示例代码](http://developer.apple.com/library/ios/#samplecode/SpeakHere/Listings/iPublicUtility_CAXException_h.html)?(2)你怎么能确定开发者发明的OSStatus不想使用4字节作为存储4个字符的紧凑方式?我确定**这是真的,因为[OSType](http://en.wikipedia.org/wiki/OSType)来自Mac OS. (6认同)

小智 13

我最近遇到了另一种方法:macerror命令.将OSStatus值打印为带符号整数.然后在终端窗口(在Mac上,而不是你的iDevice!)类型,例如macerror -50.它将以简短的描述作出回应.显然,这只对您在开发过程中有所帮助.


Ech*_* Lu 11

这是我写的代码,希望它能为你节省一些打字...呃,不知道怎么让它显示正确.

- (NSString *)OSStatusToStr:(OSStatus)st
{
    switch (st) {
        case kAudioFileUnspecifiedError:
            return @"kAudioFileUnspecifiedError";

        case kAudioFileUnsupportedFileTypeError:
            return @"kAudioFileUnsupportedFileTypeError";

        case kAudioFileUnsupportedDataFormatError:
            return @"kAudioFileUnsupportedDataFormatError";

        case kAudioFileUnsupportedPropertyError:
            return @"kAudioFileUnsupportedPropertyError";

        case kAudioFileBadPropertySizeError:
            return @"kAudioFileBadPropertySizeError";

        case kAudioFilePermissionsError:
            return @"kAudioFilePermissionsError";

        case kAudioFileNotOptimizedError:
            return @"kAudioFileNotOptimizedError";

        case kAudioFileInvalidChunkError:
            return @"kAudioFileInvalidChunkError";

        case kAudioFileDoesNotAllow64BitDataSizeError:
            return @"kAudioFileDoesNotAllow64BitDataSizeError";

        case kAudioFileInvalidPacketOffsetError:
            return @"kAudioFileInvalidPacketOffsetError";

        case kAudioFileInvalidFileError:
            return @"kAudioFileInvalidFileError";

        case kAudioFileOperationNotSupportedError:
            return @"kAudioFileOperationNotSupportedError";

        case kAudioFileNotOpenError:
            return @"kAudioFileNotOpenError";

        case kAudioFileEndOfFileError:
            return @"kAudioFileEndOfFileError";

        case kAudioFilePositionError:
            return @"kAudioFilePositionError";

        case kAudioFileFileNotFoundError:
            return @"kAudioFileFileNotFoundError";

        default:
            return @"unknown error";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用宏和字符串化,可以节省更多的打字时间。 (2认同)

iOS*_*com 10

这适用于macOS和iOS 11.3及以上版本.

我知道这是一个旧帖子,但我正在阅读与钥匙链相关的部分中的苹果文档.他们提到了一种用于将OSStatus错误转换为可读内容的方法.

SecCopyErrorMessageString

返回一个解释安全结果代码含义的字符串.

SecCopyErrorMessageString(OSStatus status,void*reserved);

用途:

NSString* ErrMsg = (__bridge_transfer NSString *) SecCopyErrorMessageString(theOSStatusError, NULL);
Run Code Online (Sandbox Code Playgroud)

我的钥匙串OSStatus错误对我有用.对你起作用吗?您需要将Security.Framework添加到项目中才能使用此方法.

  • 不幸的是,iOS上不存在SecCopyErrorMessageString. (5认同)

Ash*_*lls 6

对于 iOS 11.3+,我在OSStatus

extension OSStatus {

    var error: NSError? {
        guard self != errSecSuccess else { return nil }

        let message = SecCopyErrorMessageString(self, nil) as String? ?? "Unknown error"

        return NSError(domain: NSOSStatusErrorDomain, code: Int(self), userInfo: [
            NSLocalizedDescriptionKey: message])
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以称之为……

let status = SecItemAdd(attributes as CFDictionary, nil)

if let error = status.error {
    throw error
}    
// etc
Run Code Online (Sandbox Code Playgroud)

写完这篇后,我注意到这与@RomanMykitchak 之前的回答非常接近(所以请给他点赞) - 但我会把它留在这里,因为扩展可能对某人有用。


Ear*_*rlz 5

我最近发现了这个非常不错的网站,该网站适用于我向其抛出的每个状态值。它比grep浏览框架头文件更加用户友好:http : //www.osstatus.com/


Nep*_*Muw 5

我结合了一些答案。实际上,我正在寻找类似“ throw errorForStatusCode(status)”的东西。但最终实现了:

    guard status == errSecSuccess else {
        throw  NSError(domain: NSOSStatusErrorDomain, code: Int(status), userInfo: [NSLocalizedDescriptionKey: SecCopyErrorMessageString(status, nil) ?? "Undefined error"])
    }
Run Code Online (Sandbox Code Playgroud)

可从iOS 11.3 https://developer.apple.com/documentation/security/1542001-security_framework_result_codes获得SecCopyErrorMessageString


Ker*_*dex 5

我创建了一个 OSStatus 扩展,您可能会发现它很有用。它会记录音频相关错误的完整错误消息,否则可能会记录四字符代码,否则会记录您可以在https://www.osstatus.com 中查找的 OSStatus 编号

它进一步添加了有用的信息,如文件、函数和发生错误的行。

这是代码:

let isDebug = true

//**************************
// OSStatus extensions for logging
//**************************
extension OSStatus {
    //**************************
    func asString() -> String? {
        let n = UInt32(bitPattern: self.littleEndian)
        guard let n1 = UnicodeScalar((n >> 24) & 255), n1.isASCII else { return nil }
        guard let n2 = UnicodeScalar((n >> 16) & 255), n2.isASCII else { return nil }
        guard let n3 = UnicodeScalar((n >>  8) & 255), n3.isASCII else { return nil }
        guard let n4 = UnicodeScalar( n        & 255), n4.isASCII else { return nil }
        return String(n1) + String(n2) + String(n3) + String(n4)
    } // asString

    //**************************
    func detailedErrorMessage() -> String? {
        switch(self) {
        //***** AUGraph errors
        case kAUGraphErr_NodeNotFound:             return "AUGraph Node Not Found"
        case kAUGraphErr_InvalidConnection:        return "AUGraph Invalid Connection"
        case kAUGraphErr_OutputNodeErr:            return "AUGraph Output Node Error"
        case kAUGraphErr_CannotDoInCurrentContext: return "AUGraph Cannot Do In Current Context"
        case kAUGraphErr_InvalidAudioUnit:         return "AUGraph Invalid Audio Unit"

        //***** MIDI errors
        case kMIDIInvalidClient:     return "MIDI Invalid Client"
        case kMIDIInvalidPort:       return "MIDI Invalid Port"
        case kMIDIWrongEndpointType: return "MIDI Wrong Endpoint Type"
        case kMIDINoConnection:      return "MIDI No Connection"
        case kMIDIUnknownEndpoint:   return "MIDI Unknown Endpoint"
        case kMIDIUnknownProperty:   return "MIDI Unknown Property"
        case kMIDIWrongPropertyType: return "MIDI Wrong Property Type"
        case kMIDINoCurrentSetup:    return "MIDI No Current Setup"
        case kMIDIMessageSendErr:    return "MIDI Message Send Error"
        case kMIDIServerStartErr:    return "MIDI Server Start Error"
        case kMIDISetupFormatErr:    return "MIDI Setup Format Error"
        case kMIDIWrongThread:       return "MIDI Wrong Thread"
        case kMIDIObjectNotFound:    return "MIDI Object Not Found"
        case kMIDIIDNotUnique:       return "MIDI ID Not Unique"
        case kMIDINotPermitted:      return "MIDI Not Permitted"

        //***** AudioToolbox errors
        case kAudioToolboxErr_CannotDoInCurrentContext: return "AudioToolbox Cannot Do In Current Context"
        case kAudioToolboxErr_EndOfTrack:               return "AudioToolbox End Of Track"
        case kAudioToolboxErr_IllegalTrackDestination:  return "AudioToolbox Illegal Track Destination"
        case kAudioToolboxErr_InvalidEventType:         return "AudioToolbox Invalid Event Type"
        case kAudioToolboxErr_InvalidPlayerState:       return "AudioToolbox Invalid Player State"
        case kAudioToolboxErr_InvalidSequenceType:      return "AudioToolbox Invalid Sequence Type"
        case kAudioToolboxErr_NoSequence:               return "AudioToolbox No Sequence"
        case kAudioToolboxErr_StartOfTrack:             return "AudioToolbox Start Of Track"
        case kAudioToolboxErr_TrackIndexError:          return "AudioToolbox Track Index Error"
        case kAudioToolboxErr_TrackNotFound:            return "AudioToolbox Track Not Found"
        case kAudioToolboxError_NoTrackDestination:     return "AudioToolbox No Track Destination"

        //***** AudioUnit errors
        case kAudioUnitErr_CannotDoInCurrentContext: return "AudioUnit Cannot Do In Current Context"
        case kAudioUnitErr_FailedInitialization:     return "AudioUnit Failed Initialization"
        case kAudioUnitErr_FileNotSpecified:         return "AudioUnit File Not Specified"
        case kAudioUnitErr_FormatNotSupported:       return "AudioUnit Format Not Supported"
        case kAudioUnitErr_IllegalInstrument:        return "AudioUnit Illegal Instrument"
        case kAudioUnitErr_Initialized:              return "AudioUnit Initialized"
        case kAudioUnitErr_InvalidElement:           return "AudioUnit Invalid Element"
        case kAudioUnitErr_InvalidFile:              return "AudioUnit Invalid File"
        case kAudioUnitErr_InvalidOfflineRender:     return "AudioUnit Invalid Offline Render"
        case kAudioUnitErr_InvalidParameter:         return "AudioUnit Invalid Parameter"
        case kAudioUnitErr_InvalidProperty:          return "AudioUnit Invalid Property"
        case kAudioUnitErr_InvalidPropertyValue:     return "AudioUnit Invalid Property Value"
        case kAudioUnitErr_InvalidScope:             return "AudioUnit InvalidScope"
        case kAudioUnitErr_InstrumentTypeNotFound:   return "AudioUnit Instrument Type Not Found"
        case kAudioUnitErr_NoConnection:             return "AudioUnit No Connection"
        case kAudioUnitErr_PropertyNotInUse:         return "AudioUnit Property Not In Use"
        case kAudioUnitErr_PropertyNotWritable:      return "AudioUnit Property Not Writable"
        case kAudioUnitErr_TooManyFramesToProcess:   return "AudioUnit Too Many Frames To Process"
        case kAudioUnitErr_Unauthorized:             return "AudioUnit Unauthorized"
        case kAudioUnitErr_Uninitialized:            return "AudioUnit Uninitialized"
        case kAudioUnitErr_UnknownFileType:          return "AudioUnit Unknown File Type"
        case kAudioUnitErr_RenderTimeout:             return "AudioUnit Rendre Timeout"

        //***** AudioComponent errors
        case kAudioComponentErr_DuplicateDescription:   return "AudioComponent Duplicate Description"
        case kAudioComponentErr_InitializationTimedOut: return "AudioComponent Initialization Timed Out"
        case kAudioComponentErr_InstanceInvalidated:    return "AudioComponent Instance Invalidated"
        case kAudioComponentErr_InvalidFormat:          return "AudioComponent Invalid Format"
        case kAudioComponentErr_NotPermitted:           return "AudioComponent Not Permitted "
        case kAudioComponentErr_TooManyInstances:       return "AudioComponent Too Many Instances"
        case kAudioComponentErr_UnsupportedType:        return "AudioComponent Unsupported Type"

        //***** Audio errors
        case kAudio_BadFilePathError:      return "Audio Bad File Path Error"
        case kAudio_FileNotFoundError:     return "Audio File Not Found Error"
        case kAudio_FilePermissionError:   return "Audio File Permission Error"
        case kAudio_MemFullError:          return "Audio Mem Full Error"
        case kAudio_ParamError:            return "Audio Param Error"
        case kAudio_TooManyFilesOpenError: return "Audio Too Many Files Open Error"
        case kAudio_UnimplementedError:    return "Audio Unimplemented Error"

        default: return nil
        } // switch(self)
    } // detailedErrorMessage

    //**************************
    func debugLog(filePath: String = #file, line: Int = #line, funcName: String = #function) {
        guard isDebug, self != noErr else { return }
        let fileComponents = filePath.components(separatedBy: "/")
        let fileName = fileComponents.last ?? "???"

        var logString = "OSStatus = \(self) in \(fileName) - \(funcName), line \(line)"

        if let errorMessage = self.detailedErrorMessage() { logString = errorMessage + ", " + logString }
        else if let errorCode = self.asString()           { logString = errorCode    + ", " + logString }

        NSLog(logString)
    } // debugLog
} // extension OSStatus
Run Code Online (Sandbox Code Playgroud)

用法是:

//***** Create audioGraph
NewAUGraph(&audioGraph).debugLog()

//***** Testing .debugLog() OSStatus extension
kAUGraphErr_InvalidAudioUnit.debugLog()
OSStatus(560226676).debugLog()
OSStatus(-125).debugLog()
Run Code Online (Sandbox Code Playgroud)

三个测试的结果日志:

2018-11-12 19:41:48.427606+0100 HexaSynth[5875:102611] AUGraph 无效音频单元,SoftSynthesizer.swift 中的 OSStatus = -10864 - init(soundFontFileName:),第 40 行

2018-11-12 19:41:48.428403+0100 HexaSynth[5875:102611] !dat, OSStatus = 560226676 in SoftSynthesizer.swift - init(soundFontFileName:), line 41

2018-11-12 19:41:48.428638+0100 HexaSynth[5875:102611] OSStatus = -125 in SoftSynthesizer.swift - init(soundFontFileName:),第 42 行