1

here is my JSON data,

    {
    "total": 60,
    "per_page": 10,
    "current_page": 1,
    "last_page": 6,
    "next_page_url": "http://www.ladybirdweb.com/support/api/v1/helpdesk/inbox?page=2",
    "prev_page_url": null,
    "from": 1,
    "to": 10,
    "data": [
        {
            "updated_at": "2017-07-18 07:17:25",
            "user_name": "eugene@smartitfirm.com",
            "first_name": "Eugene",
            "last_name": "Dunayev",
            "email": "eugene@smartitfirm.com",
            "profile_pic": "https://secure.gravatar.com/avatar/841369e30f04310b23750abbb670c65c?s=80&r=g&d=identicon",
            "ticket_number": "AAAA-0000-745",
            "id": 4395,
            "title": "Demo",
            "created_at": "2017-07-12 04:15:15",
            "department_name": "Support",
            "priotity_name": "Low",
            "priority_color": "#00a65a",
            "sla_plan_name": "Low",
            "help_topic_name": "Support query",
            "ticket_status_name": "Open",
            "department_id": "3",
            "user_dpt": null,
            "attachment": "23",
            "overdue_date": "2017-07-12 12:15:15"
        },
        {
            "updated_at": "2017-07-18 07:15:40",
            "user_name": "rmuller@idagroup.net",
            "first_name": "Robin",
            "last_name": "W.",
            "email": "rmuller@idagroup.net",
            "profile_pic": "https://secure.gravatar.com/avatar/90efb0e570dfc699f78c414449cb46d9?s=80&r=g&d=identicon",
            "ticket_number": "AAAA-0000-776",
            "id": 4426,
            "title": "=?UTF-8?Q?Re:_Robin_-_Implementing_Faveo_H?= =?UTF-8?Q?elp_Desk._Let=E2=80=99s_get_you_started.?=",
              "created_at": "2017-07-14 16:15:17",
"department_name": "Support",
            "priotity_name": "Low",
            "priority_color": "#00a65a",
            "sla_plan_name": "Low",
            "help_topic_name": "Support query",
            "ticket_status_name": "Open",
            "department_id": "3",
            "user_dpt": null,
            "attachment": "3",
            "overdue_date": "2017-07-17 12:00:00"
        }
    ]

}

In this particular dictionary only I m getting this fromat. Rest of other dictionaries showing right data. So, here I expect response like,

"title: Re: Robin - Implementing Faveo Help Desk. Let’s get you started."

Even If it is ok, I m getting this format, then is there any solution there getting actual data, so that I will print in view controller.

code is,

here I m sending a request,

    -(void)reload
      { 
          NSString *url=[NSString stringWithFormat:@"%@helpdesk/inbox?api_key=%@&ip=%@&token=%@",[userDefaults objectForKey:@"companyURL"],API_KEY,IP,[userDefaults objectForKey:@"token"]];

        MyWebservices *webservices=[MyWebservices sharedInstance];
        [webservices httpResponseGET:url parameter:@"" callbackHandler:^(NSError *error,id json,NSString* msg) {



            if (error || [msg containsString:@"Error"]) {
                [refresh endRefreshing];
                [[AppDelegate sharedAppdelegate] hideProgressView];
                if (msg) {

                    [utils showAlertWithMessage:[NSString stringWithFormat:@"Error-%@",msg] sendViewController:self];

                }else if(error)  {
                    [utils showAlertWithMessage:[NSString stringWithFormat:@"Error-%@",error.localizedDescription] sendViewController:self];
                    NSLog(@"Thread-NO4-getInbox-Refresh-error == %@",error.localizedDescription);
                }
                return ;
            }

            if ([msg isEqualToString:@"tokenRefreshed"]) {

                [self reload];
                NSLog(@"Thread--NO4-call-getInbox");
                return;
            }

            if (json) {
                //NSError *error;
                 NSLog(@"Thread-NO4--getInboxAPI--%@",json);
                _mutableArray = [json objectForKey:@"data"];
                _nextPageUrl =[json objectForKey:@"next_page_url"];
                _currentPage=[[json objectForKey:@"current_page"] integerValue];
                _totalTickets=[[json objectForKey:@"total"] integerValue];
                _totalPages=[[json objectForKey:@"last_page"] integerValue];
                NSLog(@"Thread-NO4.1getInbox-dic--%@", _mutableArray);
                dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [[AppDelegate sharedAppdelegate] hideProgressView];
                        [refresh endRefreshing];
                        [self.tableView reloadData];
                    });
                });

            }
            NSLog(@"Thread-NO5-getInbox-closed");

        }];
    }
}

and here is cellForRowAtIndexPath method,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{


if (indexPath.row == [_mutableArray count]) {

   LoadingTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"LoadingCellID"];
    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"LoadingTableViewCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }
   UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:1];
    [activityIndicator startAnimating];
    return cell;
}else{

    TicketTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"TableViewCellID"];

    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"TicketTableViewCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

        NSDictionary *finaldic=[_mutableArray objectAtIndex:indexPath.row];

        cell.ticketIdLabel.text=[finaldic objectForKey:@"ticket_number"];


    NSString *fname= [finaldic objectForKey:@"first_name"];
     NSString *lname= [finaldic objectForKey:@"last_name"];
    NSString *userName= [finaldic objectForKey:@"user_name"];


    [Utils isEmpty:fname];
    [Utils isEmpty:lname];

   if  (![Utils isEmpty:fname] && ![Utils isEmpty:lname])
   {
        cell.mailIdLabel.text=[NSString stringWithFormat:@"%@ %@",[finaldic objectForKey:@"first_name"],[finaldic objectForKey:@"last_name"]];
    }
    else
    { if(![Utils isEmpty:userName])
       {
        cell.mailIdLabel.text=[finaldic objectForKey:@"user_name"];
       }
        else
        {
            cell.mailIdLabel.text=[finaldic objectForKey:@"email"];
        }

    }


    NSString *title1= [finaldic objectForKey:@"title"];

    [Utils isEmpty:title1];

    if  ([Utils isEmpty:title1]){
         cell.ticketSubLabel.text=@"No Title";
    }
    else
    {
        cell.ticketSubLabel.text=[finaldic objectForKey:@"title"];
    }




    return cell;
}

}

and my web service class method is,

-(void)httpResponseGET:(NSString *)urlString
             parameter:(id)parameter
       callbackHandler:(callbackHandler)block{

    NSError *error;
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];

    //[request addValue:@"text/html" forHTTPHeaderField:@"Accept"];
    [request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setTimeoutInterval:45.0];

    NSData *postData = nil;
    if ([parameter isKindOfClass:[NSString class]]) {
        postData = [((NSString *)parameter) dataUsingEncoding:NSUTF8StringEncoding];
    } else {
        postData = [NSJSONSerialization dataWithJSONObject:parameter options:0 error:&error];
    }
    [request setHTTPBody:postData];

    [request setHTTPMethod:@"GET"];

    NSLog(@"Thread--httpResponseGET--Request : %@", urlString);

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] ];

    [[session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {
        NSLog(@"Response is required : %@",(NSHTTPURLResponse *) response);
        if (error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                block(error,nil,nil);
            });
            NSLog(@"Thread--httpResponseGET--dataTaskWithRequest error: %@", [error localizedDescription]);

        }else if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

            NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];

            if (statusCode != 200) {
                NSLog(@"dataTaskWithRequest HTTP status code: %ld", (long)statusCode);

                if (statusCode==400) {
                    if ([[self refreshToken] isEqualToString:@"tokenRefreshed"]) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            block(nil,nil,@"tokenRefreshed");
                        });
                        NSLog(@"Thread--httpResponsePOST--tokenRefreshed");
                    }else {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            block(nil,nil,@"tokenNotRefreshed");
                        });
                        NSLog(@"Thread--httpResponsePOST--tokenNotRefreshed");
                    }
                }else
                    dispatch_async(dispatch_get_main_queue(), ^{
                        block(nil, nil,[NSString stringWithFormat:@"Error-%ld",(long)statusCode]);
                    });
                return ;
            }

            NSString *replyStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

            if ([replyStr containsString:@"token_expired"]) {
                NSLog(@"Thread--httpResponseGET--token_expired");

                if ([[self refreshToken] isEqualToString:@"tokenRefreshed"]) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        block(nil,nil,@"tokenRefreshed");
                    });
                    NSLog(@"Thread--httpResponseGET--tokenRefreshed");
                }else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        block(nil,nil,@"tokenNotRefreshed");
                    });
                    NSLog(@"Thread--httpResponseGET--tokenNotRefreshed");
                }
                return;
            }

            NSError *jsonerror = nil;
            id responseData =  [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonerror];

            dispatch_async(dispatch_get_main_queue(), ^{
                block(jsonerror,responseData,nil);
            });

        }
    }] resume];

}

2 Answers2

2

OK, first the string is a Q-encode and is a MIME Header from an Email.

The "Q" encoding is similar to the "Quoted-Printable" content- transfer-encoding defined in RFC 1521. It is designed to allow text containing mostly ASCII characters to be decipherable on an ASCII terminal without decoding.

  1. Any 8-bit value may be represented by a "=" followed by two hexadecimal digits. For example, if the character set in use were ISO-8859-1, the "=" character would thus be encoded as "=3D", and a SPACE by "=20". (Upper case should be used for hexadecimal digits "A" through "F".)

  2. The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be represented as "" (underscore, ASCII 95.). (This character may not pass through some internetwork mail gateways, but its use will greatly enhance readability of "Q" encoded data with mail readers that do not support this encoding.) Note that the "" always represents hexadecimal 20, even if the SPACE character occupies a different code position in the character set in use.

  3. 8-bit values which correspond to printable ASCII characters other than "=", "?", "_" (underscore), and SPACE may be represented as those characters. (But see section 5 for restrictions.)

source http://www.freesoft.org/CIE/RFC/1522/6.htm

This issue was resolved in other stackoverflow's post:

  1. Mime Encoded-Word parsing in Objective-C

In the post above is shown a snippet code to replace the Q-coded string with base 64 support and transform it to a valid NSString format:

@implementation NSString (MimeEncodedWord)

- (BOOL) isMimeEncodedWord
{
    return [self hasPrefix:@"=?"]  && [self hasSuffix:@"?="];
}

+ (NSString*) stringWithMimeEncodedWord:(NSString*)word
{ // Example: =?iso-8859-1?Q?=A1Hola,_se=F1or!?=
    NSArray *components = [word componentsSeparatedByString:@"?"];
    if (components.count < 5) return nil;

    NSString *charset = [components objectAtIndex:1];
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset)); // TODO: What happens if the encoding is invalid?

    NSString *encodingType = [components objectAtIndex:2];
    NSString *encodedText = [components objectAtIndex:3];
    if ([encodingType isEqualToString:@"Q"])
    { // quoted-printable
        encodedText = [encodedText stringByReplacingOccurrencesOfString:@"_" withString:@" "];
        encodedText = [encodedText stringByReplacingOccurrencesOfString:@"=" withString:@"%"];
        NSString *decoded = [encodedText stringByReplacingPercentEscapesUsingEncoding:encoding];
        return decoded;
    } else if ([encodingType isEqualToString:@"B"])
    { // base64
        NSData *data = [QSStrings decodeBase64WithString:encodedText];
        NSString *decoded = [[NSString alloc] initWithData:data encoding:encoding];
        return decoded;
    } else {
        NSLog(@"%@ is not a valid encoding (must be Q or B)", encodingType);
        return nil;
    }    
}

@end

This code is also found in a Github post as a NSString class category here: https://github.com/hpique/NSString-MimeEncodedWord

Hope it helps

Community
  • 1
  • 1
Sophy Swicz
  • 1,307
  • 11
  • 21
2

check following code, I hope it will work. I created according to your code..! This code taken from @Sophy Swicz.

 NSString *encodedString =[finaldic objectForKey:@"title"];


        [Utils isEmpty:encodedString];

        if  ([Utils isEmpty:encodedString]){
            cell.ticketSubLabel.text=@"No Title";
        }
        else
        {

        NSMutableString *decodedString = [[NSMutableString alloc] init];

        if ([encodedString hasPrefix:@"=?UTF-8?Q?"] || [encodedString hasSuffix:@"?="])
        {
            NSScanner *scanner = [NSScanner scannerWithString:encodedString];
            NSString *buf = nil;
            //  NSMutableString *decodedString = [[NSMutableString alloc] init];

            while ([scanner scanString:@"=?UTF-8?Q?" intoString:NULL]
                   || ([scanner scanUpToString:@"=?UTF-8?Q?" intoString:&buf] && [scanner scanString:@"=?UTF-8?Q?" intoString:NULL])) {
                if (buf != nil) {
                    [decodedString appendString:buf];
                }

                buf = nil;

                NSString *encodedRange;

                if (![scanner scanUpToString:@"?=" intoString:&encodedRange]) {
                    break; // Invalid encoding
                }

                [scanner scanString:@"?=" intoString:NULL]; // Skip the terminating "?="

                // Decode the encoded portion (naively using UTF-8 and assuming it really is Q encoded)
                // I'm doing this really naively, but it should work

                // Firstly I'm encoding % signs so I can cheat and turn this into a URL-encoded string, which NSString can decode
                encodedRange = [encodedRange stringByReplacingOccurrencesOfString:@"%" withString:@"=25"];

                // Turn this into a URL-encoded string
                encodedRange = [encodedRange stringByReplacingOccurrencesOfString:@"=" withString:@"%"];


                // Remove the underscores
                encodedRange = [encodedRange stringByReplacingOccurrencesOfString:@"_" withString:@" "];

               // [decodedString appendString:[encodedRange stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

                NSString *str1= [encodedRange stringByRemovingPercentEncoding];
                [decodedString appendString:str1];


            }

            NSLog(@"Decoded string = %@", decodedString);

            cell.ticketSubLabel.text= decodedString;
        }
        else{

            cell.ticketSubLabel.text= encodedString;

        }

        }