অবজেক্টিভ-সি-তে একটি সামগ্রীর বৈশিষ্ট্যের তালিকা পান


109

আমি কীভাবে অবজেক্টিভ-সি-তে কোনও প্রদত্ত বস্তুর বৈশিষ্ট্যের একটি তালিকা ( NSArrayবা আকারে NSDictionary) পেতে পারি ?

নিম্নলিখিত দৃশ্যের কল্পনা করুন: আমি একটি প্যারেন্ট ক্লাস সংজ্ঞায়িত করেছি যা সবেমাত্র প্রসারিত NSObject, যা একটি NSString, একটি BOOLএবং NSDataঅবজেক্টকে বৈশিষ্ট্য হিসাবে ধারণ করে। তারপরে আমার বেশ কয়েকটি ক্লাস রয়েছে যা এই প্যারেন্ট ক্লাসকে প্রসারিত করে, প্রতিটিগুলিতে বিভিন্ন বৈশিষ্ট্য যুক্ত করে।

কোনো উপায় আছে আমি একটি দৃষ্টান্ত পদ্ধতি বাস্তবায়ন হতে পারে কি পিতা বা মাতা যে সমগ্র বস্তু এবং আয়, বলে, একটি মাধ্যমে যায় বর্গ NSArrayবর্গ বৈশিষ্ট্যাবলী (শিশু) প্রতিটি যেমন NSStringsযে না তাই আমি পরে এই ব্যবহার করতে পারেন, পিতা বা মাতা বর্গ উপর NSStringকেভিসির জন্য?

উত্তর:


116

আমি নিজেই উত্তরটি পেতে পেরেছি। ওবজ-সি রানটাইম লাইব্রেরিটি ব্যবহার করে, আমি যেভাবে চাইলে বৈশিষ্ট্যগুলিতে অ্যাক্সেস পেয়েছিলাম:

- (void)myMethod {
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);
    for(i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithCString:propName
                                                                encoding:[NSString defaultCStringEncoding]];
            NSString *propertyType = [NSString stringWithCString:propType
                                                                encoding:[NSString defaultCStringEncoding]];
            ...
        }
    }
    free(properties);
}

এটির জন্য আমাকে একটি 'getPropertyType' সি ফাংশন তৈরি করা দরকার যা মূলত একটি অ্যাপল কোড নমুনা থেকে নেওয়া হয়েছিল (সঠিক উত্সটি এখনই মনে করতে পারে না):

static const char *getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T') {
            if (strlen(attribute) <= 4) {
                break;
            }
            return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
        }
    }
    return "@";
}

5
এটি ব্যতীত +1 আদিমগুলিতে ত্রুটি ঘটবে, যেমন ইনট। এই একই জিনিসটির সামান্য বর্ধিত সংস্করণের জন্য দয়া করে নীচে আমার উত্তরটি দেখুন।
jpswain

1
যথার্থতার বিষয়টি হিসাবে, [NSString stringWithCString:]পক্ষে হ্রাস করা হয় [NSString stringWithCString:encoding:]
জেকেল

4
ইজেক্ট রানটাইম হেডার আমদানি করা উচিত # আমদানি <আপত্তি / রানটাইম.h> এটি আরসি তে কাজ করে।
দা কেম

সুইফট ব্যবহার করে এটি কীভাবে সম্পন্ন হয় তা এখানে
রামিস

76

@ বলিভার উত্তর ভাল, তবে ইন্টি, লং, ফ্লোট, ডাবল ইত্যাদির মতো আদিমগুলি পরিচালনা করতে একটু বাড়তি দরকার

এই কার্যকারিতা যুক্ত করতে আমি তার থেকে তৈরি করেছিলাম।

// PropertyUtil.h
#import 

@interface PropertyUtil : NSObject

+ (NSDictionary *)classPropsFor:(Class)klass;

@end


// PropertyUtil.m
#import "PropertyUtil.h"
#import "objc/runtime.h"

@implementation PropertyUtil

static const char * getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    printf("attributes=%s\n", attributes);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T' && attribute[1] != '@') {
            // it's a C primitive type:
            /* 
                if you want a list of what will be returned for these primitives, search online for
                "objective-c" "Property Attribute Description Examples"
                apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.            
            */
            return (const char *)[[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes];
        }        
        else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
            // it's an ObjC id type:
            return "id";
        }
        else if (attribute[0] == 'T' && attribute[1] == '@') {
            // it's another ObjC object type:
            return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
        }
    }
    return "";
}


+ (NSDictionary *)classPropsFor:(Class)klass
{    
    if (klass == NULL) {
        return nil;
    }

    NSMutableDictionary *results = [[[NSMutableDictionary alloc] init] autorelease];

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(klass, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithUTF8String:propName];
            NSString *propertyType = [NSString stringWithUTF8String:propType];
            [results setObject:propertyType forKey:propertyName];
        }
    }
    free(properties);

    // returning a copy here to make sure the dictionary is immutable
    return [NSDictionary dictionaryWithDictionary:results];
}




@end

1
আপনি কি #import <Foundation/Foundation.h>.h ফাইলের শীর্ষে থাকতে চান ?
অ্যান্ড্রু

2
[NSString stringWithUTF8String: propType] বিশ্লেষণ করতে পারি না "propType const গৃহস্থালি *" NSNumber \ x94 \ xfdk; "এবং আয় একটি শূন্য স্ট্রিং ... না কেন জানি এটা যেমন একটি অদ্ভুত NSNumber মেগাবাইট কারণ ActiveRecord হয়।?
Dumoko

চমত্কার! অনেক ধন্যবাদ.
আজিক আবদুল্লাহ

এটি একেবারে নিখুঁত!
প্রণয় সি

28

@ কমলা 80 এর উত্তরের একটি সমস্যা রয়েছে: এটি আসলে সর্বদা 0 এর সাথে স্ট্রিংটি শেষ করে না। এটি ইউটিএফ 8 এ রূপান্তর করার চেষ্টা করার সময় ক্র্যাশ হওয়ার মতো অপ্রত্যাশিত ফলাফলের দিকে নিয়ে যেতে পারে (কেবলমাত্র এর কারণে আমার আসলেই বেশ বিরক্তিকর ক্র্যাশব্যাগ হয়েছিল it এটি ডিবাগ করা মজা ছিল ^^)। আমি এট্রিবিউট থেকে আসলে একটি এনএসএসস্ট্রিং পেয়ে এবং তারপরে সিস্ট্রিং ইউজিং এঙ্কোডিং কল করে এটি ঠিক করেছি :. এটি এখন কবজির মতো কাজ করে। (এআরসি-র সাথেও কাজ করে, কমপক্ষে আমার জন্য)

সুতরাং এটি এখন কোডের আমার সংস্করণ:

// PropertyUtil.h
#import 

@interface PropertyUtil : NSObject

+ (NSDictionary *)classPropsFor:(Class)klass;

@end


// PropertyUtil.m
#import "PropertyUtil.h"
#import <objc/runtime.h>

@implementation PropertyUtil

static const char *getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    //printf("attributes=%s\n", attributes);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T' && attribute[1] != '@') {
            // it's a C primitive type:
            /*
             if you want a list of what will be returned for these primitives, search online for
             "objective-c" "Property Attribute Description Examples"
             apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.
             */
            NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
        else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
            // it's an ObjC id type:
            return "id";
        }
        else if (attribute[0] == 'T' && attribute[1] == '@') {
            // it's another ObjC object type:
            NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
    }
    return "";
}


+ (NSDictionary *)classPropsFor:(Class)klass
{
    if (klass == NULL) {
        return nil;
    }

    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(klass, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithUTF8String:propName];
            NSString *propertyType = [NSString stringWithUTF8String:propType];
            [results setObject:propertyType forKey:propertyName];
        }
    }
    free(properties);

    // returning a copy here to make sure the dictionary is immutable
    return [NSDictionary dictionaryWithDictionary:results];
}

@end

@ পরে আপনি কি এমন একটি উদাহরণ প্রদান করতে পারেন যা আমি প্রদত্ত কোডটি দিয়ে সমস্যাটি দেখায়? আমি এটি দেখতে আগ্রহী।
jpswain

@ কমলা 80 ওয়েল, আফার ডেটা কখনই শূন্য-সমাপ্ত হয় না। যদি এটি হয় তবে এটি কেবল দুর্ঘটনায় ঘটে। আমি যদিও ভুল হতে পারে। অন্যান্য খবরে: আমার কাছে এখনও এই কোডটি চলছে এবং এটি রক
সলিডে

@ অরেঞ্জ ৮০ আমি গুগলের আইএমএ বিজ্ঞাপন লাইব্রেরি থেকে আইএমএএডআরকুইস্টে আপনার সংস্করণটি চাওয়ার চেষ্টা করে এই সমস্যায় পড়েছি। এর সমাধান এর সমাধান করে।
ক্রিস্টোফার পিক্সলে 21

ধন্যবাদ। পূর্ববর্তী দুটি উত্তর না দিলে এটি iOS7 এ আমার জন্য কাজ করেছিল। সবার জন্য +1 ৩
ক্রিশএইচ

এটি আমার পক্ষে কাজ করা একমাত্র উত্তর। অন্য সব কিছু আমাকে "এনএসএসস্ট্রিং \ x8d \ xc0 \ xd9" প্রপার্টি প্রকারের জন্য অদ্ভুততার মতো দিচ্ছিল, সম্ভবতঃ চর * সাইজিং বন্ধ ছিল
ব্রায়ান কোলাভিটো

8

আমি যখন আইওএস ৩.২ দিয়ে চেষ্টা করেছি তখন getPropertyType ফাংশন সম্পত্তি বর্ণনার সাথে ভালভাবে কাজ করে না। আমি আইওএস ডকুমেন্টেশন থেকে একটি উদাহরণ পেয়েছি: "উদ্দেশ্য-সি রানটাইম প্রোগ্রামিং গাইড: ঘোষিত সম্পত্তি"।

আইওএস ৩.২-এ সম্পত্তি তালিকার জন্য একটি সংশোধিত কোড এখানে দেওয়া হয়েছে:

#import <objc/runtime.h>
#import <Foundation/Foundation.h>
...
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([UITouch class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
free(properties);

7

আমি খুঁজে পেয়েছি যে বলিভার দ্রবণগুলি সিমুলেটারে সূক্ষ্মভাবে কাজ করে তবে ডিভাইসে স্থির দৈর্ঘ্যের সাবস্ট্রিং সমস্যার কারণ হয়। ডিভাইসে কাজ করে এমন সমস্যাটির জন্য আমি আরও একটি উদ্দেশ্য-সি-বান্ধব সমাধান লিখেছি। আমার সংস্করণে, আমি বৈশিষ্ট্যগুলির সি-স্ট্রিংগুলিকে একটি এনএসএসস্ট্রিং-তে রূপান্তর করি এবং কেবল প্রকারের বিবরণের একটি স্ট্রিং পেতে এটিতে স্ট্রিং ক্রিয়াকলাপ করি।

/*
 * @returns A string describing the type of the property
*/

+ (NSString *)propertyTypeStringOfProperty:(objc_property_t) property {
    const char *attr = property_getAttributes(property);
    NSString *const attributes = [NSString stringWithCString:attr encoding:NSUTF8StringEncoding];

    NSRange const typeRangeStart = [attributes rangeOfString:@"T@\""];  // start of type string
    if (typeRangeStart.location != NSNotFound) {
        NSString *const typeStringWithQuote = [attributes substringFromIndex:typeRangeStart.location + typeRangeStart.length];
        NSRange const typeRangeEnd = [typeStringWithQuote rangeOfString:@"\""]; // end of type string
        if (typeRangeEnd.location != NSNotFound) {
            NSString *const typeString = [typeStringWithQuote substringToIndex:typeRangeEnd.location];
            return typeString;
        }
    }
    return nil;
}

/**
* @returns (NSString) Dictionary of property name --> type
*/

+ (NSDictionary *)propertyTypeDictionaryOfClass:(Class)klass {
    NSMutableDictionary *propertyMap = [NSMutableDictionary dictionary];
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(klass, &outCount);
    for(i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName) {

            NSString *propertyName = [NSString stringWithCString:propName encoding:NSUTF8StringEncoding];
            NSString *propertyType = [self propertyTypeStringOfProperty:property];
            [propertyMap setValue:propertyType forKey:propertyName];
        }
    }
    free(properties);
    return propertyMap;
}

এটি এনএসআরজ কনস্ট টাইপরেঞ্জস্টার্ট = [বৈশিষ্ট্যগুলি রেঞ্জঅফস্ট্রিং: @ "টি @ \" "]; // টাইপ স্ট্রিংয়ের শুরুতে
অ্যাডাম মেন্দোজা

6

এই বাস্তবায়ন উভয় উদ্দেশ্য-সি অবজেক্ট ধরণের এবং সি আদিম দুটি নিয়ে কাজ করে। এটি আইওএস 8 সামঞ্জস্যপূর্ণ। এই শ্রেণিটি তিনটি শ্রেণীর পদ্ধতি সরবরাহ করে:

+ (NSDictionary *) propertiesOfObject:(id)object;

কোনও বস্তুর সমস্ত দৃশ্যমান বৈশিষ্ট্যের একটি অভিধান প্রদান করে, এর সমস্ত সুপারক্লাসগুলি সহ।

+ (NSDictionary *) propertiesOfClass:(Class)class;

শ্রেণীর সমস্ত দৃশ্যমান বৈশিষ্ট্যের একটি অভিধান প্রদান করে, এর সমস্ত সুপারক্লাসের অন্তর্ভুক্ত।

+ (NSDictionary *) propertiesOfSubclass:(Class)class;

সাবক্লাসের জন্য সুনির্দিষ্ট সমস্ত দৃশ্যমান বৈশিষ্ট্যের একটি অভিধান প্রদান করে । এর সুপারক্লাসের বৈশিষ্ট্যগুলি অন্তর্ভুক্ত নয়

এই পদ্ধতিগুলির ব্যবহারের একটি কার্যকর উদাহরণ হ'ল একটি অনুলিপি পদ্ধতিতে বৈশিষ্ট্য নির্দিষ্ট করে না রেখে অবজেক্টিভ-সি-তে সাবক্লাস উদাহরণে কোনও বিষয় অনুলিপি করা । এই উত্তরের অংশগুলি এই প্রশ্নের অন্যান্য উত্তরের উপর ভিত্তি করে তবে এটি পছন্দসই কার্যকারিতাটিতে একটি ক্লিনার ইন্টারফেস সরবরাহ করে।

শিরোলেখ:

//  SYNUtilities.h

#import <Foundation/Foundation.h>

@interface SYNUtilities : NSObject
+ (NSDictionary *) propertiesOfObject:(id)object;
+ (NSDictionary *) propertiesOfClass:(Class)class;
+ (NSDictionary *) propertiesOfSubclass:(Class)class;
@end

বাস্তবায়ন:

//  SYNUtilities.m

#import "SYNUtilities.h"
#import <objc/objc-runtime.h>

@implementation SYNUtilities
+ (NSDictionary *) propertiesOfObject:(id)object
{
    Class class = [object class];
    return [self propertiesOfClass:class];
}

+ (NSDictionary *) propertiesOfClass:(Class)class
{
    NSMutableDictionary * properties = [NSMutableDictionary dictionary];
    [self propertiesForHierarchyOfClass:class onDictionary:properties];
    return [NSDictionary dictionaryWithDictionary:properties];
}

+ (NSDictionary *) propertiesOfSubclass:(Class)class
{
    if (class == NULL) {
        return nil;
    }

    NSMutableDictionary *properties = [NSMutableDictionary dictionary];
    return [self propertiesForSubclass:class onDictionary:properties];
}

+ (NSMutableDictionary *)propertiesForHierarchyOfClass:(Class)class onDictionary:(NSMutableDictionary *)properties
{
    if (class == NULL) {
        return nil;
    }

    if (class == [NSObject class]) {
        // On reaching the NSObject base class, return all properties collected.
        return properties;
    }

    // Collect properties from the current class.
    [self propertiesForSubclass:class onDictionary:properties];

    // Collect properties from the superclass.
    return [self propertiesForHierarchyOfClass:[class superclass] onDictionary:properties];
}

+ (NSMutableDictionary *) propertiesForSubclass:(Class)class onDictionary:(NSMutableDictionary *)properties
{
    unsigned int outCount, i;
    objc_property_t *objcProperties = class_copyPropertyList(class, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = objcProperties[i];
        const char *propName = property_getName(property);
        if(propName) {
            const char *propType = getPropertyType(property);
            NSString *propertyName = [NSString stringWithUTF8String:propName];
            NSString *propertyType = [NSString stringWithUTF8String:propType];
            [properties setObject:propertyType forKey:propertyName];
        }
    }
    free(objcProperties);

    return properties;
}

static const char *getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T' && attribute[1] != '@') {
            // A C primitive type:
            /*
             For example, int "i", long "l", unsigned "I", struct.
             Apple docs list plenty of examples of values returned. For a list
             of what will be returned for these primitives, search online for
             "Objective-c" "Property Attribute Description Examples"
             */
            NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
        else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
            // An Objective C id type:
            return "id";
        }
        else if (attribute[0] == 'T' && attribute[1] == '@') {
            // Another Objective C id type:
            NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
    }
    return "";
}

@end

আমি এই লাইনে এনএসএসটিরিং * নাম = [[এনএসএসআরটিং বরাদ্দ] টিউনবিাইটবাইটস: অ্যাট্রিবিউট + 1 দৈর্ঘ্য: স্ট্রেন (অ্যাট্রিবিউট) - 1 এনকোডিং: এনএসএএসসিআইআইএসটিআরইং কোডিং] এ একটি EXC_BAD_ACCESS ব্যতিক্রম পেয়েছি;
অ্যাডাম মেন্দোজা

4

কেউ যদি প্যারেন্ট ক্লাসগুলি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত সম্পত্তি পাওয়ার প্রয়োজনে থাকে (যেমনটি করেছি) তবে এটি পুনরুক্তি করার জন্য " কমলা 80 " কোডে কিছু পরিবর্তন রয়েছে :

+ (NSDictionary *)classPropsForClassHierarchy:(Class)klass onDictionary:(NSMutableDictionary *)results
{
    if (klass == NULL) {
        return nil;
    }

    //stop if we reach the NSObject class as is the base class
    if (klass == [NSObject class]) {
        return [NSDictionary dictionaryWithDictionary:results];
    }
    else{

        unsigned int outCount, i;
        objc_property_t *properties = class_copyPropertyList(klass, &outCount);
        for (i = 0; i < outCount; i++) {
            objc_property_t property = properties[i];
            const char *propName = property_getName(property);
            if(propName) {
                const char *propType = getPropertyType(property);
                NSString *propertyName = [NSString stringWithUTF8String:propName];
                NSString *propertyType = [NSString stringWithUTF8String:propType];
                [results setObject:propertyType forKey:propertyName];
            }
        }
        free(properties);

        //go for the superclass
        return [PropertyUtil classPropsForClassHierarchy:[klass superclass] onDictionary:results];

    }
}

1
আমরা কি এটিকে কোনও বিভাগ তৈরি করতে এবং এর সাথে এনএসবজেক্টকে প্রসারিত করতে পারি না যাতে এই কার্যকারিতাটি প্রতিটি ক্লাসে তৈরি হয় যা এনএসবজেক্টের শিশু?
অ্যালেক্স জাভাটোন

এটি একটি ভাল ধারণা মত শোনাচ্ছে, আমি যদি সময় পাই তবে সেই বিকল্পটি দিয়ে উত্তরটি আপডেট করবে।
পাকিতোভি

এটি শেষ হয়ে গেলে আমি সময় পেলে একটি পদ্ধতি ডাম্প যুক্ত করব। প্রায় প্রতিটি এনএসবজেক্টের শীর্ষে আমরা সত্যিকারের অবজেক্ট সম্পত্তি এবং পদ্ধতির অন্তর্নিবেশ পেয়েছি about
অ্যালেক্স জাভাটোন

আমি পাশাপাশি মান আউটপুট যোগ করার কাজ করছি, কিন্তু এটি প্রদর্শিত হয় যে কিছু কাঠামোর জন্য (rects), ধরণটি সম্পত্তিটির আসল মান। উদ্দেশ্য-সি রানটাইম ডক্সের সাথে দ্বন্দ্বপূর্ণ টাইপ হিসাবে একটি ভিউকন্ট্রোলার স্ট্রাক্ট রিটার্ন সি বা এফ হিসাবে একটি সারণীভিউ কনট্রোলার এবং অন্যান্য স্বাক্ষরযুক্ত ইন্টের কেয়ারট্যাক্টের ক্ষেত্রে এটিই ঘটে। স্পষ্টতই এটি সম্পূর্ণ পেতে এখানে আরও কাজ করা দরকার। বিকাশকারী.এপ্লে.লাইবারি
ম্যাক / ডকুমেন্টেশন / কোকোয়া / কনসেপ্টুয়াল/…

আমি একটি চেহারা দিচ্ছিলাম কিন্তু একটি সমস্যা আছে যা আমি কাজ করতে পারি না, এটি পুনরাবৃত্ত করার জন্য আমাকে সুপারক্লাসের জন্য পদ্ধতিটি কল করতে হবে (পূর্ববর্তী কোডের শেষ লাইনের মতো) কারণ এনএসবজেক্ট মূল শ্রেণি যা কোনও বিভাগের মধ্যে কাজ করবে না is । সুতরাং কোনও পুনরুক্তি সম্ভব নয় ... :( এনএসওবজেক্টের কোনও বিভাগ যদি আরও যাওয়ার উপায় হয় তা নিশ্চিত নয় ...
পাকিতোভি

3

"গুণাবলী" শব্দটি কিছুটা অস্পষ্ট f আপনি উদাহরণস্বরূপ ভেরিয়েবল, বৈশিষ্ট্য, অ্যাক্সেসরের মতো দেখতে পদ্ধতিগুলি বোঝাতে চান?

তিনটিরই উত্তর হ্যাঁ, তবে এটি খুব সহজ নয়। উদ্দেশ্য সি রানটাইম এপিআই ivar তালিকা, পদ্ধতি তালিকা বা বর্গ জন্য সম্পত্তি তালিকা পেতে ফাংশন অন্তর্ভুক্ত (যেমন, class_copyPropertyList()), এবং তারপর প্রতিটি ধরনের জন্য একটি সংশ্লিষ্ট ফাংশন তালিকা থেকে একটি আইটেম নাম পেতে (যেমন, property_getName())।

সব মিলিয়ে এটি সঠিকভাবে পরিচালিত করার জন্য এটি অনেক ধরণের কাজ হতে পারে, বা বেশিরভাগ লোকেরা সাধারণত একটি তুচ্ছ বৈশিষ্ট্যের জন্য যা প্রয়োজন তার জন্য কমপক্ষে আরও অনেক কিছু করতে চান।

বিকল্পভাবে, আপনি কেবল একটি রুবি / পাইথন স্ক্রিপ্ট লিখতে পারেন যা কেবল একটি শিরোলেখ ফাইলটি পড়ে এবং আপনি শ্রেণীর জন্য "বৈশিষ্ট্যগুলি" বিবেচনা করে যা কিছু চান তা সন্ধান করে।


হাই চক, আপনার প্রতিক্রিয়া জন্য ধন্যবাদ। আমি 'অ্যাট্রিবিউটস' দিয়ে যা উল্লেখ করছি তা আসলে শ্রেণীর বৈশিষ্ট্যগুলির মধ্যে ছিল। আমি ইতোমধ্যে ওবজে-সি রানটাইম লাইব্রেরিটি ব্যবহার করে যা করতে চাই তা অর্জন করতে সক্ষম হয়েছি। শিরোনাম ফাইলটি বিশ্লেষণের জন্য একটি স্ক্রিপ্ট ব্যবহার করা আমার রানটাইমের সময় যা প্রয়োজন তা কাজ করে না।
বলিভা

3

আমি @ কমলা 80 এর কাজের উত্তর পেতে সক্ষম হয়েছি কমপক্ষে ... যা চেয়েছিলাম তার জন্য ... কমপক্ষে ... তবে কিছুটা পরীক্ষা এবং ত্রুটি ছাড়াই নয়, আমি কমপক্ষে ... যা চেয়েছিলাম তার সাথে । আশা করি এই অতিরিক্ত তথ্য কারও শোক রক্ষা করতে পারে।

তিনি তার উত্তরে বর্ণিত classes শ্রেণিগুলি সংরক্ষণ করুন = একটি শ্রেণি হিসাবে এবং আপনার AppDelegate.h(বা যাই হোক না কেন) #import PropertyUtil.h। তারপরে আপনার ...

- (void)applicationDidFinishLaunching:
         (NSNotification *)aNotification {

পদ্ধতি (বা যাই হোক না কেন)

PropertyUtil *props  = [PropertyUtil new];  
NSDictionary *propsD = [PropertyUtil classPropsFor:
                          (NSObject*)[gist class]];  
NSLog(@"%@, %@", props, propsD);

গোপনীয়তা হল আপনার ক্লাসের উদাহরণ পরিবর্তনশীল ( এই ক্ষেত্রে আমার ক্লাসটি হ'ল Gist, এবং আমার উদাহরণটি Gistহ'লgist ) যে আপনি জিজ্ঞাসা করতে চান ... এনএসবজেক্টে ... (id)ইত্যাদি, এটি কাটবে না ... বিভিন্নের জন্য, অদ্ভুত , রহস্যজনক কারণ। এটি আপনাকে এরকম কিছু আউটপুট দেবে ...

<PropertyUtil: 0x7ff0ea92fd90>, {
apiURL = NSURL;
createdAt = NSDate;
files = NSArray;
gistDescription = NSString;
gistId = NSString;
gitPullURL = NSURL;
gitPushURL = NSURL;
htmlURL = NSURL;
isFork = c;
isPublic = c;
numberOfComments = Q;
updatedAt = NSDate;
userLogin = NSString;
}

ওবজিসির "অ্যামেজবলস" "আত্মবিশ্বাসের বিষয়ে অ্যাপলের সমস্ত অপ্রকাশিত / ওসিডি দাম্ভিকতার জন্য ... তারা নিশ্চিত যে এই সাধারণ" চেহারা "" নিজের স্বরে "," তাই বলার জন্য "এটি সম্পাদন করা খুব সহজ করে না ..

আপনি যদি সত্যিই হগ বন্য হয়ে যেতে চান তবে .. চেক আউট .. ক্লাস-ডাম্প , যা কোনও নির্বাহযোগ্য ইত্যাদির শ্রেণির শিরোনামগুলিতে উঁকি দেওয়ার একটি মন-কৌতুকপূর্ণভাবে উন্মাদ উপায় ... এটি আপনার ক্লাসগুলিতে একটি ভারবস চেহারা সরবরাহ করে ... যে আমি, ব্যক্তিগতভাবে, অনেকগুলি ক্ষেত্রে, অনেক ক্ষেত্রেই সত্যই সহায়ক find আসলে আমি কেন ওপি-র প্রশ্নের সমাধান খুঁজতে শুরু করেছি। এখানে কিছু ব্যবহারের প্যারামিটার রয়েছে .. উপভোগ করুন!

    -a             show instance variable offsets
    -A             show implementation addresses
    --arch <arch>  choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64)
    -C <regex>     only display classes matching regular expression
    -f <str>       find string in method name
    -I             sort classes, categories, and protocols by inheritance (overrides -s)
    -r             recursively expand frameworks and fixed VM shared libraries
    -s             sort classes and categories by name
    -S             sort methods by name

3

আপনার কাছে তিনটি যাদু স্পেল রয়েছে

Ivar* ivars = class_copyIvarList(clazz, &count); // to get all iVars
objc_property_t  *properties = class_copyPropertyList(clazz, &count); //to get all properties of a class 
Method* methods = class_copyMethodList(clazz, &count); // to get all methods of a class.

কোড অনুসরণ করে আপনাকে সহায়তা করতে পারে।

-(void) displayClassInfo
{
    Class clazz = [self class];
    u_int count;

    Ivar* ivars = class_copyIvarList(clazz, &count);
    NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* ivarName = ivar_getName(ivars[i]);
        ivarArray addObject:[NSString  stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
    }
    free(ivars);

    objc_property_t* properties = class_copyPropertyList(clazz, &count);
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    }
    free(properties);

    Method* methods = class_copyMethodList(clazz, &count);
    NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        SEL selector = method_getName(methods[i]);
        const char* methodName = sel_getName(selector);
        [methodArray addObject:[NSString  stringWithCString:methodName encoding:NSUTF8StringEncoding]];
    }
    free(methods);

    NSDictionary* classInfo = [NSDictionary dictionaryWithObjectsAndKeys:
                           ivarArray, @"ivars",
                           propertyArray, @"properties",
                           methodArray, @"methods",
                           nil];

        NSLog(@"%@", classInfo);
}

2

আমি প্রদত্ত ফাংশন বলিভা ব্যবহার করছিলাম তবে স্পষ্টতই এটি আইওএসের সাথে কাজ করা বন্ধ করে দিয়েছে So তাই এখন স্ট্যাটিক কনস্ট চর এর পরিবর্তে * getPropertyType (objc_property_t সম্পত্তি) কেবলমাত্র নিম্নলিখিতটি ব্যবহার করতে পারেন:

- (NSString*) classOfProperty:(NSString*)propName{

objc_property_t prop = class_getProperty([self class], [propName UTF8String]);
if (!prop) {
    // doesn't exist for object
    return nil;
}
const char * propAttr = property_getAttributes(prop);
NSString *propString = [NSString stringWithUTF8String:propAttr];
NSArray *attrArray = [propString componentsSeparatedByString:@","];
NSString *class=[attrArray objectAtIndex:0];
return [[class stringByReplacingOccurrencesOfString:@"\"" withString:@""] stringByReplacingOccurrencesOfString:@"T@" withString:@""];
}

আপনি আমার নায়ক. আমাকে এখনও কিছু জিনিস ম্যানুয়ালি সংশোধন করতে হবে (কোনও কারণে বিওএলগুলি 'টিসি' হিসাবে উপস্থিত হচ্ছে), তবে এটি আসলে আমাকে জিনিসগুলিকে আবার কাজ করতে দেয়।
হার্পস্টাম

প্রিমিটিভগুলির নিজস্ব ধরণ রয়েছে, "@" অবজেক্টগুলি বোঝায় এবং এর পরে শ্রেণীর নাম উদ্ধৃতিগুলির মধ্যে উপস্থিত হয়। একমাত্র ব্যতিক্রম আইডি যা কেবল "টি @" হিসাবে এনকোড করা আছে
মিহাই তিমার

2

সুইফট দর্শকদের জন্য, আপনি কার্যকারিতাটি কাজে লাগিয়ে এই কার্যকারিতাটি পেতে পারেন Encodable। আমি কিভাবে ব্যাখ্যা করব:

  1. আপনার বিষয়টিকে Encodableপ্রোটোকলে রূপান্তর করুন

    class ExampleObj: NSObject, Encodable {
        var prop1: String = ""
        var prop2: String = ""
    }
  2. কার্যকারিতা সরবরাহ Encodableকরার জন্য এক্সটেনশন তৈরি করুনtoDictionary

     public func toDictionary() -> [String: AnyObject]? {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data =  try? encoder.encode(self),
              let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [String: AnyObject] else {
            return nil
        }
        return jsonDict
    }
  3. toDictionaryআপনার অবজেক্ট উদাহরণস্বরূপ কল করুন এবং keysসম্পত্তি অ্যাক্সেস করুন ।

    let exampleObj = ExampleObj()
    exampleObj.toDictionary()?.keys
  4. ভাল খবর! আপনার সম্পত্তি হিসাবে যেমন অ্যাক্সেস:

    for k in exampleObj!.keys {
        print(k)
    }
    // Prints "prop1"
    // Prints "prop2"

1

এই উত্তরগুলি সহায়ক, তবে এ থেকে আমার আরও প্রয়োজন। আমি কেবল যা করতে চাই তা হ'ল শ্রেণীর ধরণের কোনও সম্পত্তির বিদ্যমান বস্তুর সমান কিনা তা যাচাই করা। উপরের সমস্ত কোডগুলি এটি করতে সক্ষম নয়, কারণ: কোনও বস্তুর শ্রেণীর নাম পেতে, অবজেক্ট_জেট ক্লাসনাম () এই জাতীয় পাঠ্য পাঠায়:

__NSArrayI (for an NSArray instance)
__NSArrayM (for an NSMutableArray instance)
__NSCFBoolean (an NSNumber object initialized by initWithBool:)
__NSCFNumber (an NSValue object initialized by [NSNumber initWithBool:])

তবে যদি উপরের নমুনা কোড থেকে getPropertyType (...) আহ্বান করা হয়, বুদ্ধিমান 4 অবজেক্ট_প্রোট্টি_t শ্রেণীর বৈশিষ্ট্যগুলির স্ট্রাক্ট এর মতো সংজ্ঞায়িত করা হয়েছে:

@property (nonatomic, strong) NSArray* a0;
@property (nonatomic, strong) NSArray* a1;
@property (nonatomic, copy) NSNumber* n0;
@property (nonatomic, copy) NSValue* n1;

এটি যথাক্রমে নিম্নোক্ত স্ট্রিংগুলি প্রদান করে:

NSArray
NSArray
NSNumber
NSValue

সুতরাং এটি কোনও এনএসবজেক্ট শ্রেণীর একটি সম্পত্তির মূল্য হতে সক্ষম কিনা তা নির্ধারণ করতে সক্ষম হয় না। তাহলে কীভাবে করব?

এখানে আমার সম্পূর্ণ নমুনা কোড (ফাংশন getPropertyType (...) উপরের মত একই):

#import <objc/runtime.h>

@interface FOO : NSObject

@property (nonatomic, strong) NSArray* a0;
@property (nonatomic, strong) NSArray* a1;
@property (nonatomic, copy) NSNumber* n0;
@property (nonatomic, copy) NSValue* n1;

@end

@implementation FOO

@synthesize a0;
@synthesize a1;
@synthesize n0;
@synthesize n1;

@end

static const char *getPropertyType(objc_property_t property) {
    const char *attributes = property_getAttributes(property);
    //printf("attributes=%s\n", attributes);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T' && attribute[1] != '@') {
            // it's a C primitive type:

            // if you want a list of what will be returned for these primitives, search online for
            // "objective-c" "Property Attribute Description Examples"
            // apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.

            NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
        else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
            // it's an ObjC id type:
            return "id";
        }
        else if (attribute[0] == 'T' && attribute[1] == '@') {
            // it's another ObjC object type:
            NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
    }
    return "";
}

int main(int argc, char * argv[]) {
    NSArray* a0 = [[NSArray alloc] init];
    NSMutableArray* a1 = [[NSMutableArray alloc] init];
    NSNumber* n0 = [[NSNumber alloc] initWithBool:YES];
    NSValue* n1 = [[NSNumber alloc] initWithBool:NO];
    const char* type0 = object_getClassName(a0);
    const char* type1 = object_getClassName(a1);
    const char* type2 = object_getClassName(n0);
    const char* type3 = object_getClassName(n1);

    objc_property_t property0 = class_getProperty(FOO.class, "a0");
    objc_property_t property1 = class_getProperty(FOO.class, "a1");
    objc_property_t property2 = class_getProperty(FOO.class, "n0");
    objc_property_t property3 = class_getProperty(FOO.class, "n1");
    const char * memberthype0 = getPropertyType(property0);//property_getAttributes(property0);
    const char * memberthype1 = getPropertyType(property1);//property_getAttributes(property1);
    const char * memberthype2 = getPropertyType(property2);//property_getAttributes(property0);
    const char * memberthype3 = getPropertyType(property3);//property_getAttributes(property1);
    NSLog(@"%s", type0);
    NSLog(@"%s", type1);
    NSLog(@"%s", type2);
    NSLog(@"%s", type3);
    NSLog(@"%s", memberthype0);
    NSLog(@"%s", memberthype1);
    NSLog(@"%s", memberthype2);
    NSLog(@"%s", memberthype3);

    return 0;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.