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

我对这个 iPhone SDK 和它的文档已经有点厌烦了... ..。

我正在调用 AudioConverterNew

在“返回”下的文档中: 它说“返回状态码” ... 真的..。

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

它们是“ mrep”和“ ? tmf”(将 OSStatus 转换为字符数组) ,但具体的代码并不是重点。

据我所知,随机错误代码是在随机文件中定义的,所以你不能只搜索一个文件,我找不到一个帮助文档,只让你搜索一个错误代码来获得更多信息,而且据我所知,在 OS X 中,你可以使用 GetMacOSStatusErrorString ()来将一个错误转换成有用的东西,但是没有 iPhone 版本的?

任何帮助都将不胜感激。

编辑:

好的,那么对它们进行转换会得到相反的结果(我检查了 mrep,但是没有出现) ,fmt?在音频转换器应用程序接口的列表中,如果有点模糊,但是足够公平,仍然没有“ perm”(尽管它可能与模拟器不支持 aac 解码有关) ,这是相当不言而喻的,我的一般问题仍然存在。

45787 次浏览

不,不完全是。

有些 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;
}

(有关将 fourcc 转换为 string 的更多方法,请参见 IOS/C: 将“整数”转换为四个字符串,包括 Swift)

NSERror 的 NSOSStatusErrorDomain 能够解码一些操作系统错误。

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

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

状态错误; ... Printf (“% s”,(char *) & err) ;

OSStatus 是一个有符号整数值。不能将其转换或“强制转换”为字符串。你可以像下面这样把它转换成 NSERerror:

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

这里是我写的代码,希望它节省您一些打字... 呃,不知道如何使它显示正确。

- (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";
}
}

这可以在 macOS 和11.3及以上版本的 iOS 上使用。

我知道这是一篇很老的文章,但是我在一个关于钥匙链的章节中读到了 苹果文档。他们提到了一个用于将 OSStatus 错误转换为可读性的方法。

SecCopyErrorMessageString

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

SecCopyErrorMessageString (OSStatus 状态,void * 保留) ;

用途:

NSString* ErrMsg = (__bridge_transfer NSString *) SecCopyErrorMessageString(theOSStatusError, NULL);

对于我的密钥链 OS 状态错误,它起作用了。对你有用吗?您需要将 安全,框架添加到您的项目中才能使用此方法。

这并不是对 OP 问题的直接回答,但是我认为对于任何关心这些 OSStatus 返回代码的人来说,它都是有用的:

在 Xcode 文档(Organizer)中搜索关键字“ Result Codes”,我们将在“ System Guides”结果中获得一个或多或少分类的返回代码文档部分。

如果您只是需要在自定义函数中直接使用一些代码,那么它们非常有用。

大多数情况下,您可能只需要在.h 文件中找到错误代码

我只是编写了一个 Python 脚本来查找代码(在调试/打印 osstatus 代码时)

Https://github.com/sprhawk/mygist/blob/master/tools/find_osstatus_error.py

使用 OSX 计算程序。在演示文稿菜单中选择“程序员”模式。 然后用十进制表示法输入代码。然后选择“ ascii”按钮,计算器将显示您的4个字符的翻译如“ !“ init”,“ !”!等等。.

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

如果您想要创建一个命令行实用程序,以便在开发和支持期间使用,那么您仍然可以使用不推荐的 Carbon 方法,即使在10.9(Mavericks)中也是如此。很明显,你不能在提交给苹果的应用程序中使用这个功能。

#import <Foundation/Foundation.h>
#import <CoreServices/CoreServices.h>


int main(int argc, const char **argv)
{
@autoreleasepool {
for (int i = 1; i < argc; i++) {
char *endp;
long value = strtol(argv[i], &endp, 10);
if (*endp == '\0') {
printf("%10ld: %s (%s)\n",
value,
GetMacOSStatusCommentString((OSStatus)value),
GetMacOSStatusErrorString((OSStatus)value));
} else {
fprintf(stderr, "Invalid OSStatus code '%s' ignored\n", argv[i]);
}
}
}
}

编制:

$ clang -fobjc-arc -o osstatus osstatus.m -framework Foundation -framework CoreServices

把它复制到 $PATH的某个地方:

$ cp osstatus ~/bin

并从您的日志文件或错误报告中提供错误代码:

$ osstatus -47
-47: File is busy (delete) (fBsyErr)

如果描述字符串失败,可以方便地将 OSStatus 值转换为类似于其四字符定义的字符串。至少这样你可以抓取标题,希望能找到一条关于状态意味着什么的注释。

// declaration:  extern CFStringRef CreateTypeStringWithOSType(OSType inType);


OSStatus result = ...;


if (result != noErr) {
NSString *statusString = (NSString *)CreateTypeStringWithOSType(result);
NSLog(@"Error while $VERBing: %@", statusString);
[statusString release]; // because "Create..."
statusString = nil;
}

OSStatus 错误可以是表示4个字符代码的字节,也可以是在 MacErrors.h中定义的任意数量的错误。

如果 OSStatus 错误是 0noErr,则表示没有错误。

或者,尝试在 MacErrors.h中查找错误号:

Http://www.opensource.apple.com/source/carbonheaders/carbonheaders-18.1/macerrors.h

这可能会有帮助。

static NSString *stringForOSStatus(OSStatus status)
{
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.security"];
NSString *key = [NSString stringWithFormat:@"%d", status];
return [bundle localizedStringForKey:key value:key table:@"SecErrorMessages"];
}

我最近发现了一个非常不错的网站,它为我投入的每一个状态价值而工作。与浏览框架头文件 http://www.osstatus.com/相比,它更加用户友好

考虑到平台上的 DYI 缺少 SecCopyErrorMessageString,IOS 上的 Security 框架

底部添加错误代码

Https://developer.apple.com/library/ios/documentation/security/reference/keychainservices

你自己的开关。

比如说

        let status : OSStatus = SecItemAdd(query as CFDictionaryRef, nil)
switch status {
case errSecSuccess:
return nil
case errSecAuthFailed:
// that's the result of dumping kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly into the query
return "changing app lock type on a device without fingerprint and/or passcode setup is not allowed".localized
default:
return "unhandled case: implement this"
}

这就是你需要的 https://www.osstatus.com/。 只要搜索给定的 OSStatus。

我组合了一些答案,实际上我看到的是“ throw errorForStatusCode (status)”。 但最终实现了:

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

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

对于 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])
}
}

你可以称之为..。

let status = SecItemAdd(attributes as CFDictionary, nil)


if let error = status.error {
throw error
}
// etc

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

我创建了一个 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

使用方法是:

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


//***** Testing .debugLog() OSStatus extension
kAUGraphErr_InvalidAudioUnit.debugLog()
OSStatus(560226676).debugLog()
OSStatus(-125).debugLog()

三个测试的结果日志:

2018-11-1219:41:48.427606 + 0100 HexaSynth [5875:102611] AUGraph 无效音频单元,OSStatus = -10864 in SoftSynthesizer.swift-init (Sound FontFileName:) ,第40行

2018-11-1219:41:48.428403 + 0100 HexaSynth [5875:102611] ! dat,OSStatus = 560226676 in SoftSynthesizer.ift-init (Sound FontFileName:) ,line 41

2018-11-1219:41:48.428638 + 0100 HexaSynth [5875:102611] OSStatus = -125 in SoftSynthesizer.ift-init (Sound FontFileName:) ,line 42