Как конвертировать код iPhone OSStatus во что-то полезное?
Мне больше всего надоел этот iPhone SDK и его документация...
Я звоню AudioConverterNew
в документации в разделе "Возвращает" написано "возвращает код состояния"
...
на самом деле...
до сих пор, играя с параметрами, я смог получить только две разные ошибки, ни одна из которых не указана в нижней части справочника Audio Converter.
это 'mrep' и '? tmf' (приведение OSStatus к массиву символов), но конкретные коды на самом деле не имеют значения.
Насколько я могу судить, случайные коды ошибок определены в случайных файлах, поэтому вы не можете просто искать один файл, я не могу найти справочный документ, который просто позволяет вам искать код ошибки, чтобы получить больше информации, и от что я могу сказать, в OS X вы можете использовать GetMacOSStatusErrorString(), чтобы преобразовать ошибку во что-то полезное, но нет эквивалента iPhone?
любая помощь будет принята с благодарностью.
EDIT:
хорошо, поэтому приведение их дает их в обратном порядке (что-то, что я проверил на "mrep", но не было там в любом случае), fmt? находится в списке для Audio Converter api, и довольно понятен, если немного расплывчатый, но достаточно справедливый, все еще "perm" не существует (хотя это может быть что-то связанное с симулятором, не поддерживающим декодирование aac) и мой общий вопрос все еще стоит.
Ответы
Ответ 1
Нет. Не полностью.
Некоторые 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;
}
(см. iOS/C: Преобразуйте "целое число" в четыре строки символов для еще нескольких способов преобразования четырьмя в строку, включая Swift)
NSError NSOSStatusErrorDomain способен декодировать некоторые ошибки ОС. См. ответ @tomk.
Если вам не нужно декодировать номер в программе для пользователя, вы можете использовать macerror
script, чтобы вручную узнать значение, как указано в @lros answer. Список поддерживаемых OSStatus можно найти из его исходного кода в /System/Library/Perl/Extras/5.18/Mac/Errors.pm
.
Существует также онлайн-сервис http://osstatus.com/ сбор ошибок из всех общедоступных фреймворков. Они все еще не заполнены, например. сопоставление с -12792
, указанное в комментарии, отсутствует. Вероятно, это код из частной структуры.
Ответ 2
OSStatus - знаковое целочисленное значение. Вы не можете преобразовать или "отличить" его от строки. Вы можете преобразовать его в NSError следующим образом:
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil];
Ответ 3
Недавно я столкнулся с другим подходом: командой macerror. Распечатайте значение OSStatus как целое число со знаком. Затем в окне терминала (на вашем Mac, а не на вашем iDevice!) Введите, например, macerror -50. Он ответит кратким описанием. Очевидно, что это полезно только вам, во время разработки.
Ответ 4
Вот код, который я написал, надеюсь, что он спасет вас от ввода текста... er, не знаю, как правильно это показать.
- (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";
}
}
Ответ 5
Это доступно в macOS и для iOS от 11.3 и выше.
Я знаю, что это старый пост, но я читал яблочные документы в разделе, связанном с цепочками для ключей. Они упоминают метод, который используется для преобразования ошибок OSStatus в нечто читаемое.
SecCopyErrorMessageString
Возвращает строку, объясняющую смысл кода результата безопасности.
SecCopyErrorMessageString (OSStatus status, void* reserved );
Использование:
NSString* ErrMsg = (__bridge_transfer NSString *) SecCopyErrorMessageString(theOSStatusError, NULL);
Это сработало для меня с ошибками моего брелка OSStatus. Работает ли это для вас? Вам понадобится Security.Framework, добавленный в ваш проект, чтобы использовать этот метод.
Ответ 6
Недавно я нашел этот действительно хороший сайт, который работал для каждого значения статуса, которое я выбрасывал. Это намного удобнее для пользователя, чем просмотр файлов заголовков фреймворка: http://www.osstatus.com/
Ответ 7
Я объединил несколько ответов. На самом деле я искал что-то вроде "throw errorForStatusCode (status)".
Но в итоге достигнуто:
guard status == errSecSuccess else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status), userInfo: [NSLocalizedDescriptionKey: SecCopyErrorMessageString(status, nil) ?? "Undefined error"])
}
SecCopyErrorMessageString доступна из iOS 11.3https://developer.apple.com/documentation/security/1542001-security_framework_result_codes
Ответ 8
Используйте программу OSX calc. Выберите "программатор" в меню презентации.
Затем введите код в десятичном представлении. Затем выберите кнопку "ascii", и в Calc вы увидите 4 char перевод, такой как "! Init", "! Cat" и т.д.
Ответ 9
Я создал расширение OSStatus, которое может оказаться полезным. Он регистрирует полное сообщение об ошибках, связанных со звуком, в противном случае, когда это возможно, четырехзначный код, в противном случае номер OSStatus, который можно найти в https://www.osstatus.com
Кроме того, он добавляет полезную информацию, такую как файл, функция и строка, где произошла ошибка.
Вот код:
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-12 19: 41: 48.427606 + 0100 HexaSynth [5875: 102611] Недопустимый аудиоблок AUGraph, OSStatus = -10864 в SoftSynthesizer.swift - init (soundFontFileName :), строка 40
2018-11-12 19: 41: 48.428403 + 0100 HexaSynth [5875: 102611]! Dat, OSStatus = 560226676 в SoftSynthesizer.swift - init (soundFontFileName :), строка 41
2018-11-12 19: 41: 48.428638 + 0100 HexaSynth [5875: 102611] OSStatus = -125 в SoftSynthesizer.swift - init (soundFontFileName :), строка 42
Ответ 10
В большинстве случаев вам может понадобиться найти код ошибки в файлах .h
Я только что сделал python script, чтобы найти код (при отладке/печати кода osstatus)
https://github.com/sprhawk/MyGist/blob/master/tools/find_osstatus_error.py
Ответ 11
Если вы хотите создать служебную программу командной строки для использования во время разработки и поддержки, вы можете использовать устаревшие методы Carbon, даже в 10.9 (Mavericks). Очевидно, вы не можете использовать это в приложении, которое вы отправляете в Apple для включения в App Store.
#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)
Ответ 12
Если строка описания отсутствует, удобно преобразовать значения OSStatus в строки, которые выглядят как их четырехсимвольные определения. По крайней мере, тогда вы можете grep заголовки в надежде найти комментарий о том, что означает статус.
// 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;
}
Ответ 13
Это не прямой ответ на вопрос OP, но я думаю, что это будет полезно для тех, кто занимается этими кодами возврата OSStatus:
Ищите ключевое слово "Коды результата" в документации Xcode (Организатор), и мы получаем разделы документации по кодам с более или менее категоризированными кодами в "Системных руководствах".
Если вам просто нужно использовать некоторые коды непосредственно в своих пользовательских функциях, они очень полезны.
Ответ 14
Ошибки OSStatus могут быть байтами, представляющими код 4- char, или любое количество ошибок, определенных в MacErrors.h
.
Если ошибка OSStatus равна 0
или noErr
, это означает, что у вас нет ошибки.
Или попробуйте найти номер своей ошибки в MacErrors.h
:
http://www.opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/MacErrors.h
Ответ 15
Это может быть помощь.
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"];
}
Ответ 16
для среды безопасности в IOS, если на платформе отсутствует SecCopyErrorMessageString, DYI
добавить коды ошибок внизу
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 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"
}
Ответ 17
Это то, что вам нужно https://www.osstatus.com/.
Просто найдите данный OSStatus.
Ответ 18
Для 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 (поэтому, пожалуйста, дайте ему ответ), но я оставлю это здесь, так как расширение может оказаться полезным для кого-то.
Ответ 19
OSStatus err;
...
printf ( "% s", (char *) & err);