3

I'm trying to figure out at runtime whether a property of a class is nullable. For example:

@interface A : NSObject

+ (NSSet<NSString *> *)nullableProperties;

@property (readonly, nonatomic) NSString *description;

@property (readonly, nonatomic, nullable) NSError *error;

@end

@implementation A

+ (NSSet<NSString *> *)nullableProperties {
  // Code that identifies nullable properties.
}

@end

nullableProperties should in this case return an NSSet with @"error".

property_getAttributes function can provide information of some of the attributes (more info here). Unfortunately, it doesn't provide information on whether the property is declared as nullable.

I would like to avoid implementing nullableProperties for every class that I need to know the nullable properties for.

jscs
  • 63,694
  • 13
  • 151
  • 195
byohay
  • 272
  • 4
  • 11
  • 3
    The `nullable` modifier is simply information to the compiler that helps it provide an appropriate interface to Swift; It doesn't modify the compiled code. – Paulw11 Aug 22 '17 at 10:53
  • As far I know you can't get declared variable value with `class`(+) function. Check your code if anything wrong. – Mathi Arasan Aug 22 '17 at 10:58
  • Pre-compile script to scrape the property info and insert the method decl? libclang is pretty easy to use, although I've no idea if it exposes this attribute. – jscs Aug 22 '17 at 13:21

1 Answers1

6

Every Objective-C pointer or object property is technically nullable at runtime. The nullability specifiers are simply compiler hints that don't affect the actual built binary [edit: by which I mean, since this is apparently unclear, the 1s and 0s that get written to the disk in either Mach-O or some other comparable binary format by the compiler and linker, and which contain the machine instructions that represent the program logic along with other information and metadata]. Therefore, there's no way to detect at runtime which properties are nullable and which are not.

Charles Srstka
  • 16,665
  • 3
  • 34
  • 60
  • +1 Completely correct except of the *therefore*. Sometimes you can get type information at runtime that is not important for the runtime environment's work itself. – Amin Negm-Awad Aug 22 '17 at 19:16
  • @Amin Negm-Awad Not nullability. That information is not present at runtime. – Charles Srstka Aug 22 '17 at 19:32
  • I know that. But you said, that is not available, *because* (therefore) it is solely a compiler hint. But this is not a valid argument. – Amin Negm-Awad Aug 22 '17 at 19:47
  • @Amin Negm-Awad Something that is solely a compiler hint that does not affect the compiled binary is, by definition, something that you cannot detect at runtime. – Charles Srstka Aug 22 '17 at 20:43
  • That's not correct, because the RTTI can be and is richer than solely the necessary information. For example passing a pointer (to a C object) to a method, the type of the pointee does not effect the executable. However, you can ask for that type. Your conclusion, that what is not necessary is not there, is not correct. – Amin Negm-Awad Aug 22 '17 at 21:27
  • The C types of arguments to methods actually *are* stored in the binary; you can see this for yourself if you look at the declaration for `struct objc_method_declaration` in `/usr/include/objc/runtime.h`; the struct contains a `char *` member which stores a string representation of the C types of the arguments to the method (as well as the return type). This is how Objective-C is able to access this information at runtime. By contrast, the Objective-C types of object pointer arguments cannot be deduced, because those, like nullability, exist only in the source, being just `id` in the binary. – Charles Srstka Aug 22 '17 at 22:42
  • I know that. This is, why your "therefore" is wrong as I said in my very first comment. "Objctive-C" (wrong term, Objective-C is a language, likely you meant the RTE) does not need to know, what type a C pointer refers to. BTW: The property type string contains information not used by the RTE itself, too. – Amin Negm-Awad Aug 23 '17 at 06:03
  • You claimed that the type of a C pointer in a method signature does not affect the executable; this is untrue. If you peek inside the binary with a hex editor, you will find the type encodings of all your Objective-C methods are stored in there. Thus, changing the type does change the binary. By contrast, nullability specifiers do not affect how the binary is built at all. To be able to get this information at runtime, it has to be written down somewhere. Unfortunately the Psychic Friends Network cannot be used because its UI is still telephone-only and Macs don't ship with modems anymore. – Charles Srstka Aug 23 '17 at 14:33
  • I know, that they are stored there. *This is, what I said.* But it is not needed for the execution of the code. *This is, what I said.* So, there is an information that has no meaning to the program flow. So, your conclusion in your answer is wrong. I *really,* do not know, how to give you further explanations. I'm repeating me. I do not think, that a further discussion is useful. – Amin Negm-Awad Aug 23 '17 at 18:38
  • And if "not needed for the execution of the code" were what I said, then that would be relevant. But it wasn't, and it's not. What I said was, "the nullability specifiers are simply compiler hints that don't affect the actual built binary." And this is true. Changing the C type of an argument to a method *will in fact change the binary*, since different type information will be written into it. Changing a nullability specifier will not. If you compile down to the same exact binary, that code has to behave the same way at runtime. I don't know how much clearer I can get than that. – Charles Srstka Aug 23 '17 at 18:49