fill multiple nsmutabledictionary with data from API - ios

i saved results from API to nsmutabledictionary. In this API is paging after 15 results (1,2,3, etc).
I need to fill resultDictionary with results from API.
My code:
self.resultDictionary = [[NSDictionary alloc] init];
self.resultDictionary = [self.api sendDataViaPostAndFormDataWithTwoParameters:#"email" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"email"] parameterTwo:#"heslo" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"heslo"] onUrl:[NSString stringWithFormat:#"http://***", [[NSUserDefaults standardUserDefaults] valueForKey:#"id"], [[NSUserDefaults standardUserDefaults] valueForKey:#"token"], page] withMethod:#"POST" success:^(BOOL success) {
} failure:^(NSString *fail) {
NSLog(#"%#", fail);
}];
It works fine - it shows 15 results. But, when i scroll down in tableview and after 15 index load next page in api, it shows next 15 results. I need to join both (30results / old and new).
I tried add entries... but no effect.
Could you help me please?
edit:
my rest of code with edit from Ashish
#implementation testingTableViewController {
NSMutableDictionary * resultDictionary;
}
-(void)reloadData:(int)page {
// set selected NO
if ([[NSUserDefaults standardUserDefaults] valueForKey:#"id"] == NULL) {
loginViewController *login = [[loginViewController alloc] init];
login.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:login animated:NO];
} else {
SHOW_NAVIGATION_BAR
self.api = [[API alloc] init];
self.temp = [self.api sendDataViaPostAndFormDataWithTwoParameters:#"email" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"email"] parameterTwo:#"heslo" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"heslo"] onUrl:[NSString stringWithFormat:#"http://*****/=&page=%d", [[NSUserDefaults standardUserDefaults] valueForKey:#"id"], [[NSUserDefaults standardUserDefaults] valueForKey:#"token"], page] withMethod:#"POST" success:^(BOOL success) {
NSLog(#"OK načteno");
} failure:^(NSString *fail) {
NSLog(#"%#", fail);
}];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
resultDictionary = [NSMutableDictionary dictionary];
self.temp = [[NSDictionary alloc] init];
[self reloadData:1];
[self.tableView reloadData];
[self.tableView setNeedsLayout];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[TableViewCell class] forCellReuseIdentifier:#"cell"];
self.chatButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.commentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIButton *commentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
commentButton.frame = CGRectMake(15, 0, 20, 20);
[commentButton setImage:[UIImage imageNamed:#"chat"] forState:UIControlStateNormal];
[commentButton addTarget:self action:#selector(page1) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:commentButton];
UIButton *chatButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
chatButton.frame = CGRectMake(65, 0, 20, 20);
[chatButton setImage:[UIImage imageNamed:#"like"] forState:UIControlStateNormal];
[chatButton addTarget:self action:#selector(page2) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:chatButton];
}
-(void)page1 {
[self reloadData:1];
[resultDictionary addEntriesFromDictionary:self.temp];
[self.tableView reloadData];
}
-(void)page2 {
[self reloadData:2];
[resultDictionary addEntriesFromDictionary:self.temp];
[self.tableView reloadData];
}
When click at first button, result is 15, if i again click on first button, result is still 15 instead 30
Thank you for any response

As per your code
self.resultDictionary = [[NSDictionary alloc] init];
self.resultDictionary = [self.api sendDataViaPostAndFormDataWithTwoParameters:#"email" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"email"] parameterTwo:#"heslo" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"heslo"] onUrl:[NSString stringWithFormat:#"http://***", [[NSUserDefaults standardUserDefaults] valueForKey:#"id"], [[NSUserDefaults standardUserDefaults] valueForKey:#"token"], page] withMethod:#"POST" success:^(BOOL success) {
} failure:^(NSString *fail) {
NSLog(#"%#", fail);
}];
You are not using NSMutableDictionary. Create instance of NSMutableDictionary at top of the class.
NSMutableDictionary * resultDictionary;
Initialize it in viewDidLoad method
self.resultDictionary = [NSMutableDictionary dictionary];
Finally in your code for fetching result form server.
NSDictionary *tempDict = [self.api sendDataViaPostAndFormDataWithTwoParameters:#"email" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"email"] parameterTwo:#"heslo" with:[[NSUserDefaults standardUserDefaults] valueForKey:#"heslo"] onUrl:[NSString stringWithFormat:#"http://***", [[NSUserDefaults standardUserDefaults] valueForKey:#"id"], [[NSUserDefaults standardUserDefaults] valueForKey:#"token"], page] withMethod:#"POST" success:^(BOOL success) {
[self.resultDictionary addEntriesFromDictionary:tempDict];
} failure:^(NSString *fail) {
NSLog(#"%#", fail);
}];

Related

Right to left language change localization on run time. Unable to toggle the UI have to restart app again

The problem is that we want to toggle the language at run time.
We have an application supporting English and arabic.
What I am doing is changing the "AppleLanguages" and then reseting the root view controller.
I have used following code :
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* languages = [userDefaults objectForKey:#"AppleLanguages"];
NSString *language = nil;
if([[languages objectAtIndex:0] isEqual:#"en"]) {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"ar", #"en",nil] forKey:#"AppleLanguages"];
language = #"ar";
} else {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en",#"ar", nil] forKey:#"AppleLanguages"];
language = #"en";
}
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[appDelegate.window setRootViewController:initViewController];
appDelegate.window.rootViewController = [storyBoard instantiateViewControllerWithIdentifier:#"Home"];
appDelegate.window.backgroundColor = [UIColor whiteColor ];
[appDelegate.window makeKeyAndVisible];
The native localization changes but have to restart the app to see the effect on UI.
Thanks in Advance.
The problem was that the language change was not reflecting on bundle.
So I was unable to change the UI as well as localized text.
We can use following code to change the bundle settings.
The following code will toggle the language at run time.
Need to subclass the NSBundle class as shown bellow:-
#implementation BundleEx
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle *bundle = objc_getAssociatedObject(self, &kBundleKey);
if (bundle) {
return [bundle localizedStringForKey:key value:value table:tableName];
}
else {
return [super localizedStringForKey:key value:value table:tableName];
}
}
#end
#implementation NSBundle (Language)
+ (void)setLanguage:(NSString *)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object_setClass([NSBundle mainBundle], [BundleEx class]);
});
BOOL appleTextDirection = NO;
BOOL rightToLeftWritingDirection = NO;
if ([language isEqual:#"ar"]) {
rightToLeftWritingDirection =YES;
appleTextDirection = NO;
if ([[[UIView alloc] init] respondsToSelector:#selector(setSemanticContentAttribute:)]) {
[[UIView appearance] setSemanticContentAttribute:
UISemanticContentAttributeForceRightToLeft];
}
}else {
rightToLeftWritingDirection =NO;
appleTextDirection = YES;
if ([[[UIView alloc] init] respondsToSelector:#selector(setSemanticContentAttribute:)]) {
[[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
}
}
[[NSUserDefaults standardUserDefaults] setBool:appleTextDirection forKey:#"AppleTextDirection"];
[[NSUserDefaults standardUserDefaults] setBool:rightToLeftWritingDirection forKey:#"NSForceRightToLeftWritingDirection"];
[[NSUserDefaults standardUserDefaults] synchronize];
id value = language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:#"lproj"]] : nil;
objc_setAssociatedObject([NSBundle mainBundle], &kBundleKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
And the code used to toggle:-
-(void)toggleTheLanguageWith:(NSString *)identifier{
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* languages = [userDefaults objectForKey:#"AppleLanguages"];
NSString *language = nil;
if ([[languages objectAtIndex:0] rangeOfString:#"en"].location != NSNotFound) {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"ar",#"en",nil] forKey:#"AppleLanguages"];
language = #"ar";
}else if ([[languages objectAtIndex:0] rangeOfString:#"ar"].location != NSNotFound) {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en",#"ar", nil] forKey:#"AppleLanguages"];
language = #"en";
}
[[NSUserDefaults standardUserDefaults]synchronize];
[NSBundle setLanguage:language];
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.window.rootViewController = [mystoryboard instantiateViewControllerWithIdentifier:identifier];
[self.window makeKeyAndVisible];
[UIView transitionWithView:self.window duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
} completion:^(BOOL finished) {
}];
}

Saving action sheet Values/User Defaults

So in my app I'm using a Action sheet which displays which animations to use. Everything is implemented, however, I'm having trouble using user defaults to save the selected row and then pass that along to the rest of my code. I've used user defaults before on UISwitch, but this is different I suppose.
The portion I'm using is a UITableView. in the didselectrow:
//Animation Picker
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSString *actionSheetTitle = #"Choose your style.";
BlockActionSheet *sheet = [BlockActionSheet sheetWithTitle:actionSheetTitle];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[sheet addButtonWithTitle:#"Zoom Out" block:^{
[cell.textLabel setText:[NSString stringWithFormat:#"Animation Style: Zoom Out"]];
//User Defaults
[prefs setObject:#"Zoom Out" forKey:#"Zoom"];
cellTitle = #"Zoom Out";
}];
[sheet addButtonWithTitle:#"Drop In" block:^{
[cell.textLabel setText:[NSString stringWithFormat:#"Animation Style: Drop In"]];
//User Defaults
[prefs setObject:#"Drop In" forKey:#"Drop"];
cellTitle = #"Drop In";
}];
[sheet setDestructiveButtonWithTitle:#"Cancel" block:nil];
[sheet showInView:self.view];
[prefs synchronize];
[tableView reloadData];
Which should send the info to use the proper animationController:
-(void)infoButtonAction:(id)sender {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults synchronize];
if ([userDefaults stringForKey:#"Zoom"]) {
AppInfoViewController * info = [[AppInfoViewController alloc] init];
UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:info];
self.animationController = [[ZoomAnimationController alloc] init];
vc.transitioningDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
[info release];
}
else if ([userDefaults stringForKey:#"Drop"]) {
AppInfoViewController * info = [[AppInfoViewController alloc] init];
UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:info];
self.animationController = [[DropAnimationController alloc] init];
vc.transitioningDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
[info release];
}
NSLog(#"App Info");
}
Also should update the cell displaying which animationController was selected:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs synchronize];
[cell.textLabel setText:[NSString stringWithFormat:#"Animation Style:"]];
if ([prefs stringForKey:#"Zoom"]){
[cell.textLabel setText:[NSString stringWithFormat:#"Animation Style: Zoom Out"]];
}
else if ([prefs stringForKey:#"Drop"]) {
[cell.textLabel setText:[NSString stringWithFormat:#"Animation Style: Drop In"]];
}
UIView *animation = [[UIView alloc] initWithFrame:cell.frame];
animation.backgroundColor = [UIColor colorWithRed:0.176 green:0.176 blue:0.176 alpha:1];
cell.backgroundView = animation;
However, nothing is getting saved. What am I missing?
Thank you for any help.
UPDATE: 1/3
I managed to get everything working with the updated code above. The only thing now is it won't save the style I choose. If I choose Drop In, and re open the table, it reverts back to Zoom Out. How can I fix this?
Take one String object that
NSString *OneString = [NSString stringWithFormat: selectedValue];
and Use that OneString in if condition and rest of the code.

How to display UIActivityIndicatorView while fetching JSON data asynchronously to be populated in UITableView?

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

How can i implement UIActivityIndicatorView during performing search functionality?

I’m building an article reading app.I’m fetching the data from server in JSON format and load into UITableViewController.In search part when user
enter something for a search it will take time to load data into a UITableView.I’m unable to implement UIActivityIndicatorView in between the time search result takes to load
data in UITableViewController.
Here is my Code:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSString *searchText=searchBar.text;
[self.mySearchBar resignFirstResponder];
NSString *trimmedString = [searchText stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
if (trimmedString.length==0) {
isFilter=NO;
UIAlertView *noConn = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Please enter your 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&search=%#", 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++)
{
[_Title1 addObject:ys_avatars[j][#"title"]];
[_Author1 addObject: ys_avatars[j][#"author"]];
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
[_Details1 addObject:ys_avatars[j][#"content"]];
[_link1 addObject:ys_avatars[j][#"permalink"]];
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j] [#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
else
{
NSLog(#"error");
}
[self.myTableView reloadData];
}
}
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) {
}
}
}
you can do this right after the searchBarSearchButton is clicked.
then you add this line inside the cellForRowAtIndexPath:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[_activityIndicator startAnimating];
your code
}
next:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexpath.row == [your_array_of_content count]-1)
{
[_activityIndicator stopAnimating];
}
}
dataWithContentsOfURL is a synchronous API. One way to achieve what you want is to use NSURLConnection APIs to load the date from an URL asynchronously. You should also be hooking into the below listed delegate methods to start and stop the activity indicator.
connection:didReceiveResponse:
connectionDidFinishLoading:
I would also like to suggest you to use libraries like AFNetworking which will give you the before and after hooks as callback blocks, which will be little cleaner on the coding front.
Create the indicator:
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:
UIActivityIndicatorViewStyleWhiteLarge];
[activityIndicator setCenter:CGPointMake(view.frame.size.width/2.0, view.frame.size.height/2.0)];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.color = [UIColor blackColor];
//add it to the view
[self.view addSubview:activityIndicator];
//start the animation
[activityIndicator startAnimating];
and when you want to dismiss it:
[activityIndicator stopAnimating];

saving user defaults [iOS]

I saw a couple of examples but I cannot figure out what's going wrong when trying to save my text field input and reload it when restarting the app.
I have something like this in my .m file (.h file only has a <UITextViewDelegate>);
#implementation C4WorkSpace{
UITextView *textField;
C4Button *okButton;
C4Label *savedText;
}
-(void)setup {
//add text field
CGRect textViewFrame = CGRectMake(20.0f, 20, self.canvas.width-40, 124.0f);
textField = [[UITextView alloc] initWithFrame:textViewFrame];
textField.returnKeyType = UIReturnKeyDone;
[textField becomeFirstResponder];
textField.delegate = self;
//textField.hidden=true;
[self.view addSubview:textField];
okButton=[C4Button buttonWithType:ROUNDEDRECT];
[okButton setTitle:#"Save" forState:NORMAL];
okButton.center=self.canvas.center;
[self.canvas addUIElement:okButton];
[okButton runMethod:#"saveDefault" target:self forEvent:TOUCHUPINSIDE];
savedText=[C4Label labelWithText:#"default"];
savedText.center=CGPointMake(self.canvas.center.x, self.canvas.center.y+40);
[self.canvas addLabel:savedText];
}
-(void)saveDefault{
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:textField.text forKey:#"userName"];
[defaults synchronize];
C4Log(#"defaults: %#",defaults);
C4Log(#"defaults: %#", [defaults objectForKey:#"userName"]);
savedText.text=textField.text;
}
-(void)viewDidLoad{
NSMutableString *text=[[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
C4Log(#"loadedText:%s", text);
textField.text=text;
savedText.text=text;
}
#end
I'm not sure what exactly is going wrong, but when I restart the app the loadedText is always: "¯8*:å". Doesn't matter what I saved.
I found the easiest solution is to set in
ViewDidLoad
text=[[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
and in setup
if (text!=nil) {
textField.text=text;
}
Where does Setup method is call ? I think in viewDidLoad you initialize, but setup method called earlier.
You don't save this info,so button don't recognizer or load info and set text before initialization.
in setup method load info
UItextView *k = [UItextView alloc] init];
k.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
and take a look what will be.
UPDATE:
That's wrong;
[c4workspace loadInfoFromDefaults];
[c4workspace alloc]init]; (calls viedidload method with load info)
You need
[c4workspace alloc]init];
[c4workspace loadInfoFromDefaults];
Please post code where you create c4WorkSpace object.
UPDATE 2:
-(void)setup {
//add text field
CGRect textViewFrame = CGRectMake(20.0f, 20, self.canvas.width-40, 124.0f);
textField = [[UITextView alloc] initWithFrame:textViewFrame];
textField.returnKeyType = UIReturnKeyDone;
[textField becomeFirstResponder];
textField.delegate = self;
//textField.hidden=true;
[self.view addSubview:textField];
okButton=[C4Button buttonWithType:ROUNDEDRECT];
[okButton setTitle:#"Save" forState:NORMAL];
okButton.center=self.canvas.center;
[self.canvas addUIElement:okButton];
[okButton runMethod:#"saveDefault" target:self forEvent:TOUCHUPINSIDE];
savedText=[C4Label labelWithText:#"default"];
savedText.center=CGPointMake(self.canvas.center.x, self.canvas.center.y+40);
[self.canvas addLabel:savedText];
}
- (void) setTextView
{
textField.text=[[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
savedText.text=[[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
}
So you call this like:
C4WorkSpace *c4 = [C4WorkSpace alloc] init];
[c4 setup]
[c4 setTextView];

Resources