#iphone #c #cocoa-touch #ios #object
#iPhone #c #cocoa-touch #iOS #объект
Вопрос:
Предположим, у меня есть объект. Может быть объектом objective-C; может быть объектом C . Есть ли способ проверить, какой из них не вызовет никаких исключений?
РЕДАКТИРОВАТЬ: я рад использовать любую конструкцию, которая работает, включая шаблоны, если они будут выполнять эту работу.
Комментарии:
1. является ли использование @try / @catch опцией?
2. Насколько я могу судить, нет. @try / @catch — это конструкция objective C, и, похоже, она выдает ошибку при задании объекта, не являющегося ObjectiveC.
3. У вас действительно есть объект или просто указатель из какого-либо источника, в котором удалена информация о типе; это может быть либо адрес объекта C , либо идентификатор какого-либо объекта Objective-C.
4. Я использую его несколькими способами, все они связаны с отладочным кодом. Если мне нужно постоянно отслеживать, является ли мой объект Objective C или C , это еще одна вещь, которую нужно постоянно отслеживать. Кроме того, в некоторых случаях адрес может поступать из входных данных программиста, поэтому программисту также потребуется ввести, является ли объект объектом Objective C.
Ответ №1:
Друг нашел это в блоге Cocoa with Love. По-видимому, проблема не тривиальна.
Комментарии:
1. Как насчет objc_lookUpClass (const char * name) и objc_getClass (const char * name), если вы знаете имя класса C ? Зарегистрированы ли классы C во время выполнения obj-c, когда в таких объектах отсутствует реализация isa? Я что-то упускаю?
Ответ №2:
Поскольку вы можете использовать шаблоны, вы могли бы сделать что-нибудь, где вы создаете некоторый тип функции, которая принимает общий аргумент шаблона, а затем создаете экземпляр вашего базового класса со всеми классами, которые вы используете из C , с помощью макроса. Если это не класс C , то функция возвращает false. Так, например:
//...in some header file
template<typename T>
bool is_cplusplus(const T* type) { return false; }
#define IS_CPLUSPLUS_T(class)
template<>
inline bool is_cplusplus(const class* type) { return true; }
//...now use the macro to declare all your C classes as "true" in the return
//from is_cplusplus()
IS_CPLUSPLUS_T(my_class1)
IS_CPLUSPLUS_T(my_class2)
//...now use in some code in a separate .cpp file or .mm file, etc.
my_class1 a_class;
if (is_cplusplus(amp;a_class))
{
//do something
}
Я специально использую здесь указатели, а не ссылки, потому что, насколько я понимаю, вы можете создать экземпляр шаблона C с указателем на объект Objective-C, в то время как создание экземпляров с самими объектами Objective-C не работает. Если это предположение неверно, то вы можете немного упростить жизнь, перейдя с указателей на ссылки.
Комментарии:
1. Конечно, но я не хочу увеличивать объекты.
2. Можете ли вы использовать шаблоны в своем решении? Я не эксперт по Objective-C , но я знаю, что часто шаблоны C и объекты Objective-C не работают должным образом, поэтому дайте мне знать, можете ли вы использовать шаблоны в своем решении, чтобы хотя бы определить, является ли что-то классом C …
3. @William Jockusch: Хорошо, я предпринимаю еще одну попытку найти ответ… надеюсь, это не будет слишком громоздким…
Ответ №3:
Я думаю, что это можно сделать намного проще, чем это, если тип доступен статически (как подразумевается при использовании шаблона в качестве опции). Объекты Objective-C будут неявно конвертироваться в NSObject и / или объекты ‘id’ — C не будут (без по крайней мере пользовательского кода для каждого класса для добавления оператора приведения).
// by default, consider it to not be Objective-C.
// C object, pointer, built-in, or whatever.
template<typename T>
bool isObjectiveC(const Tamp; ptr) {return false;}
// specialise for any Objective-C object
template<>
bool isObjectiveC(const NSObject*amp; ptr) {return true;}
template<>
bool isObjectiveC(const idamp; theID) {return true;}
Прототипы функций здесь передают параметр с помощью constamp;
потому что у меня были проблемы с шаблонизацией с типами Objective-C, возвращаемыми сообщениями Objective-C, и это, похоже, работает там, где обычный NSObject * не работает.