Parsing Wordpress XML iOS / Objective-C - ios

I am trying to create an iOS app which (besides a few other things) needs to load in the content of a Wordpress-Page
When I use the getPosts feature from Wordpress's XML-RPC feature, I get the following returned:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><struct>
<member><name>post_id</name><value><string>23</string></value></member>
<member><name>post_title</name><value><string><!--:de-->Post1<!--:--><!--:en-->Post1<!--:--></string></value></member>
<member><name>post_date</name><value><dateTime.iso8601>20140211T14:26:39</dateTime.iso8601></value></member>
<member><name>post_date_gmt</name><value><dateTime.iso8601>20140211T12:26:39</dateTime.iso8601></value></member>
<member><name>post_modified</name><value><dateTime.iso8601>20140217T22:32:45</dateTime.iso8601></value></member>
<member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:32:45</dateTime.iso8601></value></member>
<member><name>post_status</name><value><string>publish</string></value></member>
<member><name>post_type</name><value><string>post</string></value></member>
<member><name>post_name</name><value><string>im-notfall</string></value></member>
<member><name>post_author</name><value><string>1</string></value></member>
<member><name>post_password</name><value><string></string></value></member>
<member><name>post_excerpt</name><value><string></string></value></member>
<member><name>post_content</name><value><string><!--:de--><b>Post1</b><!--:--><!--:en--><b>Post1</b><!--:--></string></value></member>
<member><name>post_parent</name><value><string>0</string></value></member>
<member><name>post_mime_type</name><value><string></string></value></member>
<member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=23</string></value></member>
<member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=23</string></value></member>
<member><name>menu_order</name><value><int>5</int></value></member>
<member><name>comment_status</name><value><string>closed</string></value></member>
<member><name>ping_status</name><value><string>open</string></value></member>
<member><name>sticky</name><value><boolean>0</boolean></value></member>
<member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
<member><name>post_format</name><value><string>standard</string></value></member>
<member><name>terms</name><value><array><data>
<value><struct>
<member><name>term_id</name><value><string>1</string></value></member>
<member><name>name</name><value><string>Allgemein</string></value></member>
<member><name>slug</name><value><string>allgemein</string></value></member>
<member><name>term_group</name><value><string>0</string></value></member>
<member><name>term_taxonomy_id</name><value><string>1</string></value></member>
<member><name>taxonomy</name><value><string>category</string></value></member>
<member><name>description</name><value><string></string></value></member>
<member><name>parent</name><value><string>0</string></value></member>
<member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
<member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
<value><struct>
<member><name>post_id</name><value><string>9</string></value></member>
<member><name>post_title</name><value><string><!--:de-->Post2<!--:--><!--:en-->Post2<!--:--></string></value></member>
<member><name>post_date</name><value><dateTime.iso8601>20140206T13:16:56</dateTime.iso8601></value></member>
<member><name>post_date_gmt</name><value><dateTime.iso8601>20140206T11:16:56</dateTime.iso8601></value></member>
<member><name>post_modified</name><value><dateTime.iso8601>20140217T22:33:01</dateTime.iso8601></value></member>
<member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:33:01</dateTime.iso8601></value></member>
<member><name>post_status</name><value><string>publish</string></value></member>
<member><name>post_type</name><value><string>post</string></value></member>
<member><name>post_name</name><value><string>neuer-erster-beitrag</string></value></member>
<member><name>post_author</name><value><string>1</string></value></member>
<member><name>post_password</name><value><string></string></value></member>
<member><name>post_excerpt</name><value><string></string></value></member>
<member><name>post_content</name><value><string><!--:de--><b>Post2</b><!--:--><!--:en--><b>Post2</b><!--:--></string></value></member>
<member><name>post_parent</name><value><string>0</string></value></member>
<member><name>post_mime_type</name><value><string></string></value></member>
<member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=9</string></value></member>
<member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=9</string></value></member>
<member><name>menu_order</name><value><int>3</int></value></member>
<member><name>comment_status</name><value><string>closed</string></value></member>
<member><name>ping_status</name><value><string>open</string></value></member>
<member><name>sticky</name><value><boolean>0</boolean></value></member>
<member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
<member><name>post_format</name><value><string>standard</string></value></member>
<member><name>terms</name><value><array><data>
<value><struct>
<member><name>term_id</name><value><string>1</string></value></member>
<member><name>name</name><value><string>Allgemein</string></value></member>
<member><name>slug</name><value><string>allgemein</string></value></member>
<member><name>term_group</name><value><string>0</string></value></member>
<member><name>term_taxonomy_id</name><value><string>1</string></value></member>
<member><name>taxonomy</name><value><string>category</string></value></member>
<member><name>description</name><value><string></string></value></member>
<member><name>parent</name><value><string>0</string></value></member>
<member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
<member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
<value><struct>
<member><name>post_id</name><value><string>5</string></value></member>
<member><name>post_title</name><value><string><!--:de-->Post3<!--:--><!--:en-->Post3<!--:--></string></value></member>
<member><name>post_date</name><value><dateTime.iso8601>20131217T17:32:09</dateTime.iso8601></value></member>
<member><name>post_date_gmt</name><value><dateTime.iso8601>20131217T15:32:09</dateTime.iso8601></value></member>
<member><name>post_modified</name><value><dateTime.iso8601>20140217T22:33:18</dateTime.iso8601></value></member>
<member><name>post_modified_gmt</name><value><dateTime.iso8601>20140217T20:33:18</dateTime.iso8601></value></member>
<member><name>post_status</name><value><string>publish</string></value></member>
<member><name>post_type</name><value><string>post</string></value></member>
<member><name>post_name</name><value><string>test-beitrag-2</string></value></member>
<member><name>post_author</name><value><string>1</string></value></member>
<member><name>post_password</name><value><string></string></value></member>
<member><name>post_excerpt</name><value><string></string></value></member>
<member><name>post_content</name><value><string><!--:de--><b>Post3</b><!--:--><!--:en--><b>Post3</b><!--:--></string></value></member>
<member><name>post_parent</name><value><string>0</string></value></member>
<member><name>post_mime_type</name><value><string></string></value></member>
<member><name>link</name><value><string>http://example.com/ExampleProjekt/?p=5</string></value></member>
<member><name>guid</name><value><string>http://example.com/ExampleProjekt/?p=5</string></value></member>
<member><name>menu_order</name><value><int>4</int></value></member>
<member><name>comment_status</name><value><string>closed</string></value></member>
<member><name>ping_status</name><value><string>open</string></value></member>
<member><name>sticky</name><value><boolean>0</boolean></value></member>
<member><name>post_thumbnail</name><value><array><data>
</data></array></value></member>
<member><name>post_format</name><value><string>standard</string></value></member>
<member><name>terms</name><value><array><data>
<value><struct>
<member><name>term_id</name><value><string>1</string></value></member>
<member><name>name</name><value><string>Allgemein</string></value></member>
<member><name>slug</name><value><string>allgemein</string></value></member>
<member><name>term_group</name><value><string>0</string></value></member>
<member><name>term_taxonomy_id</name><value><string>1</string></value></member>
<member><name>taxonomy</name><value><string>category</string></value></member>
<member><name>description</name><value><string></string></value></member>
<member><name>parent</name><value><string>0</string></value></member>
<member><name>count</name><value><int>3</int></value></member>
</struct></value>
</data></array></value></member>
<member><name>custom_fields</name><value><array><data>
</data></array></value></member>
</struct></value>
</data></array>
</value>
</param>
</params>
</methodResponse>
Specifically I would need the following fields:
post_id
post_title
post_motified
post_content
menu_order
I've tried a few options to achieve this.
One was using Gdata, which has been recommended in another post, but the example is for a simpler xml, and I can't seem to get it to work for me.
NSArray *tempPosts = [XMLdoc nodesForXPath:#"//methodResponse/params/param/value/array/data/value/struct/member" error:nil];
I also tried using the WPXMLRPC framework -> https://github.com/wordpress-mobile/wpxmlrpc
Using this code:
WPXMLRPCDecoder *decodedWPXML = [[WPXMLRPCDecoder alloc] initWithData:XMLcontent];
if ([decodedWPXML isFault]) {
NSLog(#"XML-RPC error %ld: %#", (long)[decodedWPXML faultCode], [decodedWPXML faultString]);
} else {
NSLog(#"XML-RPC response: %#", [decodedWPXML object]);
}
I manage to receive an object, which I can output via NSLog(#"%#", object);
But I fail to further process any data I receive that way.
I am (maybe obvious for some) very new to objective-c.
I have also looked at the official wordpress for iOS app, but I wasn't able to make use of any code.
Any help would be appreciated, I don't mind using any different frameworks/technologies, etc. if they help getting to my solution.

I am happy with Wordpress JSON plugin, it's free. You can easily fine tune your requests to specific pages and post types, it's well documented. What you get back from your site is always a structure of dictionaries and arrays in JSON (better then XML ;). Good way to examine the JSON structure is a JSON viewer.
Some sample code to get started.
- (void)loadNewsForPage:(NSUInteger)page
{
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.mywordpresssite.com/api/get_posts/?page=%lu", (unsigned long)page]]
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle response
NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (!jsonError) {
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
// fill datastore
[self newsIntoDataStore:(NSDictionary *)jsonObject forPage:page];
}
else {
NSLog(#"returned jsonObject is not a dictionary!");
}
} else {
NSLog(#"jsonError, news: %#", jsonError);
}
}] resume];
}
- (void)newsIntoDataStore:(NSDictionary *)news forPage:(NSUInteger)page
{
if ([[news objectForKey:#"status"] isEqualToString:#"ok"]) {
self.newsPages = [[news objectForKey:#"pages"] integerValue];
NSArray *posts = [news objectForKey:#"posts"];
if (posts.count > 0) {
// store individual posts
for (NSDictionary *post in posts) {
// determine post slug
NSArray *categoriesArray = [post objectForKey:#"categories"];
NSString *postSlug = nil;
NSString *desiredSlug = #"news";
if (categoriesArray.count > 0) {
for (NSDictionary *category in categoriesArray) {
if ([[category objectForKey:#"slug"] isEqualToString:desiredSlug]) {
postSlug = desiredSlug;
}
}
}
NSString *title = [post objectForKey:#"title"];
NSDate *dateFromAPI = [self.dateFormatterFromAPI dateFromString:[post objectForKey:#"date"]];
NSString *date = [self.dateFormatterForCell stringFromDate:dateFromAPI];
NSString *imageURLStringOrg = [[[post objectForKey:#"thumbnail_images"] objectForKey:#"full"] objectForKey:#"url"];
NSString *imageURLStringConverted = [imageURLStringOrg stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *attributedContentString = [[NSAttributedString alloc] initWithData:[[post objectForKey:#"excerpt"] dataUsingEncoding:NSUTF8StringEncoding] options:#{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
NSString *content = [attributedContentString string];
NSString *url = [post objectForKey:#"url"];
if (title && date && imageURLStringConverted && content && url) {
NSDictionary *postDictionary = #{#"title" : title, #"date" : date, #"imageURL" : imageURLStringConverted, #"content" : content, #"url" : url};
[self.newsArray addObject:postDictionary];
} else {
NSLog(#"some post item empty, skipping this post: %lu", (unsigned long)[posts indexOfObject:post]);
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
if (self.pageLoaded < self.newsPages) {
[self loadNewsForPage:self.pageLoaded + 1];
} else {
[self.delegate newsFetchingCompleted];
}
});
} else {
NSLog(#"no objects in the array");
}
} else {
NSLog(#"returned status NOT OK");
}
}

GDataXMLDocument *XMLdoc = [[GDataXMLDocument alloc] initWithData:XMLcontent options:0 error:nil];
NSArray *XMLofPosts = [XMLdoc nodesForXPath:#"//methodResponse/params/param/value/array/data/value/struct/member" error:nil];
gives me an array of all post members that i can iterate via
for(GDataXMLElement *postMember in XMLofPosts){ ... }
Thansk for the help.
I've opened a new post for a more detailed question on the subject, since I found it's pretty much a different question, since it's on GDataXML more than getting the Wordpress XML
GDataXML nodesForXPath on Node contains items of entire GDataXMLDocument

Related

How can I use NSJSONSerialization with special characters like "ñ"?

I'm using NSJSONSerialization to parse Google suggestions.
The query "f" returns these suggestions:
["f",["facebook","flipkart","fox news","forever 21","friv","fandango","fedex","fitbit","food near me","flights"]]
The parser works fine but when there are special characters like "ñ" for the query "fac":
["fac",["facebook","facebook search","fac","facebook app","facebook lite","facebook login","facebook logo","facebook messenger","facetime","facebook en español"]]
It throws an exception:
Error Domain=NSCocoaErrorDomain Code=3840 "Unable to convert data to string around character 139." UserInfo={NSDebugDescription=Unable to convert data to string around character 139.}
Any ideas? I tried all different reading options but none of them works.
#pragma mark -
- (void)request:(NSString *)text
{
NSMutableArray *items = [[NSMutableArray alloc] init];
NSString *query = [text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *languageCode = [[NSLocale preferredLanguages] firstObject];
if (!languageCode) {
languageCode = #"en";
}
NSString *URLString = [NSString stringWithFormat:#"http://suggestqueries.google.com/complete/search?q=%#&client=firefox&hl=%#", query, languageCode];
NSError *downloadError = nil;
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
if (!downloadError && JSONData) {
NSError *parseError = nil;
id object = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableContainers error:&parseError];
if (!parseError && object) {
if ([object isKindOfClass:[NSArray class]]) {
NSArray *objects = (NSArray *)object;
NSArray *texts = [objects objectAtIndex:1];
for (NSString *text in texts) {
SNGoogleItem *item = [[SNGoogleItem alloc] initWithText:text];
[items addObject:item];
}
[_delegate google:self didRespondWithItems:items];
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
JSONSerialization supports all the encodings in JSON spec, says Apple documentation.
You didn't provide much info about the encoding scheme of your data but I guess you use nonLossyASCII or something like that, which is not supported by JSONSerialization.
Here is how I convert data to/from JSON:
let rawString = "[[\"facebook en español\"]]"
// if I use String.Encoding.nonLossyASCII below, I get the error you are getting
let data = rawString.data(using: String.Encoding.utf8)
let dict = try! JSONSerialization.jsonObject(with: data!)
let convertedData = try! JSONSerialization.data(withJSONObject: dict)
let convertedString = String(data: convertedData, encoding: String.Encoding.utf8)!
// now convertedString contains "ñ" character
This will convert whatever encoding used to UTF8:
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
NSString *convertedJSONString; BOOL usedLossyConversion;
[NSString stringEncodingForData:JSONData encodingOptions:0 convertedString:&convertedJSONString usedLossyConversion:&usedLossyConversion];
NSData *convertedJSONData = [convertedJSONString dataUsingEncoding:NSUTF8StringEncoding];
Now, it works!

Any tools to beautify the nested NSDictionary result

Is there any tools, including online service and macOs app, to beautify the nested NSDictionary result like this?
{
id = 1;
testName = my name;
createDate = 20021023;
likeNumber = 0;
statusList = ({
appleId = 1;
orangeName = 81;
itsStatus = YES;
});
text = test;
type = Text;
},
I mean collapse(close and open) the tree nodes easily.
Currently ,there are many online tools for this purpose when it comes to JSON like jsonformatter.
As Fonix mentioned, the best way to convert NSDictionary to JSON and then use JSON tools for this purpose:
+(NSString *)dictionaryToJson:(NSDictionary *)dictionary {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
NSString *jsonString;
if (! jsonData) {
NSLog(#"Got an error: %#", error);
jsonString = [error localizedDescription];
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}

How do you get the "images" from a twitter feed to show in an iOS app

I have a code that accesses a Twitter feed and puts the text into a table. I then edited the code so I could display the text in my custom fashion in separate views, but I wanted to grab images from the tweets as well, and despite over an hour searching could not find a single reference. I have seen how to "Post" images, but to be clear, I need to get and "display" the images from the tweet in question.
Here are the highlights from my code that handles the Twitter Access:
-(void)twitterTimeLine
{
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if (granted == YES)
{
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0)
{
ACAccount *twitterAccount = [arrayOfAccounts lastObject]; // last account on list of accounts
NSURL *requestAPI = [NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/user_timeline.json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:#"30" forKey:#"count"];
[parameters setObject:#"1" forKey:#"incude_entities"];
SLRequest *posts = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestAPI parameters:parameters];
posts.account = twitterAccount;
[posts performRequestWithHandler:^(NSData *response, NSHTTPURLResponse *urlResponse, NSError *error) {
if (response)
{
// TODO: might want to check urlResponse.statusCode to stop early
NSError *jsonError; // use new instance here, you don't want to overwrite the error you got from the SLRequest
NSArray *array =[NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&jsonError];
if (array) {
if ([array isKindOfClass:[NSArray class]]) {
self.array = array;
NSLog(#"resulted array: %#",self.array);
}
else {
// This should never happen
NSLog(#"Not an array! %# - %#", NSStringFromClass([array class]), array);
}
}
else {
// TODO: Handle error in release version, don't just dump out this information
NSLog(#"JSON Error %#", jsonError);
NSString *dataString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(#"Received data: %#", dataString ? dataString : response); // print string representation if response is a string, or print the raw data object
}
}
else {
// TODO: show error information to user if request failed
NSLog(#"request failed %#", error);
}
self.array = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
if (self.array.count != 0)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData]; // this part loads into table - important!
});
}
}];
}
}
else
{
NSLog(#"%#", [error localizedDescription]);
}
}];
}
and here is how I display the Tweet
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
NSDictionary *tweet = _array[indexPath.row];
cell.textLabel.text = tweet[#"text"];
//NSString *element = [myArray objectAtIndex:2];
//NSString *element = myArray[2];
// I created some custom views to show the text, but kept the table for testing purposes
TemplateView *tempView = [viewArray objectAtIndex:testCounter];
tempView.TweetView.text = tweet[#"text"];
// -> this was what I was hoping for // tempView.ContentView.image = tweet[#"image"];
testCounter++;
if (testCounter >= 30)
{
testCounter = 0;
}
return cell;
}
I took out the key lines that I think is where I need to look:
tempView.TweetView.text = tweet[#"text"];
tempView.ContentView.image = tweet[#"image"];
// hoping that the latter would work as the first one does, but clearly it's not that simple
This might not be possible, if so, how would I get the images from the "link" (url) and make sure it is an image and not a video or other website?
I could set up a "word search" to grab text starting with http from the tweet and hopefully generate a URL from the string
TwitterKit doesn't seem to support images publicly.. I'm having the same stupid issue. The API internally holds images when using the built in tableview and datasource.. It requires a listID and a Slug.. However, when you want the images via JSON, you are out of luck! Even TWTRTweet object doesn't have entities or media properties!
Not sure how anyone can develop such an awful API.. In any case, I reversed the server calls made internally and found that it sends other "undocumented" parameters..
Example:
TWTRAPIClient *client = [[TWTRAPIClient alloc] init];
NSString *endpoint = #"https://api.twitter.com/1.1/statuses/user_timeline.json";
NSDictionary *params = #{#"screen_name":#"SCREEN_NAME_HERE",
#"count": #"30"};
will return NO MEDIA.. even if you have #"include_entities" : #"true".
Solution:
TWTRAPIClient *client = [[TWTRAPIClient alloc] init];
NSString *endpoint = #"https://api.twitter.com/1.1/statuses/user_timeline.json";
NSDictionary *params = #{#"screen_name":#"SCREEN_NAME_HERE",
#"count": #"30",
#"tweet_mode": #"extended"};
With tweet_mode set to extended (tweet_mode is an undocumented parameter), it will now return the media as part of the response.. This includes the "type" which is "photo" for images.
We can get tweets with images by applying "filter=images" query with "include_entities=true". It'll give tweets with media entities, under which we can see type="photo" and other related data.
For ex:
https://api.twitter.com/1.1/search/tweets.json?q=nature&include_entities=true&filter=images
Try this query at twitter developer console and see the response format: https://dev.twitter.com/rest/tools/console
Hope this will help.

Import .ics File and show in Calendar or UITableView

I retrieve an .ics file from a certain url. I'd like to present the information of this file in a calendar and/or list view in my own app. I had a look at iCal4Objc("https://github.com/cybergarage/iCal4ObjC") and parsed the information like this:
-(NSMutableArray *)getPlanFromURL:(NSURL *)url {
NSMutableArray *planEntries = [[NSMutableArray alloc]init];
NSString *storePath = [self loadICSAndReturnPathFromURL:url];
CGICalendar *parserCalendar = [[CGICalendar alloc]initWithPath:storePath];
for(CGICalendarObject *planObject in [parserCalendar objects]) {
for(CGICalendarComponent *component in [planObject components]) {
for (CGICalendarProperty *icalProp in [component properties]) {
NSString *icalPropName = [icalProp name];
NSLog(#"%#",icalPropName);
if([icalPropName isEqualToString:SUMMARY]) {
[self.summaryArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:LOCATION]) {
[self.locationArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:CATEGORIES]) {
[self.categoryArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:DTSTART]) {
[self.startArray addObject:[icalProp dateValue]];
}
else if([icalPropName isEqualToString:DTEND]) {
[self.endArray addObject:[icalProp dateValue]];
}
}
}
}
for(int i = 0;i<[self.summaryArray count];i++) {
DECalEntry *entry = [[DECalEntry alloc]init];
entry.summary = [self.summaryArray objectAtIndex:i];
entry.roomInformation = [self.locationArray objectAtIndex:i];
entry.category = [self.categoryArray objectAtIndex:i];
entry.startDate = [self.startArray objectAtIndex:i];
entry.endDate = [self.endArray objectAtIndex:i];
if ([entry.category isEqualToString:#"Prüfung"]) {
entry.isExam = true;
}
else entry.isExam = false;
[planEntries addObject:entry];
}
return planEntries;
}
-(NSString *)loadICSAndReturnPathFromURL:(NSURL *)url {
NSURLRequest * urlRequest = [NSURLRequest requestWithURL:url];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
if (error == nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *storePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory, #"planData.ics"];
[data writeToFile:storePath atomically:YES];
return storePath;
}
NSLog(#"Error: %#",[error localizedDescription]);
return nil;
}
Since this is not very clean and it would be a pain to also implement UITableView and a calendar view to illustrate the parsed data i asked me whether there exists a framework that one of you knows which already can handle .ics files and shows them accordingly.
If you have an idea how to solve this issue less complicated and/or with less effort i would be really grateful.
Also have a look at my comment. At the moment the rrule property is not considered at all. But this is very important since it shows me if a event is repeated, until it is repeated and so on...
Nevermind i got it working myself by parsing the rrule property like i did it with the other properties and constructed a method which creates the right amount of objects i need by following the information that this property contains. Well i just think this was the only way because apparently the is no framework for importing and parsing .ics files. When i finish my project i might give it a shot for people who might face this one day.
To my knowledge there is no framework or control provided by Apple that displays .ics files, but once you construct an EKEvent, there is:
https://developer.apple.com/library/ios/documentation/EventKitUI/Reference/EKEventEditViewControllerClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40009571
Specifically, you want to take a look at EventKitUI.framework.

XML into JSON conversion in iOS

I need to convert XML response to JSON and sand to the json To javaScript code.
My XML response:
<cell>
<Result>True</Result>
<sguid>02291c402-2220-422b-b199-f92f22e56d2f</sguid>
</cell>
I am using XMLReader supporting file from this site:
XMLReader
I am using this code to convert XML to JSON :
+ (NSString*) XMLToJson:(CXMLDocument *)xmlDocument
{
NSError *error = nil;
NSArray *resultNodes = [xmlDocument nodesForXPath:#"//cell" error:&error];
if(error)
NSLog(#"%#",error.description);
CXMLNode *cellNode = [resultNodes objectAtIndex:0];
NSLog(#"%#",cellNode.XMLString);
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:cellNode.XMLString error:&parseError];
NSLog(#"%#", xmlDictionary);
//{print this.
// cell = {
// Result = {
// text = True;
// };
// sguid = {
// text = "0391c402-1120-460b-b199-f92fffe56d2f";
// };
// };
//}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:xmlDictionary
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if(error)
NSLog(#"%#",error.description);
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"%#", jsonString);
return jsonString;
}
I got JSON response like this:
{
"cell" : {
"Result" : {
"text" : "True"
},
"sguid" : {
"text" : "0391c402-1120-460b-b199-f92fffe56d2f"
}
}
}
I need JSON response like this:
{
"cell": {
"Result": "True",
"sguid": "02291c402-2220-422b-b199-f92f22e56d2f"
}
}
Because then I send this json to javascript code I get that exception jquery mobile dont know parser this and throws an exception of syntax error.
I've seen programmers use this solution and is helping them but I still get the same result in this solution.
XML into JSON conversion in iOS
thanks
I just wrote a function for your problem, I tried it on with a couple of XMLs. Let me know if you find any issues
- (NSMutableDictionary *)extractXML:(NSMutableDictionary *)XMLDictionary
{
for (NSString *key in [XMLDictionary allKeys]) {
// get the current object for this key
id object = [XMLDictionary objectForKey:key];
if ([object isKindOfClass:[NSDictionary class]]) {
if ([[object allKeys] count] == 1 &&
[[[object allKeys] objectAtIndex:0] isEqualToString:#"text"] &&
![[object objectForKey:#"text"] isKindOfClass:[NSDictionary class]]) {
// this means the object has the key "text" and has no node
// or array (for multiple values) attached to it.
[XMLDictionary setObject:[object objectForKey:#"text"] forKey:key];
}
else {
// go deeper
[self extractXML:object];
}
}
else if ([object isKindOfClass:[NSArray class]]) {
// this is an array of dictionaries, iterate
for (id inArrayObject in (NSArray *)object) {
if ([inArrayObject isKindOfClass:[NSDictionary class]]) {
// if this is a dictionary, go deeper
[self extractXML:inArrayObject];
}
}
}
}
return XMLDictionary;
}
And use it like this
NSDictionary *clearXML = [[self extractXML:[yourParsedXMLDictionary mutableCopy]] copy];
Your problem in using XMLReader. For resolve this problem you can use XMLConverter instead of the XMLReader.

Resources