Нет никакого способа сделать такое обнаружение не зависящим от реализации способом, поскольку, когда вы приводите NSString к пустоте *, вы отбрасываете всю информацию о типах и преобразуете ее в «нетипизированный указатель на память».
Я не уверен, почему вам нужна такая функциональность, но если она находится между двумя объектами, вы должны использовать «id» вместо void *, поскольку это сохраняет всю информацию о типах.
В этом конкретном примере, вероятно, было бы гораздо разумнее просто сделать "log" перегруженной функцией и таким образом узнать тип времени компиляции параметра.