cocoa Expected specifier-qualifier-list before struct - objective-c

I read the other posted solutions to using structs and resolving the "Expected specifier-qualifier-list before struct" related errors, but those aren't working. Is it different in Objective C? Do I need to declare my struct somewhere else in the class? It gives me the error on the line where I declare the typedef. Here is how it looks right now:
#interface ClassA : NSObject {
NSString *name;
typedef struct _point {
uint32_t x;
uint64_t y;
} Point;
Point a;
}
#end

Put it outside of the interface:
typedef struct _point {
uint32_t x;
uint64_t y;
} Point;
#interface ClassA : NSObject {
NSString *name;
Point a;
}
#end

Related

ObjectC-Why can't I get the properties correctly using the class_copyPropertyList function?

macOS 11.5.2
Xcode 13.2.1
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <iostream>
int main(int argc, const char * argv[]) {
#autoreleasepool {
Class clazz = NSClassFromString(#"NSString");
uint32_t count = 0;
objc_property_t* properties = class_copyPropertyList(clazz, &count);
for (uint32_t i = 0; i < count; i++){
const char* name = property_getName(properties[i]);
std::cout << name << std::endl;
}
free(properties);
}
return 0;
}
I will take some snippets of the output:
hash
superclass
description
debugDescription
hash
superclass
description
debugDescription
vertexID
sha224
NS_isSourceOver
hash
superclass
description
debugDescription
...
From the output, we can find that properties such as hash, description, superclass, etc. will appear repeatedly several times, while some properties (such as UTF8String) do not appear in the result list.
How should I get the list of properties correctly?
I would appreciate it.
The reason you're not seeing UTF8String come up as a property is that it's not declared as a property in the main declaration of NSString, but rather in a category. On macOS 12.2.1/Xcode 13.2.1, the declaration of NSString boils down to this:
#interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
#property (readonly) NSUInteger length;
- (unichar)characterAtIndex:(NSUInteger)index;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
#end
All other properties and methods on NSString are declared in categories immediately afterwards:
#interface NSString (NSStringExtensionMethods)
#pragma mark *** Substrings ***
/* To avoid breaking up character sequences such as Emoji, you can do:
[str substringFromIndex:[str rangeOfComposedCharacterSequenceAtIndex:index].location]
[str substringToIndex:NSMaxRange([str rangeOfComposedCharacterSequenceAtIndex:index])]
[str substringWithRange:[str rangeOfComposedCharacterSequencesForRange:range]
*/
- (NSString *)substringFromIndex:(NSUInteger)from;
- (NSString *)substringToIndex:(NSUInteger)to;
// ...
#property (nullable, readonly) const char *UTF8String NS_RETURNS_INNER_POINTER; // Convenience to return null-terminated UTF8 representation
// ...
#end
When a property is declared in a category on a type like this, it doesn't get emitted as an actual Obj-C property because categories can only add methods to classes, and not instance variables. When a category declares a property on a type, it must be backed by a method and not a traditional property.
You can see this with a custom class, too — on my machine,
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface MyClass: NSObject
#property (nullable, readonly) const char *direct_UTF8String NS_RETURNS_INNER_POINTER;
#end
#interface MyClass (Extensions)
#property (nullable, readonly) const char *category_UTF8String NS_RETURNS_INNER_POINTER;
#end
#implementation MyClass
- (const char *)direct_UTF8String {
return "Hello, world!";
}
- (const char *)category_UTF8String {
return "Hi there!";
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Class clazz = NSClassFromString(#"MyClass");
printf("%s properties:\n", class_getName(clazz));
uint32_t count = 0;
objc_property_t* properties = class_copyPropertyList(clazz, &count);
for (uint32_t i = 0; i < count; i++){
printf("%s\n", property_getName(properties[i]));
}
free(properties);
puts("-----------------------------------------------");
printf("%s methods:\n", class_getName(clazz));
Method *methods = class_copyMethodList(clazz, &count);
for (uint32_t i = 0; i < count; i++) {
SEL name = method_getName(methods[i]);
printf("%s\n", sel_getName(name));
}
free(methods);
}
return 0;
}
outputs
MyClass properties:
direct_UTF8String
-----------------------------------------------
MyClass methods:
direct_UTF8String
category_UTF8String
If you remove the actual implementations of the *UTF8String methods from the class, the property remains declared, but the category method disappears (because it doesn't actually have a synthesized implementation because of how categories work):
MyClass properties:
direct_UTF8String
-----------------------------------------------
MyClass methods:
direct_UTF8String
As for how to adjust to this: it depends on what purpose you're trying to fetch properties for, and why you might need UTF8String specifically.
NSString declares in its interface it implements methods, but it does not actually implement them, that is why when you print at runtime a list of the its methods it does not print what you expect.
The methods are implemented by other private classes, and when you initialize a new instance of NSString, instead of getting an instance of NSString you get an instance of that private class that have the actual implementation.
You can see that by printing the class type of a string, the following prints NSCFString or NSTaggedPointerString, not NSString:
NSString* aString = [NSString stringWithFormat: #"something"];
NSLog(#"%#", [aString class]);
And this prints __NSCFConstantString:
NSLog(#"%#", [#"a constant string" class]);
This pattern is called a class cluster pattern.
If you modify to dump the methods of the NSCFString you will get a "redactedDescription", it seems you are prevented to query these classes.

Is it possible to send a struct in a block?

I am creating a Universal Class, for SQLite and I am trying to send a block of sqlite3_step, to be processed.
In sqlite3_step, I am passing the struct object statement. But, it seems I need to use pointers.
How can I possibly do ir?
Yeah, something like this should work:
typedef struct
{
int data;
}MyStruct;
#interface Foo()
#property (nonatomic, copy) void (^myBlock)(MyStruct);
#end
#implementation Foo
- (void) someMethod {
self.myBlock = ^(MyStruct theStruct) {
NSLog(#"Value of data in the struct %i", theStruct.data);
};
MyStruct theStruct;
theStruct.data = 5;
self.myBlock(theStruct);
}
#end

Objective-C: where and how should I declare enums?

Good day, friends.
I'm newbie in Objective-C. I'm wanting to use enum in my class and make it public.
I've understand how to declare enums (http://stackoverflow.com/questions/1662183/using-enum-in-objective-c), but I don't understand where should I declare them.
I've tried:
#interface MyFirstClass : NSObject {
typedef enum myTypes {VALUE_A, VALUE_B, VALUE_C} MyTypes;
}
or:
#interface MyFirstClass : NSObject {
#public
typedef enum myTypes {VALUE_A, VALUE_B, VALUE_C} MyTypes;
}
But compiler throws error: "expected specifier-qualifier-list before typedef".
What's wrong?
.h
typedef enum myTypes {VALUE_A, VALUE_B, VALUE_C} MyTypes;
#interface MyFirstClass : NSObject {
MyTypes type;
}
.m file
type=VALUE_A;
Outside of the #interface declaration.
typedef enum myTypes {VALUE_A, VALUE_B, VALUE_C} MyTypes;
#interface MyFirstClass : NSObject {
}
#end
You can create a header file (*.h) and do following to match your enum variable.
// EnumConstants.h
#ifndef EnumConstants_h
#define EnumConstants_h
typedef enum {
VEHICLE,
USERNAME
} EDIT_TYPE;
typedef enum {
HIGH_FLOW,
STANDARD_FLOW
} FLOW_TYPE;
#endif
Uses:
#import "EnumConstants.h"
UISwitch *onOffSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(self.tableview.frame.size.width-75, 26, 0, 0)];
onOffSwitch.tag =STANDARD_FLOW;

typedef in header causes error "Expected specifier-qualifier-list before 'typedef'"

Dear wisdom of the internet,
in the header-file (Objective-C)
myTestClass.h
#import <Foundation/Foundation.h>
#interface myTestClass : NSObject {
typedef int pixel;
}
- (id) initWithPic: (NSString*) picFileName;
- (void) dealloc;
- (void) doSomething;
#end
At the line typedef int pixel;xCode complains like
( ! ) "Expected specifier-qualifier-list before
'typedef'" ( 3 )
This err-msg seems pretty popular but given solutions (missing #import) do not work for me.
Also the hints I found do not explain what is going wrong here.
I do not understand this err-msg
Can someone explain it to me?
I do appreciate any tips.
Not sure what you are trying to do, put your should just put the typedef before your interface.
Inside the braces is the place for iVars.
If you want an integer variable, then you do not need the typedef:
#interface MyClass
{
int myPixel;
}
#end
Typedefs are used to create a new type, based on another. For instance:
typedef int pixel;
#interface MyClass
{
pixel myPixel;
}
#end
So when you use the pixelpseudo-type, the int type will be used.

Objective-C. I have typedef float DuglaType[3]. How do I declare the property for this?

I have:
typedef float DuglaType[3];
#interface Foo : NSObject {
DuglaType _duglaType;
}
How do I correctly declare the property?
I tried:
// .h
#property DuglaType duglaType;
// .m
#synthesize duglaType = _duglaType;
But this spews errors.
What is the secret handshake for C++ typedefs to play nice with Obj-C properties? Thanks.
Cheers,
Doug
My work around is to bail on using #property and implement setter/getters:
// .h
(float *) duglaType;
(void) setDuglaType: (DuglaType)input;
// .m
(float *) duglaType {
return &_duglaType[0];
}
(void) setDuglaType: (DuglaType)input {
m3dCopyMatrix44f(_duglaType, input);
}
I guess typdef-ing an array give Obj-C headaches. No worries.
Cheers,
Doug
Typedef the array into a struct:
typedef struct
{
float p[3];
} DuglaType;
- (DuglaType) duglaType
{
return _duglaType;
}
- (void) setDuglaType:(DuglaType) input
{
m3dCopyMatrix44f(&_duglaType.p[0], &input.p[0]);
}