How can i implement UIActivityIndicatorView during performing search functionality? - ios

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];

Related

How to add Multiple custom marker on google maps and how to change custom marker when it taped and untaped

I want to show multiple number of markers on goolemaps which is of different colours say red, green ,orange ,black marker shown in the below image.I have to show the price in the marker when I select some marker then Marker image must change same like the below image
I am getting lat and long of marker from web services and using that data I am add markers,text in the marker using the below code but the Image is becoming blur .
-(void)hourelywebsevice:(NSString *)withlogintoken withlat:(double )weblat withlong:(double )weblong withcoustamerid:(NSString *)coustamerid{
NSLog(#"%#",withlogintoken);
NSLog(#"%f",weblat);
NSString *weblatstring=[NSString stringWithFormat:#"%f",weblat];
NSString *weblongstring=[NSString stringWithFormat:#"%f",weblong];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:weblatstring,#"lat",weblongstring,#"lon",coustamerid,#"customer_id",hourlyWebFromDateStr,#"fromtime",hourlyWebToDateStr,#"totime",withlogintoken,#"login_token",filtervechtypestr,#"vehicle_type",filteraminitesarray,#"amenities",filtertypearray,#"type", nil];
NSLog(#"%#",dict);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", #"text/html", nil];
[manager POST:#"http://park24x7.com/betav2/apipoint/gethourlyserviceproviders" parameters:dict progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"%#", responseObject);
userarray=[responseObject objectForKey:#"data"];
statusstring=[NSString stringWithFormat:#"%#", [responseObject objectForKey:#"status"]];
NSInteger number=1;
NSInteger statustwonumber=2;
integerAsString = [NSString stringWithFormat:#"%ld",(long)number];
useridstring1=[NSString stringWithFormat:#"%#", [userarray valueForKey:#"id"]];
NSString *satustwostring= [NSString stringWithFormat:#"%ld",(long)number];
alertstring =[responseObject objectForKey:#"message"];
if([statusstring isEqualToString:integerAsString])
{
NSLog(#"%#",alertstring);
//
if (!(alertstring.length==0 )) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:alertstring
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[activityIndicatorView stopAnimating];
[alert show];
}else{
vehicle_id=[NSString stringWithFormat:#"%#", [responseObject objectForKey:#"vehicle_id"]];
Carnumber_string=[NSString stringWithFormat:#"%#", [responseObject objectForKey:#"vehicle_number"]];
int i;
for (i=0; i<userarray.count; i++)
{
marker1 = [[GMSMarker alloc] init];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,60,60)];
NSString *space_remaingcountstring=[[userarray objectAtIndex:i ]valueForKey:#"space_remain"];
NSInteger space_remaingcountInt=[space_remaingcountstring integerValue];
UIImageView *pinImageView;
int spacesAvilable,spacesOccupied,spacesRemain;
NSString *spacesAvilableStr,*spacesOccupiedStr,*spacesRemainStr;
spacesAvilableStr=[[userarray objectAtIndex:i ]valueForKey:#"space_available"];
;
spacesOccupiedStr=[[userarray objectAtIndex:i ]valueForKey:#"space_occupied"];
spacesRemainStr=[[userarray objectAtIndex:i ]valueForKey:#"space_remain"];
spacesAvilable=[spacesAvilableStr intValue];
spacesOccupied=[spacesOccupiedStr intValue];
spacesRemain=[spacesRemainStr intValue];
float precentage = 100*spacesOccupied/spacesAvilable;
NSLog(#" precentage %f",precentage);
if (spacesAvilable<=2) {
pinImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"marker-orange-48"]];
}
else
{
if (precentage<=50) {
pinImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"marker-green-48"]];
}else if (precentage>50)
{
pinImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"marker-black-48"]];
}
}
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(12, 7, 30, 20)];
NSString *pricestring=[[userarray objectAtIndex:i ]valueForKey:#"hourly_price"];
label.text=pricestring;
label.textColor=[UIColor colorWithRed:187/255.0 green:0/255.0 blue:29/255.0 alpha:1];
label.font=[UIFont systemFontOfSize:9.0f];
[view addSubview:pinImageView];
[pinImageView addSubview:label];
UIImage *markerIcon = [self imageFromView:view];
marker1.icon = markerIcon;
NSString *resultdictlatstring=[[userarray objectAtIndex:i ]valueForKey:#"loc_lat"];
float resultdictlatfloat=[resultdictlatstring floatValue];
NSLog(#"%f",resultdictlatfloat);
NSString *resultdictlongstring=[[userarray objectAtIndex:i ]valueForKey:#"loc_long"];
float resultdictlongfloat=[resultdictlongstring floatValue];
NSLog(#"%f",resultdictlongfloat);
marker1.position = CLLocationCoordinate2DMake(resultdictlatfloat, resultdictlongfloat);
NSLog(#"%f",marker1.position);
marker1.appearAnimation = kGMSMarkerAnimationPop;
marker1.map = hrlymapView;
marker1.zIndex=i;
NSLog(#"%d",marker1.zIndex);
}
[activityView stopAnimating];
}
}
else if ([statusstring isEqualToString:satustwostring]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:alertstring
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[activityIndicatorView stopAnimating];
[alert show];
[activityView stopAnimating];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:alertstring
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[activityIndicatorView stopAnimating];
[alert show];
[hrlymapView clear];
[activityView stopAnimating];
}
}
failure:^(NSURLSessionTask* operation, NSError* error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Sorry!!"
message:#"The Internet connection appears to be offline"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[activityIndicatorView stopAnimating];
[alert show];
[activityView stopAnimating];
[hrlymapView clear];
NSLog(#"Error: %#", error);
}];
}
- (UIImage *)imageFromView:(UIView *) view
{
UIGraphicsBeginImageContext(view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
// if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
// UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);
// } else {
// UIGraphicsBeginImageContext(view.frame.size);
// }
// [view.layer renderInContext: UIGraphicsGetCurrentContext()];
// UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// UIGraphicsEndImageContext();
// return image;
}
In didtap marker I am add belowcode to get the data from the marker I change the image of marker but I it not working
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)tappedMarker
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
_hourlyparkingSpotDetailsView.hidden=NO;
_hourlyTapOnMarkerLblView.hidden=YES;
_monthlyParkingSpotDetailsView.hidden=NO;
_currentLocationBtn.frame=CGRectMake(_currentLocationBtn.frame.origin.x, _hourlyparkingSpotDetailsView.frame.origin.y-80, _currentLocationBtn.frame.size.width, _currentLocationBtn.frame.size.height);
//marker.map=nil;
NSLog(#"You tapped at %f,%f", tappedMarker.position.latitude,tappedMarker.position.longitude);
destinationlat_fvalue=tappedMarker.position.latitude;
destinationlon_fvalue=tappedMarker.position.longitude;
tappedMarker.icon=[UIImage imageNamed:#"pin-selected"];
NSLog(#"%d",tappedMarker.zIndex);
_hourlyparkingSpotDetailsView.hidden=NO;
_hourlyTapOnMarkerLblView.hidden=YES;
_monthlyParkingSpotDetailsView.hidden=YES;
_hourlyparkingSpotAddressLbl.text=[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"address"];
_hourlyParkingSpotPriceLbl.text=[NSString stringWithFormat:#"%#/h",[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"hourly_price"]];
_markerSpaceIdStr=[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"space_id"];
_hourlyParkingSpotZoneId=[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"zone_id"];
_hourlyParkingSptVehicleType=[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"vehicle_type"];
_hourlyreviews=[NSString stringWithFormat:#"%# Reviews", [[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"reviws"]] ;
_hourlyspacetype=[[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"space_type"];
NSString *currency_symbol=[NSString stringWithFormat:#"%#", [[userarray objectAtIndex:tappedMarker.zIndex ]valueForKey:#"currency_symbol"]];
_hourlyRupeeSymbolLbl.text=currency_symbol;
[defaults setObject:currency_symbol forKey:#"currency_symbol"];
_hourlyAutomatedLbl.text=_hourlyspacetype;
_hourlyReviewsLbl.text=_hourlyreviews;
if(isMarkerActive == TRUE){
[self unhighlightMarker:marker1];
}
isMarkerActive = TRUE;
selectedMarker = tappedMarker;
[self highlightMarker:tappedMarker];
return YES;
}
-(void)highlightMarker:(GMSMarker *)tappedMarker{
if([hrlymapView.selectedMarker isEqual:tappedMarker]){
tappedMarker.icon = [UIImage imageNamed:#"pin-selected"];
}
}
-(void)unhighlightMarker:(GMSMarker* )UntappedMarker{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,70,70)];
UIImageView *pinImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pin-red-2"]];
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(23, 15, 29, 23)];
NSString *pricestring=[[userarray objectAtIndex:UntappedMarker.zIndex ]valueForKey:#"hourly_price"];
label.text=pricestring;
label.textColor=[UIColor colorWithRed:187/255.0 green:0/255.0 blue:29/255.0 alpha:1];
label.font=[UIFont systemFontOfSize:11.0f];
[view addSubview:pinImageView];
[pinImageView addSubview:label];
UIImage *markerIcon = [self imageFromView:view];
UntappedMarker.icon = markerIcon;
}
Thanks for quick answer,If you have any doubts in the code please let me know.
This is how add marker to map:
// set `SOME_NAME` on your logic
UIImage * markerIconImage = [UIImage imageNamed:SOME_NAME];
//lat - CGFloat value
//lng - CGFloat value
CLLocation * location = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
GMSMarker * marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude);
marker.icon = markerIconImage;
marker.map = mapView; // mapView - is your map view
To not duplicate the answers, here is how to manipulate on marker select and deselect actions: [Change Google Maps' Selected Marker or change marker's color? [iOS] - the logic will be same.
While making marker object, you can give an id to each marker. that later can be used for identifying the same. I thing maker has a userInfo dictionary that can be used for this purpose
Example
GMSMarker *marker = [[GMSMarker alloc] init];
marker.userData = #{#"marker_id":[NSNumber numberWithInt:1]};
In delegate methods, you can get the marker id from userData.
NSNumber *number = [marker.userData objectForKey:#"marker_id"];

How to add textfield in scrollview in ios?

I am making an app in which i am selecting photos from gallery and I want that on every picture or video one textfield will appear so that if i want to describe about that pic or video.
here is the code of display the photos but not showing the textfield on above the every pic in scrollview.
-(void)launchController
{
ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc]initImagePicker];
elcPicker.maximumImagesCount = 100;
elcPicker.returnsOriginalImage = YES;
elcPicker.returnsImage = YES;
elcPicker.onOrder = YES;
elcPicker.mediaTypes = #[(NSString *)kUTTypeImage,(NSString *)kUTTypeMovie];
elcPicker.imagePickerDelegate = self;
[self presentViewController:elcPicker animated:YES completion:Nil];
}
-(void)launchSpecialController
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
self.specialLibrary = library;
NSMutableArray *groups = [NSMutableArray array];
[_specialLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group , BOOL *stop){
if(group){
[groups addObject:group];
}else{
[self displayPickerForGroup:[groups objectAtIndex:0]];
}
} failureBlock:^(NSError *error) {
chosenImages = nil;
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Album Error: %# - %#", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
NSLog(#"A problem occured %#", [error description]);
// an error here mean
}];
}
- (void)displayPickerForGroup:(ALAssetsGroup *)group
{
ELCAssetTablePicker *tablePicker = [[ELCAssetTablePicker alloc] initWithStyle:UITableViewStylePlain];
tablePicker.singleSelection = YES;
tablePicker.immediateReturn = YES;
ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initWithRootViewController:tablePicker];
elcPicker.maximumImagesCount = 1;
elcPicker.imagePickerDelegate = self;
elcPicker.returnsOriginalImage = YES; //Only return the fullScreenImage, not the fullResolutionImage
elcPicker.returnsImage = YES; //Return UIimage if YES. If NO, only return asset location information
elcPicker.onOrder = NO; //For single image selection, do not display and return order of selected images
tablePicker.parent = elcPicker;
tablePicker.assetGroup = group;
[tablePicker.assetGroup setAssetsFilter:[ALAssetsFilter allAssets]];
[self presentViewController:elcPicker animated:YES completion:nil];
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return YES;
}else{
return toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
}
}
#pragma mark ELCImageControllerDelegate Methods
-(void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
imageScroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 150, self.view.frame.size.width, 450)];
[self.view addSubview:imageScroll];
UITextField *textfield1 = [[UITextField alloc]initWithFrame:CGRectMake(10, 100, 100, 40)];
textfield1.backgroundColor = [UIColor greenColor];
NSMutableArray *textfieldArray = [NSMutableArray arrayWithCapacity:[info count]];
[textfieldArray addObject:textfield1];
textfield1.text= #"hello";
[imageScroll addSubview:textfield1];
for(UIView *v in [imageScroll subviews]){
[v removeFromSuperview];
}
CGRect workingFrame = imageScroll.frame;
workingFrame.origin.x = 0;
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[info count]];
for (NSDictionary *dict in info) {
if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[imageScroll addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(#"UIImagePickerControllerReferenceURL = %#", dict);
}
} else if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypeVideo){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[imageScroll addSubview:imageview];
;
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(#"UIImagePickerControllerReferenceURL = %#", dict);
}
} else {
NSLog(#"Uknown asset type");
}
}
chosenImages = images;
[imageScroll setPagingEnabled:YES];
[imageScroll setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
}
- (void)elcImagePickerControllerDidCancel:(ELCImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad {
//chosenImages = [[NSArray alloc]init];
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor whiteColor]];
// textfield1 = [[UITextField alloc]initWithFrame:CGRectMake(10, 100, 100, 40)];
// textfield1.backgroundColor = [UIColor greenColor];
// textfieldArray = [NSMutableArray arrayWithCapacity:[info count]];
// [textfieldArray addObject:textfield1];
// textfield1.text= #"hello";
// [imageScroll addSubview:textfield1];
UIButton *uploadimage = [[UIButton alloc]initWithFrame:CGRectMake(10, 30, 55, 55)];
uploadimage.backgroundColor = [UIColor blueColor];
[uploadimage setTitle:#"multiple images" forState:UIControlStateNormal];
[uploadimage addTarget:self action:#selector(launchSpecialController) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:uploadimage];
UIButton *singleimage = [[UIButton alloc]initWithFrame:CGRectMake(90, 30, 55, 55)];
singleimage.backgroundColor = [UIColor blueColor];
[singleimage setTitle:#"uploadimage" forState:UIControlStateNormal];
[singleimage addTarget:self action:#selector(launchController) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:singleimage];
imagePicker = [[UIImagePickerController alloc]init];
I don't understand your code lines. The problem should be there.
Why are you doing below things?
[imageScroll addSubview:textfield1];
for(UIView *v in [imageScroll subviews]){
[v removeFromSuperview];
}
In first line you are adding textfield to your scrollview and then you are using for loop to remove all subviews. It will remove your textfield from scrollview as well. You should not do this if you want to show textfield to user.
Please try by commenting the for loop. Hope it will work for you.
//Edit begins over here.
I think you should use UICollectionView instead of UIScrollView. In each and every cells of collectionview, you can show image and textfileds. It will be easy for you and also it will look better.
Thanks
Use NSMutableArray store UITextField value in it and call it with image array with function on the same button.
NSMutableArray *arr = [NSMutablearray....];
for (UIView *subV in self.view.subviews){
if([subV isKindOfClass:[UITextField class]])
{
//store it in a NSDictionary, so later can still know which
//textField your text belongs,
NSDictionary *tempDic = [NSDictionary dictionaryWithObjectAndKey:subV.txt
,subV.tag,/*or subVw.placeholder*/,nil];
[arr addObject:tempDic];
}
}

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

AMSlideMenu Cell click takes time to open another view?

I’m building an article reading app.I’m using AMSliderMenu(https://github.com/SocialObjects-Software/AMSlideMenu)
library for menu list.When i click on any cell in AMSlideMenu it load into another table view which contain list of articles.
I’m fetching article data in uitableview with JSON.
The issue is when i click on list of menu in AMSlideMenu it takes time to open another view.How can i resolve this problem.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL myBool = [self isNetworkAvailable];
if (myBool)
{
#try {
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
NSData* data = [NSData dataWithContentsOfURL:ysURL];
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"]];
}
}
else
{
NSLog(#"asd");
}
}
#catch (NSException *exception) {
}
[self LoadMore];
[self LoadMore];
});
});
}
}
-(void)LoadMore
{ BOOL myBool = [self isNetworkAvailable];
if (myBool)
{
#try {
// for table cell seperator line color
self.tableView.separatorColor = [UIColor colorWithRed:190/255.0 green:190/255.0 blue:190/255.0 alpha:1.0];
// for displaying the previous screen lable with back button in details view controller
UIBarButtonItem *backbutton1 = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backbutton1];
NSString *urlString=[NSString stringWithFormat:#"www.example.com&page=%d",x]; NSURL *newUrl=[NSURL URLWithString:urlString];
NSData* data = [NSData dataWithContentsOfURL:newUrl];
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
x++;
if(ys_avatars){
for (int j=0;j<_Title1.count ;j++)
{
[_Title1 addObject:ys_avatars[j][#"title"]];
[_Author1 addObject: ys_avatars[j][#"author"]];
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
} }
else
{ NSLog(#"asd"); }
[self.tableView reloadData];}
#catch (NSException *exception) {
}} }
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _Title1.count;
}
Its because you have done many many works in viewDidLoad method that's executing synchronously, and that view controller will not be shown until the code in viewDidLoad will not executed completely.
So, load your data asynchronously or do it in viewDidAppear method, but I strongly suggest you to do it asynchronously.

Add loading view controller before tableview shows

I have a tableView controller that loads my parsed XML data. It takes some time to do.
- (void)viewDidLoad
{
[super viewDidLoad];
CustomStringParser *customStringParser = [[CustomStringParser alloc] init];
// Set MORE logo in navigation bar
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Navigation"]];
// Download and parse XML data
RXMLElement *rxml = [RXMLElement elementFromXMLData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.morecobalt.co.uk/rss/?t=events"]]];
// Create an array to store each feed
eventsFeeds = [[NSMutableArray alloc] init];
// Loop through XML data
[rxml iterate:#"channel" usingBlock:^(RXMLElement *supportElement) {
[supportElement iterate:#"item" usingBlock:^(RXMLElement *repElement) {
// Assign element to string
NSString *title = [repElement child:#"title"].text;
NSString *subtitle = [repElement child:#"tagline"].text;
NSString *description = [repElement child:#"description"].text;
NSString *imageurl = [repElement child:#"image"].text;
NSString *startDate = [repElement child:#"start_date"].text;
NSString *endDate = [repElement child:#"end_date"].text;
// Assign element value to MoreCobalt.h propertys
currentFeed = [MoreCobaltEvents alloc];
currentFeed.title = title;
currentFeed.subtitle = subtitle;
currentFeed.imageurl = imageurl;
// DESCRIPTION FORMATTING
description = [customStringParser parseHTML:description];
description = [customStringParser parseLinesMultiple:description];
description = [customStringParser removeSocialSignifiers:description];
currentFeed.description = description;
// DATE FORMATTING
currentFeed.startDate = [customStringParser formatDate:startDate];
currentFeed.endDate = [customStringParser formatDate:endDate];
// Add a new object to the feeds array
[eventsFeeds addObject:currentFeed];
}];
}];
}
While the data is been parsed I want to add a loading screen with a activity indicator on. Im guessing this is going to be a sub view. How can I do this?
NOTE: Im using storyboards. Image below
Just drag an activity indicator component on your xib.
Declare a property in your .h file. Hook it up.
In your .m file in viewDidLoad call.
[self.activityIndicator starAnimating];
[self.activityIndicator.hidesWhenStopped = YES;
And then after your table loads call:
[self.activityIndicator stopAnimating];
No need for subviews.
Write below code in **AppDelegate.h**
UIActivityIndicatorView *progressIndicator;
UIView *progressIndicatorView;
Write below code in **AppDelegate.m**
-(void) addProgressIndicator:(UIView *)parentView
{
[self.progressIndicatorView removeFromSuperview];
self.progressIndicatorView = [[UIView alloc] initWithFrame:CGRectMake(0,0, parentView.frame.size.width,parentView.frame.size.height)];
self.progressIndicatorView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
self.progressIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake((parentView.frame.size.width - 70) / 2,(parentView.frame.size.height - 70) / 2,70,70)];
[self.progressIndicatorView addSubview:self.progressIndicator];
[parentView addSubview:self.progressIndicatorView];
[parentView bringSubviewToFront:self.progressIndicatorView];
[self.progressIndicatorView bringSubviewToFront:self.progressIndicator];
[self.progressIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.progressIndicator setHidesWhenStopped:YES];
[self.progressIndicator stopAnimating];
[self.progressIndicatorView setHidden:YES];
}
-(void) startProgressIndicator
{
[NSThread detachNewThreadSelector:#selector(showProgressIndicator) toTarget:self withObject:nil];
}
-(void) showProgressIndicator
{
[self.progressIndicatorView setHidden:NO];
[self.progressIndicator startAnimating];
}
-(void) stopProgressIndicator
{
[self.progressIndicator stopAnimating];
[self.progressIndicatorView setHidden:YES];
}
Call this methods where you want to show Progress Indicator,in viewDidLoad/ViewWillAppear .
Good Luck !!

Resources