Save a lot of code by using NSClassFromString in Objective C

Recently, I am implementing database synchronize feature by using SQL sync framework 2.1.  In the iOS client, I need save each row of data (entity) into its corresponding table. 

From the metadata of the response, I can see the entity table name and its columns' value and name.  Usually, I need write method for each table to save the entity into the table, like below piece of code: Status and Priority are the tables' name.


// populates the StatusEntity store with the values from the json object dict
+ (void)populateStatus: (id)dict withMetadata:(id)metadata withContext:(NSManagedObjectContext*) context;
{
    bool isTombstone = [Utils isDeleted:metadata];
    StatusEntity *status = nil;
    
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    [fetch setEntity:[NSEntityDescription entityForName:@"Status" inManagedObjectContext:context]];
    [fetch setPredicate:[NSPredicate predicateWithFormat:@"ID = %@", [dict valueForKey:@"ID"]]];
    NSArray *results = [context executeFetchRequest:fetch error:nil];
    if (results.count == 1)
    {
        status = [results objectAtIndex:0];
    }
    
    
    if (status == nil && !isTombstone)
    {
        // insert new status
        status = [NSEntityDescription insertNewObjectForEntityForName:@"Status" inManagedObjectContext:context];
    }
    

    // if its deleted and we have not seen it ignore it
    // else delete it
    if (isTombstone && status != nil)
    {
        [context deleteObject:status];
    }
    else if (!isTombstone)
    {
        status.ID = [dict valueForKey:@"ID"];
        status.statusName = [dict valueForKey:@"Name"];
    }
    
}

// populates the PriorityEntity store with the values from the json object dict
+ (void)populatePriority: (id)dict withMetadata:(id)metadata withContext:(NSManagedObjectContext*) context;
{
    bool isTombstone = [Utils isDeleted:metadata];
    PriorityEntity *priority = nil;
    
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    [fetch setEntity:[NSEntityDescription entityForName:@"Priority" inManagedObjectContext:context]];
    [fetch setPredicate:[NSPredicate predicateWithFormat:@"ID = %@", [dict valueForKey:@"ID"]]];
    
    NSArray *results = [context executeFetchRequest:fetch error:nil];
    if (results.count == 1)
    {
        priority = [results objectAtIndex:0];
    }
    
    
    if (priority == nil && !isTombstone)
    {
        // insert new status
        priority = [NSEntityDescription insertNewObjectForEntityForName:@"Priority" inManagedObjectContext:context];
    }
    
    
    // if its deleted and we have not seen it ignore it
    // else delete it
    if (isTombstone && priority != nil)
    {
        [context deleteObject:priority];
    }
    else if (!isTombstone)
    {
        priority.ID = [dict valueForKey:@"ID"];
        priority.priorityName = [dict valueForKey:@"Name"];
    }
    
}


Thanks NSClassFromString method, which saved me a lot of time and code to just use a method to handle all the entities automatically. 

The most important methods are NSClassFromString and insertNewObjectForEntityForName:

            Class cls = NSClassFromString(tableName);
            if (cls != Nil)
            {

               // if the name is a class object, then we can call the class method directly.

                newObject = [cls findFirstWithPredicate:predicate];
            }

and:

    if (NSClassFromString(name)) {

        // Based on the entity name, we can generate the entity object with below method directly.  It is very helpful.
        NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];

    }


Here is the full code on my implementation, some methods are my wrapped internal method for the CoreData, which are not exposed here.  But it will be very help for the reader to see how did I insert the entity :

 // populates the ListEntity store with the values from the json object dict
+ (void)populateEntity: (id)dict withMetadata:(id)metadata withContext:(NSManagedObjectContext*) context {
    bool isTombstone = [Utils isDeleted:metadata];
    
    NSString *uri = [metadata valueForKey:@"uri"];
    NSMutableDictionary *pKeys = [NSMutableDictionary dictionary];
    NSString *tableName = nil;
    
    
    NSArray *sub = [uri componentsSeparatedByString:@".svc/"];
    
    if ([sub count] == 2) {
        uri = [sub objectAtIndex:1];
        NSArray *subStrings = [uri componentsSeparatedByString:@"("];
        
        if ([subStrings count] == 2) {
            tableName = [subStrings objectAtIndex:0];
            
            // (Robert #) in Heat3, the table name is capitalized. So need special convert it here.
            tableName = [NSString stringWithFormat:@"%@%@",[tableName substringToIndex:1].uppercaseString, [tableName substringFromIndex:1]];
            
            NSString *keys = [[subStrings objectAtIndex:1] stringByReplacingOccurrencesOfString:@")" withString:@""];
            
            NSArray *subKeys = [keys componentsSeparatedByString:@","];
            
            for (NSString *key in subKeys) {
                NSArray *keyPair = [key componentsSeparatedByString:@"="];
                if ([keyPair count] == 2) {
                    [pKeys setObject:[keyPair objectAtIndex:1] forKey: [keyPair objectAtIndex:0]];
                }
            }
        }
        
    } else {
        NSLog(@"Something is wrong, please check.");
    }

    if (nil != tableName && [pKeys allKeys] > 0)
    {
        NSManagedObject *newObject = nil;
        
       // measure = [TgMeasure findFirstByAttribute:@"MeasureID" withValue:[dict valueForKey:@"MeasureID"]];
        
        if (NSClassFromString(tableName)) {
            
            NSString *string = [NSString string];
            for (NSString *key in [pKeys allKeys]) {
                
                if ([string length] == 0) {
                    string = [string  stringByAppendingFormat:@"%@=%@", key, [pKeys objectForKey:key]];
                } else {
                    string = [string stringByAppendingFormat:@" and %@=%@", key, [pKeys objectForKey:key]];
                }
                
            }
            
            NSPredicate *predicate = [NSPredicate predicateWithFormat:string];
            
            Class cls = NSClassFromString(tableName);
            if (cls != Nil)
            {
                newObject = [cls findFirstWithPredicate:predicate];
            }

        }
        
        // if its deleted and we have not seen it ignore it
        // else delete it
        if (isTombstone && newObject != nil)
        {
            [context deleteObject:newObject];
        }
        else if (!isTombstone)
        {

            [NSManagedObject createManagedObjectFromDictionary:dict inContext:CONTEXT_FOR_CURRENT_THREAD withName:tableName];
            SAVE_COREDATA_CONTEXT;
        }
    }
}


+ (NSManagedObject *)createManagedObjectFromDictionary:(NSDictionary *)dictionary inContext:(NSManagedObjectContext *)context withName:(NSString *)name
{
    if (NSClassFromString(name)) {
        NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
        
        NSMutableDictionary *tmpDict = [NSMutableDictionary new];
        for(NSString *aKey in dictionary){
            
            id object = [dictionary valueForKey:aKey];

            NSString * newKey = [aKey lowercaseString];
            
            [tmpDict setValue:object forKey:newKey];
            
        }
        
        [newObject fromDictionary:tmpDict];
        
        return newObject;
    } else {
        return nil; 
    }
    
}



To create a PAL decoder in GNU Radio Companion (GRC), follow these steps: 1. Open GNU Radio Companion (GRC) and create a new flowgraph. 2. Drag and drop a "File Source" block onto the flowgraph workspace. 3. Double click on the "File Source" block and select the PAL audio file that you want to decode. 4. Drag and drop a "Quadrature Demod" block onto the flowgraph workspace. 5. Connect the output of the "File Source" block to the input of the "Quadrature Demod" block. 6. Drag and drop a "Low Pass Filter" block onto the flowgraph workspace. 7. Connect the output of the "Quadrature Demod" block to the input of the "Low Pass Filter" block. 8. Double click on the "Low Pass Filter" block and set the cutoff frequency to 4.5 kHz. 9. Drag and drop a "Throttle" block onto the flowgraph workspace. 10. Connect the output of the "Low Pass Filter" block to the input of the "Throttle" block. 11. Drag and drop a "PAL Decoder" block onto the flowgraph workspace. 12. Connect the output of the "Throttle" block to the input of the "PAL Decoder" block. 13. Double click on the "PAL Decoder" block and set the "Standard" to "PAL-B/G". 14. Drag and drop a "WAV File Sink" block onto the flowgraph workspace. 15. Connect the output of the "PAL Decoder" block to the input of the "WAV File Sink" block. 16. Double click on the "WAV File Sink" block and set the filename and format of the output file. 17. Save and run the flowgraph. This should create a PAL decoder that reads in a PAL audio file, filters and demodulates it, decodes it using the PAL-B/G standard, and saves the output as a WAV file.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值