I have working codes with local sample_data.son but I want to use remote sample_data.json. It's working but I didn't find true way. My code below.
- (void)generateData
{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Add code here to do background processing
//
//
NSError* err = nil;
data = [[NSMutableArray alloc] init];
companyData = [[NSMutableArray alloc] init];
NSString* dataPath = [[NSBundle mainBundle] pathForResource:#"sample_data" ofType:#"json"];
NSArray* contents = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath] options:kNilOptions error:&err];
dispatch_async( dispatch_get_main_queue(), ^{
// Add code here to update the UI/send notifications based on the
// results of the background processing
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[data addObject:[NSDictionary dictionaryWithObjectsAndKeys:[[obj objectForKey:#"first_name"] stringByAppendingString:[NSString stringWithFormat:#" %#", [obj objectForKey:#"last_name"]]], #"DisplayText", [obj objectForKey:#"email"], #"DisplaySubText",obj,#"CustomObject", nil]];
[companyData addObject:[NSDictionary dictionaryWithObjectsAndKeys:[obj objectForKey:#"company_name"], #"DisplayText", [obj objectForKey:#"address"], #"DisplaySubText",obj,#"CustomObject", nil]];
}];
});
});
}
#pragma mark MPGTextField Delegate Methods
- (NSArray *)dataForPopoverInTextField:(MPGTextField *)textField
{
if ([textField isEqual:self.name]) {
return data;
}
else if ([textField isEqual:self.companyName]){
return companyData;
}
else{
return nil;
}
}
- (BOOL)textFieldShouldSelect:(MPGTextField *)textField
{
return YES;
}
- (void)textField:(MPGTextField *)textField didEndEditingWithSelection:(NSDictionary *)result
{
//A selection was made - either by the user or by the textfield. Check if its a selection from the data provided or a NEW entry.
if ([[result objectForKey:#"CustomObject"] isKindOfClass:[NSString class]] && [[result objectForKey:#"CustomObject"] isEqualToString:#"NEW"]) {
//New Entry
[self.nameStatus setHidden:NO];
}
else{
//Selection from provided data
if ([textField isEqual:self.name]) {
[self.nameStatus setHidden:YES];
[self.web setText:[[result objectForKey:#"CustomObject"] objectForKey:#"web"]];
[self.email setText:[[result objectForKey:#"CustomObject"] objectForKey:#"email"]];
[self.phone1 setText:[[result objectForKey:#"CustomObject"] objectForKey:#"phone1"]];
[self.phone2 setText:[[result objectForKey:#"CustomObject"] objectForKey:#"phone2"]];
}
[self.address setText:[[result objectForKey:#"CustomObject"] objectForKey:#"address"]];
[self.state setText:[[result objectForKey:#"CustomObject"] objectForKey:#"state"]];
[self.zip setText:[[result objectForKey:#"CustomObject"] objectForKey:#"zip"]];
[self.companyName setText:[[result objectForKey:#"CustomObject"] objectForKey:#"company_name"]];
}
}
I need only change to local parsing code to remote parsing code.
Also you can see original project with local json here
https://github.com/gaurvw/MPGTextField
Not an answer, an example of cleaner code as an answer for formatting.
Original:
[data addObject:[NSDictionary dictionaryWithObjectsAndKeys:[[obj objectForKey:#"first_name"] stringByAppendingString:[NSString stringWithFormat:#" %#", [obj objectForKey:#"last_name"]]], #"DisplayText", [obj objectForKey:#"email"], #"DisplaySubText",obj,#"CustomObject", nil]];
Re-formatted:
NSString *fullName = [NSString stringWithFormat:#"%# %#", obj[#"first_name"], obj[#"last_name"]];
[data addObject: #{
#"DisplayText" : fullName,
#"DisplaySubText" : obj[#"email"],
#"CustomObject" : obj
}];
Related
Requirement:
We are able to make connection from host device to multiple slave devices. For example, if device A initiate connection to device B and C, the contributor devices can accept peer connection and connected to device A. Here A is master device and B and C are contributors device. Now if B share their songs to A, A can play songs and see songs information. In meantime C will be idle but should connected. When B will finish to play songs, then C can also able to share their songs to device A.
Here are the problem that we have faced to achieve above tasks:
1. As soon as B started sharing songs to A, C got crashed. But A still able to play song shared by B.
array = [[NSMutableArray alloc] initWithObjects:[self.session connectedPeers], nil];
[_session sendData:[NSKeyedArchiver archivedDataWithRootObject:[info mutableCopy]] toPeers:[array objectAtIndex:0] withMode:MCSessionSendDataUnreliable error: &error];
NSLog(#"localizedDescription %#",error);
To overcome from this problem directly pass array without index here toPeers:array. It is working and we are able to share and play songs with device A, but song information not receive to device A.
Here are full code that we are using:
contributor Controller :
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
[self dismissViewControllerAnimated:YES completion:nil];
someMutableArray = [mediaItemCollection items];
counter = 0;
if(someMutableArray.count>1){
BOOL isselectsongone=YES;
[[NSUserDefaults standardUserDefaults] setBool:isselectsongone forKey:#"isselectsongone"];
}
[self showSpinner];
[self someSelector:nil];
}
- (void)someSelector:(NSNotification *)notification {
if(notification && someMutableArray.count>1 && counter <someMutableArray.count-1){
NSDate *start = [NSDate date];
counter=counter+1;
[self.outputStreamer stop];
self.outputStreamer = nil;
self.outputStream = nil;
}
song=[someMutableArray objectAtIndex:counter];
NSMutableDictionary *info = [NSMutableDictionary dictionary];
info=[[NSMutableDictionary alloc] init];
info[#"title"] = [song valueForProperty:MPMediaItemPropertyTitle] ? [song valueForProperty:MPMediaItemPropertyTitle] : #"";
info[#"artist"] = [song valueForProperty:MPMediaItemPropertyArtist] ? [song valueForProperty:MPMediaItemPropertyArtist] : #"";
//NSNumber *duration=[song valueForProperty:MPMediaItemPropertyPlaybackDuration];
int fullminutes = floor([timeinterval floatValue] / 60); // fullminutes is an int
int fullseconds = trunc([duration floatValue] - fullminutes * 60); // fullseconds is an int
[NSTimer scheduledTimerWithTimeInterval:[duration doubleValue]target:self selector:#selector(getdata) userInfo:nil repeats:YES];
}
-(void)getdata {
NSMutableDictionary *info = [NSMutableDictionary dictionary];
info=[[NSMutableDictionary alloc] init];
info[#"title"] = [song valueForProperty:MPMediaItemPropertyTitle] ? [song valueForProperty:MPMediaItemPropertyTitle] : #"";
info[#"artist"] = [song valueForProperty:MPMediaItemPropertyArtist] ? [song valueForProperty:MPMediaItemPropertyArtist] : #"";
NSNumber *duration=[song valueForProperty:MPMediaItemPropertyPlaybackDuration];
int fullminutes = floor([duration floatValue] / 60); // fullminutes is an int
int fullseconds = trunc([duration floatValue] - fullminutes * 60); // fullseconds is an int
info[#"duration"] = [NSString stringWithFormat:#"%d:%d", fullminutes, fullseconds];
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage *image = [artwork imageWithSize:CGSizeMake(150, 150)];
NSData * data = UIImageJPEGRepresentation(image, 0.0);
image = [UIImage imageWithData:data];
array = [[NSMutableArray alloc] initWithObjects:[self.session connectedPeers], nil];
MCPeerID* peerID11 = self.session.myPeerID;
NSMutableArray *arr=[[NSMutableArray alloc] initWithObjects:peerID11, nil];
NSLog(#"%#",arr);
if (image)
self.songArtWorkImageView.image = image;
else
self.songArtWorkImageView.image = nil;
self.songTitleLbl.text = [NSString stringWithFormat:#"%# \n[Artist : %#]", info[#"title"], info[#"artist"]];
NSError *error;
[_session sendData:[NSKeyedArchiver archivedDataWithRootObject:[info mutableCopy]] toPeers:[array objectAtIndex:0] withMode:MCSessionSendDataUnreliable error: &error];
NSLog(#"localizedDescription %#",error);
#try {
if(_session && _session.connectedPeers && [_session.connectedPeers count] > 0) {
NSLog(#"%#",[song valueForProperty:MPMediaItemPropertyAssetURL]);
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[song valueForProperty:MPMediaItemPropertyAssetURL] options:nil];
[self convertAsset: asset complition:^(BOOL Success, NSString *filePath) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
if(Success) {
if(image) {
[self saveImage: image withComplition:^(BOOL status, NSString *imageName, NSURL *imageURL) {
if(status) {
#try {
[_session sendResourceAtURL:imageURL withName:imageName toPeer:[_session.connectedPeers objectAtIndex:0]withCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Failed to send picture to %#", error.localizedDescription);
return;
}
//Clean up the temp file
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:imageURL error:nil];
}];
}
#catch (NSException *exception) {
}
}
}];
}
#try {
[self hideSpinner];
if(!self.outputStream) {
NSArray * connnectedPeers = [_session connectedPeers];
if([connnectedPeers count] != 0) {
[self outputStreamForPeer:[_session.connectedPeers objectAtIndex:0]];
}
}
}
#catch (NSException *exception) {
}
if(self.outputStream) {
self.outputStreamer = [[TDAudioOutputStreamer alloc] initWithOutputStream:self.outputStream];
//
[self.outputStreamer initStream:filePath];
NSLog(#"%#",filePath);
if(self.outputStreamer) {
[self.outputStreamer start];
}
else{
NSLog(#"Error: output streamer not found");
}
}
else{
//self.outputStream=[[NSOutputStream alloc] init];
self.outputStreamer = [[TDAudioOutputStreamer alloc] initWithOutputStream:self.outputStream];
[self.outputStreamer initStream:filePath];
NSLog(#"%#",filePath);
if(self.outputStreamer) {
[self.outputStreamer start];
}
}
}
else {
[UIView showMessageWithTitle:#"Error!" message:#"Error occured!" showInterval:1.5];
}
});
}];
// }
}
}
#catch (NSException *exception) {
NSLog(#"Expection: %#", [exception debugDescription]);
}
//}
}
HostViewcontroller :
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID
{
NSLog(#"%#",peerID);
NSLog(#"sessions%#",session);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
#try {
// NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:data];
info = [NSKeyedUnarchiver unarchiveObjectWithData:data];
self.songTitleLbl.text = [NSString stringWithFormat:#"%# \n[Duration: %#] [Artist : %#] ", info[#"title"], info[#"duration"], info[#"artist"]];
NSLog(#"eeret%#",self.songTitleLbl.text);
self.songArtWorkImageView.image = nil;
[self showSpinner];
}
#catch (NSException *exception) {
self.songTitleLbl.text = #"Some error occured...\nPlease try again";
self.songArtWorkImageView.image = nil;
}
});
}
Please let us know if I have missed anything here or the better way to achieve the above requirement. Any help really appreciated.
I am calling a GET API , that takes a string keyword and returns me JSON data , which i parse and display in my UITableView
While the API returns data , I am displaying UIActivityIndicatorView, this is working fine.
However , as soon as the data is recieved the UIActivityIndicatorView disappears as expected but data does not show in the UITableView, but if i touch anywhere on the screen the data gets visible in the UI TableView.
This is my code:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
dispatch_queue_t queue = dispatch_queue_create("ID", NULL);
dispatch_async(queue, ^{
NSString *searchText=searchBar.text;
NSString *trimmedString = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
if (trimmedString.length==0) {
isFilter=NO;
UIAlertView *noConn = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Please enter something in search bar" delegate:self cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[noConn show];
} else {
NSString *searchNew = [trimmedString stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
isFilter=YES;
#try {
[label removeFromSuperview];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSString* myURLString = [NSString stringWithFormat:#"www.example.com=%#", searchNew];
NSURL *url = [NSURL URLWithString:myURLString];
NSData* data = [NSData dataWithContentsOfURL:url];
if ((unsigned long)data.length > 3) {
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(ys_avatars) {
for (int j=0;j<ys_avatars.count;j++) {
if( ys_avatars[j][#"title"]==[NSNull null] ) {
[_Title1 addObject: #""];
} else {
[_Title1 addObject:ys_avatars[j][#"title"]];
}
if( ys_avatars[j][#"author"]==[NSNull null] ) {
[_Author1 addObject: #""];
}
[_Author1 addObject: ys_avatars[j][#"author"]];
if( ys_avatars[j][#"featured_img"]==[NSNull null] ) {
[_Images1 addObject: #""];
} else {
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
}
if( ys_avatars[j][#"content"]==[NSNull null] ) {
[_Details1 addObject: #""];
} else {
[_Details1 addObject:ys_avatars[j][#"content"]];
}
if( ys_avatars[j][#"permalink"]==[NSNull null] ) {
[_link1 addObject: #""];
} else {
[_link1 addObject:ys_avatars[j][#"permalink"]];
}
if( ys_avatars[j][#"date"]==[NSNull null] ) {
[_Date1 addObject: #""];
} else {
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
} else {
NSLog(#"error");
}
[self.myTableView reloadData];
} else {
if(IDIOM == IPAD){
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(150, 200, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
} else {
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(90, 100, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
}
}
}
#catch (NSException *exception) { }
}
dispatch_async(dispatch_get_main_queue(), ^{
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
});
[self.mySearchBar resignFirstResponder];
}
Your basic problem is that you are trying to update the UI from background threads. All UI updates must be done on the main thread / queue.
Usually the easiest way to do that is by using:
dispatch_async(dispatch_get_main_queue(), ^{
// code to run on the main queue
});
I actually see that you're using that when you stop the UIActiviteIndicatorView here:
dispatch_async(dispatch_get_main_queue(), ^{
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
But, in that case, you're actually dispatching the stopAnimating method to the main queue twice. You only really need this:
dispatch_async(dispatch_get_main_queue(), ^{
[indicator stopAnimating];
});
As for your table not updating, that's because you need to dispatch all your reloadData calls to the main queue.
There are quite a few places in your code that need to be dispatched back to the main queue but, instead of wrapping all of those in a dispatch_async to the main queue, there's an easier way. The only place I see where you are actually doing something that should be done on a background thread is this line:
NSData* data = [NSData dataWithContentsOfURL:url];
Which means you can get rid of the dispatch_async(queue, ^{...}); at the beginning of your method and, instead, only do that just before you call [NSData dataWithContentsOfUrl:url]. Then, dispatch_async back to the main queue immediately after.
Like this:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
NSString *searchText=searchBar.text;
NSString *trimmedString = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
if (trimmedString.length==0) {
isFilter=NO;
UIAlertView *noConn = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Please enter something in search bar" delegate:self cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[noConn show];
} else {
NSString *searchNew = [trimmedString stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
isFilter=YES;
#try {
[label removeFromSuperview];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSString* myURLString = [NSString stringWithFormat:#"www.example.com=%#", searchNew];
NSURL *url = [NSURL URLWithString:myURLString];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
if ((unsigned long)data.length > 3) {
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(ys_avatars) {
for (int j=0;j<ys_avatars.count;j++) {
if( ys_avatars[j][#"title"]==[NSNull null] ) {
[_Title1 addObject: #""];
} else {
[_Title1 addObject:ys_avatars[j][#"title"]];
}
if( ys_avatars[j][#"author"]==[NSNull null] ) {
[_Author1 addObject: #""];
}
[_Author1 addObject: ys_avatars[j][#"author"]];
if( ys_avatars[j][#"featured_img"]==[NSNull null] ) {
[_Images1 addObject: #""];
} else {
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
}
if( ys_avatars[j][#"content"]==[NSNull null] ) {
[_Details1 addObject: #""];
} else {
[_Details1 addObject:ys_avatars[j][#"content"]];
}
if( ys_avatars[j][#"permalink"]==[NSNull null] ) {
[_link1 addObject: #""];
} else {
[_link1 addObject:ys_avatars[j][#"permalink"]];
}
if( ys_avatars[j][#"date"]==[NSNull null] ) {
[_Date1 addObject: #""];
} else {
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
} else {
NSLog(#"error");
}
[self.myTableView reloadData];
} else {
if(IDIOM == IPAD){
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(150, 200, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
} else {
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(90, 100, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
}
}
[indicator stopAnimating];
});
});
}
#catch (NSException *exception) { }
}
[self.mySearchBar resignFirstResponder];
}
Note: You are doing quite a bit in that one method. I'd suggest splitting that up in to multiple methods to make your code more readable and maintainable.
try to use NSURLConnection that would save a lot of headache and make your URL requests more manageable
#interface myTableView : UITableViewController<NSURLConnectionDelegate>{
NSMutableData *_responseData;
}
and then use the delegate methods to parse data received,stop your indicatorview,and reload your tableview
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
_responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[_responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}
and make your URL request wherever you want
// Create the request.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
source
I am trying to create a profile inside my application to show only his twitter profile. So far I do have the time line working but I don't have the number counter for the tweets,followers and following. I'm pretty sure I can use something what my code looks like but just don't know how, any help? Thanks
Code:
STTwitterAPI *twitter = [STTwitterAPI twitterAPIAppOnlyWithConsumerKey:#"ConsumerKey"
consumerSecret:#"consumerSecret"];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *bearerToken) {
[twitter getUserTimelineWithScreenName:#"MikesiOSHelp"
successBlock:^(NSArray *statuses) {
self.twitterFeed = [NSMutableArray arrayWithArray:statuses];
[self->tableView reloadData];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
You should check out their demo application.
Your request for finding the followers of a user is explicitly covered in the CLI demo:
typedef void (^AllFollowersBlock_t)(NSArray *allFollowers);
void getFollowers(STTwitterAPI *twitter,
NSString *screenName,
NSMutableArray *followers,
NSString *cursor,
AllFollowersBlock_t allFollowersBlock) {
if(followers == nil) followers = [NSMutableArray array];
NSMutableDictionary *md = [NSMutableDictionary dictionary];
md[#"screen_name"] = screenName;
if(cursor) md[#"cursor"] = cursor;
md[#"skip_status"] = #"1";
md[#"include_user_entities"] = #"0";
[twitter getResource:#"followers/list.json"
baseURLString:kBaseURLStringAPI_1_1
parameters:md
downloadProgressBlock:^(id json) {
//
} successBlock:^(NSDictionary *rateLimits, id response) {
NSArray *users = nil;
NSString *previousCursor = nil;
NSString *nextCursor = nil;
if([response isKindOfClass:[NSDictionary class]]) {
users = [response valueForKey:#"users"];
previousCursor = [response valueForKey:#"previous_cursor_str"];
nextCursor = [response valueForKey:#"next_cursor_str"];
}
NSLog(#"-- users: %#", #([users count]));
NSLog(#"-- previousCursor: %#", previousCursor);
NSLog(#"-- nextCursor: %#", nextCursor);
[followers addObjectsFromArray:users];
if([nextCursor integerValue] == 0) {
allFollowersBlock(followers);
return;
}
/**/
NSString *remainingString = [rateLimits objectForKey:#"x-rate-limit-remaining"];
NSString *resetString = [rateLimits objectForKey:#"x-rate-limit-reset"];
NSInteger remainingInteger = [remainingString integerValue];
NSInteger resetInteger = [resetString integerValue];
NSTimeInterval timeInterval = 0;
if(remainingInteger == 0) {
NSDate *resetDate = [[NSDate alloc] initWithTimeIntervalSince1970:resetInteger];
timeInterval = [resetDate timeIntervalSinceDate:[NSDate date]] + 5;
}
NSLog(#"-- wait for %# seconds", #(timeInterval));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
getFollowers(twitter, screenName, followers, nextCursor, allFollowersBlock);
});
} errorBlock:^(NSError *error) {
NSLog(#"-- error: %#", error);
}];
}
I want to populate the UITableView with data from a plist file into core data
It's so I easy can update the uitableview in later versions, then I only need to change in the plist life and the core data takes care of the rest. Please tell me if there is a better way...
Anyway this I'm doing here ain't working properly, on the first run it fills the core data BUT the UITableView is empty, then if you close the app totally, also from multi-task-bar thingy and start it up again it now show the uitableview with data
In my app delegate.h I have :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ( ![userDefaults valueForKey:#"version"] )
{
[self value1];
[self value2];
[self value3];
[self value4];
[self value5];
[self value6];
NSLog(#"running code");
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
// Adding version number to NSUserDefaults for first version:
[userDefaults setFloat:[[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] forKey:#"version"];
}
if ([[NSUserDefaults standardUserDefaults] floatForKey:#"version"] == [[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] )
{
/// Same Version so dont run the function
}
else
{
[Hovedmenu MR_truncateAll];
[BarneDaab MR_truncateAll];
[Graviditeten MR_truncateAll];
[MineSygedomme MR_truncateAll];
[Fortalt MR_truncateAll];
[Familien MR_truncateAll];
[self value2];
[self value3];
[self value4];
[self value5];
[self value6];
[self value1];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
NSLog(#"running code agian");
// Update version number to NSUserDefaults for other versions:
[userDefaults setFloat:[[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] floatValue] forKey:#"version"];
}
}
and value1 2 3 4 5 6 are almost all the same but from different plists, here's and example
-(void)value1{
NSManagedObjectModel *mom = [self managedObjectModel];
NSDictionary *attrs = [[[mom entitiesByName] objectForKey:#"Hovedmenu"] attributesByName];
NSArray *keyedValues = [[NSArray alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"hovedMenu" ofType:#"plist"]
];
for( NSDictionary *keyedValueDict in keyedValues ) {
NSManagedObject *mObj = [NSEntityDescription insertNewObjectForEntityForName:#"Hovedmenu" inManagedObjectContext:[self managedObjectContext]];
for (NSString *attribute in attrs) {
id value = [keyedValueDict objectForKey:attribute];
if (value == nil) {
// Don't attempt to set nil, or you'll overwite values in self that aren't present in keyedValues
continue;
}
NSAttributeType attributeType = [[attrs objectForKey:attribute] attributeType];
if ((attributeType == NSStringAttributeType) && ([value isKindOfClass:[NSNumber class]])) {
value = [value stringValue];
} else if (((attributeType == NSInteger16AttributeType) || (attributeType == NSInteger32AttributeType) || (attributeType == NSInteger64AttributeType) || (attributeType == NSBooleanAttributeType)) && ([value isKindOfClass:[NSString class]])) {
value = [NSNumber numberWithInteger:[value integerValue]];
} else if ((attributeType == NSFloatAttributeType) && ([value isKindOfClass:[NSString class]])) {
value = [NSNumber numberWithDouble:[value doubleValue]];
}
[mObj setValue:value forKey:attribute];
NSLog(#"Value %# for Key %#", value, attribute);
}
}
NSError *error;
[[self managedObjectContext] save:&error];
}
in my viewcontroller.h
-(void)viewWillAppear:(BOOL)animated{
[self.mainTableView reloadData];
[super viewWillAppear:animated];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
_fetchedResultsController = [Hovedmenu fetchAllGroupedBy:nil withPredicate:nil sortedBy:#"numberRow" ascending:YES delegate:self];
return _fetchedResultsController;
}
I'm using MagicalRecord as well
most likey, from what I can see from your code here is that the contexts which you are using to fetch the values for value1, value2,etc is not the same as the context MagicalRecord creates for you. If you change that context to use the MR_defaultContext, that might update everything properly.
I have this code:
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
and it is repeated three times
#pragma mark MyURLConnection delegate methods
- (void)connection:(MyURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Response received...");
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
- (void)connection:(MyURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"Receiving data...");
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] appendData:data];
}
- (void)connectionDidFinishLoading:(MyURLConnection *)connection {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSLog(#"Request Succeeded! Received %d bytes of data",[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] length]);
//do something with data
NSString *response = [[NSString alloc] initWithData:[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] encoding:NSASCIIStringEncoding];
NSLog(#"HTTP Response: %#",response);
if(connection.tag == APNRegisterURLConnection) {
if([response isEqualToString:kPushNotificationRegistrationSuccess])
[self.userNotifications setObject:[NSNumber numberWithBool:TRUE] forKey:kRegistered];
else if ([response isEqualToString:kPushNotificationReRegistrationSuccess]){
[self.userNotifications setObject:[NSNumber numberWithBool:TRUE] forKey:kRegistered];
NSUUID *udid = [[UIDevice currentDevice] identifierForVendor];
NSString *httpBody = [NSString stringWithFormat:#"udid=%#",udid];
NSString *url = [kRequestURLAddress stringByAppendingString:#"updatenotifications.php"];
[self postRequestForURL:url withParameters:httpBody andTag:UpdateNotificationsURLConnection andPassingData:nil andOptionalMethod:#selector(displayUIActivityIndicatorView)];
}
else {
[self alertWithTitle:#"Error configuring push notifications" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == AddNotificationURLConnection) {
if([response isEqualToString:kPushNotificationAdditionSuccess]){
[[self.userNotifications valueForKey:kNotifications] addObject:connection.passingData];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
else {
[self alertWithTitle:#"Error adding notification" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == DeleteNotificationURLConnection) {
if([response isEqualToString:kPushNotificationDeletionSuccess]){
[[self.userNotifications valueForKey:kNotifications] removeObjectAtIndex:[connection.passingData row]];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:connection.passingData] withRowAnimation:UITableViewRowAnimationFade];
}
else {
[self alertWithTitle:#"Error deleting notification" andMessage:kUnknownErrorAlertMessage];
}
}
else if(connection.tag == UpdateNotificationsURLConnection) {
if(![response isEqualToString:#"error selecting udid"]){
//load notifications with myurlconnection, since internet is required to add items locally, logical sync is syncing everything to match the database
//sample format for list of notifications
// (int)periodindex (int)timeindex|(int)periodindex2 (int)timeindex2|(int)periodindex3 (int)timeindex3 (sorted by period index
// i.e. --> 0 13|2 6|4 11|4 6|9 4
NSArray *unparsedNotifications = [response componentsSeparatedByString:kNotificationDelimeter];
NSMutableArray *parsedNotifications = [NSMutableArray arrayWithCapacity:[unparsedNotifications count]];
int x;
if(!([[unparsedNotifications objectAtIndex:0] isEqualToString:#""] && [unparsedNotifications count] == 1)) {//no hits in database
NSArray *notificationStringArray;
Notification *parsed;
for (x=0; x<[unparsedNotifications count]; x++) {
notificationStringArray = [[unparsedNotifications objectAtIndex:x] componentsSeparatedByString:kElementDelimeter];
parsed = [Notification withPeriod:[[notificationStringArray objectAtIndex:0] intValue] andTime:[[notificationStringArray objectAtIndex:1] intValue]];
[parsedNotifications addObject:parsed];
}
NSLog(#"number of notifications in database = %d",[parsedNotifications count]);
}
//add missing notifications to array
Notification *value;
for(x=0;x<[parsedNotifications count];x++){
value = [parsedNotifications objectAtIndex:x];
if(![[self.userNotifications valueForKey:kNotifications] containsObject:value]){
[[self.userNotifications valueForKey:kNotifications] addObject:value];
NSLog(#"Adding notification with period:%# and time:%#",[value periodString],[value timeString]);
}
}
//delete objects in local array that are missing from online, reversed in order to remove largest indices and rows so that issue does not arise from looping through an array that has been changed
for(x=[[self.userNotifications valueForKey:kNotifications] count]-1;x>=0;x--){
value = [[self.userNotifications valueForKey:kNotifications] objectAtIndex:x];
if(![parsedNotifications containsObject:value]){
NSLog(#"Deleting notification with period:%# and time:%#",[value periodString],[value timeString]);
[[self.userNotifications valueForKey:kNotifications] removeObjectAtIndex:x];
}
}
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
else
[self alertWithTitle:kDefaultAlertTitle andMessage:kUnknownErrorAlertMessage];
}
[self cleanUpAfterRequest:connection.tag];
[response release];
[connection release];
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
-(void)cleanUpAfterRequest:(int)connectionType{
if(connectionType == AddNotificationURLConnection){
self.tableView.allowsSelection = TRUE;
self.tableView.allowsSelectionDuringEditing = TRUE;
}
else if(connectionType == DeleteNotificationURLConnection){
self.view.userInteractionEnabled = TRUE;
}
else if(connectionType == UpdateNotificationsURLConnection){
[[self.view viewWithTag:5] removeFromSuperview];
}
}
- (void)connection:(MyURLConnection *)connection didFailWithError:(NSError *)error {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSString *failingKey = nil;
//IF_PRE_IOS4(failingKey = NSErrorFailingURLStringKey;);
failingKey = NSURLErrorFailingURLStringErrorKey;
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription], [[error userInfo] objectForKey:failingKey]);
[self cleanUpAfterRequest:connection.tag];
[self alertWithTitle:kDefaultAlertTitle andMessage:kDefaultAlertMessage];
[connection release];
[[self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] setLength:0];
}
Xcode returns the error "Multiple methods named "setLength" found."
Any ideas on what I should do to fix it?
Assign the results of [self.receivedData objectForKey:[NSNumber numberWithInt:connection.tag]] to a variable of the proper type. Then call the setLength: method on that variable.
BTW - use modern syntax:
self.receivedData[#(connection.tag)];
The #(connection.tag) replaces the use of [NSNumber numberWithInt:connection.tag] and self.receivedData[xxx] replaces the use of objectForKey:.