iOS nav bar with username - ios

How do we handle showing a http posted username to a navigation bar title? Here is a method which successfully shows a username in a jpeg represented photo taken by people in a UIScrollView*listview;
-(id)initWithIndex:(int)i andData:(NSDictionary*)data {
self = [super init];
if (self !=nil) {
//initialize
self.tag = [[data objectForKey:#"IdPhoto"] intValue];
int row = i/3;
int col = i % 3;
self.frame = CGRectMake(1.5*kPadding+col*(kThumbSide+kPadding), 1.5*kPadding+row*(kThumbSide+kPadding), kThumbSide, kThumbSide);
self.backgroundColor = [UIColor grayColor];
//add the photo caption
UILabel* caption = [[UILabel alloc] initWithFrame:CGRectMake(0, kThumbSide-16, kThumbSide, 16)];
caption.backgroundColor = [UIColor blackColor];
caption.textColor = [UIColor whiteColor];
caption.textAlignment = UITextAlignmentCenter;
caption.font = [UIFont systemFontOfSize:12];
caption.text = [NSString stringWithFormat:#"#%#",[data objectForKey:#"username"]];
[self addSubview: caption];
//add touch event
[self addTarget:delegate action:#selector(didSelectPhoto:) forControlEvents:UIControlEventTouchUpInside];
//load the image
API* api = [API sharedInstance];
int IdPhoto = [[data objectForKey:#"IdPhoto"] intValue];
NSURL* imageURL = [api urlForImageWithId:[NSNumber numberWithInt: IdPhoto] isThumb:YES];
AFImageRequestOperation* imageOperation = [AFImageRequestOperation imageRequestOperationWithRequest: [NSURLRequest requestWithURL:imageURL] success:^(UIImage *image) {
//create an image view, add it to the view
UIImageView* thumbView = [[UIImageView alloc] initWithImage: image];
thumbView.frame = CGRectMake(0,0,90,90);
thumbView.contentMode = UIViewContentModeScaleAspectFit;
[self insertSubview: thumbView belowSubview: caption];
}];
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[queue addOperation:imageOperation];
}
return self;
}

Place the self.navigationItem.title = label in the same method as the -(void)initWithIndex:(int)i andData:(NSDictionary*)data method, after the label receives information.
-(void)initWithIndex:(int)i andData:(NSDictionary*)data {
//remove the "#" from before the %# that you have below
label = [NSString stringWithFormat:#"#%#",[data objectForKey:#"username"]];
self.navigationItem.title = label;
}
Depending on whether it needs to load immediately, you should call the -(void)initWithIndex:(int)i andData:(NSDictionary*)data in viewDidLoad or viewWillAppear methods.
UPDATE
Try using this:
[self.navigationItem setTitle: label];
For some reason this works better. I tried both in a test and this one worked for me over the other.
UPDATE 2
Initialise your label with a value/object.
-(void)viewDidLoad{
label = #"";//initialises the value to be a blank string enabling use
//call your method that assigns the title now.
}
Now when the method -(void)initWithIndex:(int)i andData:(NSDictionary*)data is called, the title should update as label has been initialised and will now update it's value.
UPDATE 3 - AS PER ASKERS REQUEST
At the top of .m file
#interface YourClassName ()
{
NSString * label;
}
#end
#implementation YourClassName
-(void)viewDidLoad{
label = #"";//initialises the value to be a blank string enabling use
}
-(void)initWithIndex:(int)i andData:(NSDictionary*)data {
//remove the "#" from before the %# that you have below
label = [NSString stringWithFormat:#"#%#",[data objectForKey:#"username"]];
//the label now has a new value so use it for title
self.navigationItem.title = label;
//test to see that there is a value available in log
NSLog(#"What is the name: %#", label);
}

Related

custom label not being filled with data completely

I have the following code:
if (product) {
if ([product.title isStringOfInterest]) {
scriptName = [[PPLinearLayoutLabelItem alloc] initWithText:#"" font:[PPFonts bold20] maxWidth:[LayoutValues getMaxWidthClipped]];
[self.topContainerContent addObject:scriptName];
extraName = [[PPLinearLayoutLabelItem alloc] initWithText:#"" font:[PPFonts regular14] maxWidth:[LayoutValues getMaxWidthClipped]];
[scriptName setPaddingTop:20];
[self.topContainerContent addObject:extraName];
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){
[self loadProductDetails];
});
-(void) loadProductDetails{
IHProduct *product = orderDisplayed.product;
id<ProductDownloadServiceProtocol> productDetailsDownloader = [[ProductDownloadService alloc] initWithClient:[[HttpClient alloc] initWith:APIbackend forEndpoint:EndpointProduct]];
[productDetailsDownloader downloadProductWithProductID:product.productID success:^(ProductDownloadResponse *response) {
scriptName.label.text = [NSString stringWithFormat:#"%# (%#)",response.product.title,response.product.pillTypeShort];
extraName.label.text = response.product.sameAs;
NSString *qtyText = [NSString stringWithFormat:#"%# PACKS (%# at $%# per pack)",[orderDisplayed.interval objectForKey:#"quantity_per_interval"], [orderDisplayed.interval objectForKey:#"quantity_per_interval"], response.product.price];
quantity.label.text = qtyText;
} error:^(ProductDownloadResponse *response) {
[self hideHttpLoadingOverlay];
[RMUniversalAlert showAlertInViewController:self
withTitle:alertErrorTitle
message:#"Error downloading mail order product details"
cancelButtonTitle:OKDialogButton
destructiveButtonTitle:nil
otherButtonTitles:nil
tapBlock:nil];
}];
}
The labels extraname and scriptname are getting filled or getting chopped off in the end i.e. incomplete data. How can I fix this? When I statically put large texts in this the data gets filled into those views nicely. Help!
If you wish adjust width of UILabel based on it text content then use below code;
NSDictionary *fontAttributes = #{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:14]};
CGRect rectOfText = [textToMeasure boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:fontAttributes
context:nil];
CGRect tempFrame = self.label.frame;
tempFrame.size.width = rectOfText.size.width;
self.label.frame = tempFrame;
And if you wish to change its font based on uilabel width then use below;
NOTE : This will work only if self.label.numberOfLines = 1.
self.label.adjustsFontSizeToFitWidth = YES;
self.label.minimumFontSize = 0;

How to get text from all text fields created inside for loop in ios

I created Textfields like below
for (DataSourceForController *ds in _dataArray)
{
NSString *name = ds.labelName;
NSString *bits = ds.textLabelPlceholder;
_paramNameLabel = [[UILabel alloc]initWithFrame:CGRectMake(self.frame.size.width*0, (self.frame.size.height*0.15)+i, self.frame.size.width*0.45,self.frame.size.height*0.05)];
_paramNameLabel.text = name;
_paramNameLabel.textColor = [UIColor blueColor];
_paramNameLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_paramNameLabel];
_paramValue = [[UITextField alloc]initWithFrame:CGRectMake(self.frame.size.width*0.45, (self.frame.size.height*0.15)+i, self.frame.size.width*0.55,self.frame.size.height*0.05)];
_paramValue.placeholder = bits;
_paramValue.textAlignment= NSTextAlignmentCenter;
_paramValue.delegate = self;
_paramValue.backgroundColor = [UIColor colorWithRed:35/255.0 green:185/255.0 blue:235/255.0 alpha:1];
[self addSubview:_paramValue];
i=self.frame.size.height*.1+i;
}
How can i get the text from each textfield like _paramVlue.text
You can add UITextField in NSMutableArray. Try below code:
NSMutableArray *textFieldArr = [NSMutableArray alloc]]init;
for (DataSourceForController *ds in _dataArray)
{
NSString *name = ds.labelName;
NSString *bits = ds.textLabelPlceholder;
_paramNameLabel = [[UILabel alloc]initWithFrame:CGRectMake(self.frame.size.width*0, (self.frame.size.height*0.15)+i, self.frame.size.width*0.45,self.frame.size.height*0.05)];
_paramNameLabel.text = name;
_paramNameLabel.textColor = [UIColor blueColor];
_paramNameLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_paramNameLabel];
_paramValue = [[UITextField alloc]initWithFrame:CGRectMake(self.frame.size.width*0.45, (self.frame.size.height*0.15)+i, self.frame.size.width*0.55,self.frame.size.height*0.05)];
_paramValue.placeholder = bits;
_paramValue.textAlignment= NSTextAlignmentCenter;
_paramValue.delegate = self;
_paramValue.backgroundColor = [UIColor colorWithRed:35/255.0 green:185/255.0 blue:235/255.0 alpha:1];
[self addSubview:_paramValue];
[textFieldArr addObject:_paramValue];
i=self.frame.size.height*.1+i;
}
Now suppose yow want to get text of UITextField at index 2 then write below line:
NSString *str = [(UITextField *)[textFieldArr objectAtIndex:2] text];
Hope this will help you.
I found another easy way
for (UITextField *feild in [self subviews])
{
if ([feild isKindOfClass:[UITextField class]])
{
NSLog(#"Text = %# ",feild.text);
}
}

Loading overlay on collection view

I have a loading view that I insert over the top of a view while it is parsing data from the internet using a separate thread, in this case its on top of a UICollectionView.
For some reason that I cannot understand the loading overlay disappears on its own whist the parsing is still taking place, presenting a blank screen for a second or two. It doesn't seem to happen on UITableViews just on UIcollectionviews. Any help would be appreciated.
Activity overlay.m:
#import "ActivityOverlayController.h
#interface ActivityOverlayController ()
#end
#implementation ActivityOverlayController
-(id)initWithFrame:(CGRect)theFrame {
if (self = [super init]) {
frame = theFrame;
self.view.frame = theFrame;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", #"ActivityOverlayController called");
container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 110, 30)];
activityLabel = [[UILabel alloc] init];
activityLabel.text = NSLocalizedString(#"Loading", #"string1");
activityLabel.textColor = [UIColor lightGrayColor];
activityLabel.font = [UIFont boldSystemFontOfSize:17];
[container addSubview:activityLabel];
activityLabel.frame = CGRectMake(0, 3, 70, 25);
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicator.color = [UIColor blackColor];
activityIndicator.hidesWhenStopped = TRUE;
[activityIndicator startAnimating];
activityIndicator.frame = CGRectMake(80, 0, 30, 30);
[container addSubview:activityIndicator];
[self.view addSubview:container];
container.center = CGPointMake(frame.size.width/2, frame.size.height/2);
self.view.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:0.7];
}
-(void)viewWillAppear:(BOOL) animated {
[super viewWillAppear:animated];
}
-(void)viewWillDisappear:(BOOL) animated {
[super viewWillDisappear:animated];
}
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[activityIndicator stopAnimating];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
Parsing part of collectionViewController.m:
-(void)ParseCollectionView{
[self performSelectorOnMainThread:#selector(showActivityView) withObject:nil waitUntilDone:YES];
CollectionViewImages = [[NSMutableArray alloc]init];
NSData *xmlData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:GalleryTitle]];
cvTBXML = [[TBXML alloc]initWithXMLData:xmlData];
// Obtain root element
TBXMLElement * root = cvTBXML.rootXMLElement;
TBXMLElement * channel = [TBXML childElementNamed:#"channel" parentElement:root];
if (root)
{
TBXMLElement * item = [TBXML childElementNamed:#"item" parentElement:channel];
while (item !=nil)
{
//create new instance of news object
NSObject *Imagetoparse = [[GalleryImage alloc] init];
TBXMLElement * link = [TBXML childElementNamed:#"link" parentElement:item];
NSString *linktext= [TBXML textForElement:link];
[Imagetoparse setValue:linktext forKey:#"link"];
TBXMLElement * thumbnail = [TBXML childElementNamed:#"description" parentElement:item];
NSString *Thumbnailtext= [TBXML textForElement:thumbnail];
Thumbnailtext = [Thumbnailtext substringFromIndex:21];
NSInteger *slength = Thumbnailtext.length -4;
Thumbnailtext = [Thumbnailtext substringToIndex:slength];
Thumbnailtext = [Thumbnailtext stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
Thumbnailtext = [Thumbnailtext stringByReplacingOccurrencesOfString:#"thumb" withString:#"main"];
NSLog(#"Thumnail1 : %#", Thumbnailtext);
NSData *Thumbnailimage = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: Thumbnailtext]];
[Imagetoparse setValue:Thumbnailimage forKey:#"thumbnail"];
[CollectionViewImages addObject:Imagetoparse];
item = [TBXML nextSiblingNamed:#"item" searchFromElement:item];
}
}
[self.collectionView reloadData];
NSLog(#"%#", #"Finished Parse Collection View");
[self performSelectorOnMainThread:#selector(hideActivityView) withObject:nil waitUntilDone:NO];
}
-(void)showActivityView {
if (overlayController == nil) {
overlayController = [[ActivityOverlayController alloc] initWithFrame:(self.view.superview.bounds)];
}
[self.view.superview insertSubview:overlayController.view aboveSubview:self.view];
}
-(void)hideActivityView {
[overlayController.view removeFromSuperview];
}

iOS NSFetchedResultsController: Is it possible to use same cache for the same fetch in different View Controllers?

I have two different view controllers displaying almost the same fetch request. One of them displays more info than the other and is also used for editing of the data. The second one is just for display.
Is there a way to speed things up, since both are displaying exactly the same data? I'm looking for something in my code which makes the whole reorder slow after displaying the second view controller for the first time. In other words: Initially the reordering in my main view controller is very fast. Then you just display the second view controller and switch back and then the reordering in the main view controller gets slow. I have reason to assume that it is because they are using the same fetch.
I'm initiating the fetch request in both viewDidLoad methods, as in the following code snippets. The first one is my main view controller, and also the first one displayed when starting the app:
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil cacheName:#"MainCategoryCache"];
}
And this is my second one:
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:#"NetCache"];
}
Here are the view did load and cellForRowAtIndexPath of my main view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupFetchedResultsController];
//Edit/Done button
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Edit", nil) style:UIBarButtonItemStyleBordered target:self action:#selector(editTable:)];
[self.navigationItem setRightBarButtonItem:editButton];
//Budget at bottom
self.sumTitleLabel.text = [NSString stringWithFormat:#"%#%#:",NSLocalizedString(#"Budget", nil),NSLocalizedString(#"PerMonth", nil)];
self.sumLabel.text = [[DatabaseFetches budgetPerMonthForManagedObjectContext:self.managedObjectContext] getLocalizedCurrencyString];
//Layout
self.view.backgroundColor = [UIColor clearColor];
[self styleTableView];
[self styleBudgetTotal];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Data model and cell setup
static NSString *CellIdentifier = #"MainCategoryCell";
MainCategoryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
//Clear background color
cell.backgroundColor = [UIColor clearColor];
//Setup the cell texts
cell.title.text = mainCategory.name;
int numberOfSubcategories = [[mainCategory getNumberOfSpendingCategories] integerValue];
if (numberOfSubcategories == 1) {
cell.subcategories.text = [NSString stringWithFormat:#"%i %#", numberOfSubcategories, NSLocalizedString(#"subcategory", nil)];
} else {
cell.subcategories.text = [NSString stringWithFormat:#"%i %#", numberOfSubcategories, NSLocalizedString(#"subcategories", nil)];
}
cell.costs.text = [[mainCategory getMonthlyCostsOfAllSpendingCategories] getLocalizedCurrencyString];
//Delegation
cell.title.delegate = self;
//Format text
cell.title.font = [Theme tableCellTitleFont];
cell.title.textColor = [Theme tableCellTitleColor];
cell.title.tag = indexPath.row;
cell.subcategories.font = [Theme tableCellSubTitleFont];
cell.subcategories.textColor = [Theme tableCellSubTitleColor];
cell.costs.font = [Theme tableCellValueFont];
cell.costs.textColor = [Theme tableCellValueColor];
//Icon
UIImage *icon;
if(!mainCategory.icon){
icon = [UIImage imageNamed:#"DefaultIcon.png"];
} else {
icon = [UIImage imageNamed:mainCategory.icon];
}
[cell.iconButton setImage:icon forState: UIControlStateNormal];
cell.icon.image = icon;
cell.iconButton.tag = indexPath.row;
//Background image
cell.cellBackground.image = [[UIImage imageNamed:#"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
//Selection
//cell.title.highlightedTextColor = cell.title.textColor;
cell.subcategories.highlightedTextColor = cell.subcategories.textColor;
cell.costs.highlightedTextColor = cell.costs.textColor;
return cell;
}
Complete second view controller:
#interface NetIncomeViewController()
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
#end
#implementation NetIncomeViewController
#synthesize incomeTitleLabel = _incomeTitleLabel;
#synthesize incomeValueTextField = _incomeValueTextField;
#synthesize incomeBackground = _incomeBackground;
#synthesize incomeValueBackground = _incomeValueBackground;
#synthesize netIncomeTitleLabel = _netIncomeTitleLabel;
#synthesize netIncomeValueLabel = _netIncomeValueLabel;
#synthesize netIncomeBackground = _netIncomeBackground;
#synthesize netIncomeValueBackground = _netIncomeValueBackground;
#synthesize managedObjectContext = _managedObjectContext;
#pragma mark Initializer and view setup
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
#pragma mark View lifecycle
- (void)awakeFromNib{
[super awakeFromNib];
//Title (necessary here because otherwise the tab bar would be only localized after first click
//on the respective tab bar and not from beginning
self.title = NSLocalizedString(#"Net Income", nil);
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateNetIncome];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupFetchedResultsController];
//Edit/Done button
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Edit", nil) style:UIBarButtonItemStyleBordered target:self action:#selector(editIncome:)];
[self.navigationItem setRightBarButtonItem:editButton];
//Get or set and get the gross income
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber *grossIncome = [defaults objectForKey:#"income"];
if (!grossIncome) {
[defaults setDouble:0 forKey:#"income"];
[defaults synchronize];
grossIncome = [defaults objectForKey:#"income"];
}
self.incomeValueTextField.enabled = NO;
self.incomeValueTextField.delegate = self;
self.incomeValueTextField.keyboardType = UIKeyboardTypeDecimalPad;
self.incomeValueTextField.text = [grossIncome getLocalizedCurrencyString];
[self styleTableViewAndIncome];
}
- (void)styleTableViewAndIncome
{
self.view.backgroundColor = [UIColor clearColor];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.backgroundColor = [UIColor clearColor];
self.incomeTitleLabel.textColor = [Theme budgetValueTitleColor];
self.incomeTitleLabel.font = [Theme budgetValueTitleFont];
self.incomeValueTextField.textColor = [Theme budgetValueColor];
self.incomeValueTextField.font = [Theme budgetValueTitleFont];
self.netIncomeTitleLabel.textColor = [Theme budgetValueTitleColor];
self.netIncomeTitleLabel.font = [Theme budgetValueTitleFont];
self.netIncomeValueLabel.textColor = [Theme budgetValueColor];
self.netIncomeValueLabel.font = [Theme budgetValueFont];
self.incomeTitleLabel.text = [NSString stringWithFormat:#"%#:",NSLocalizedString(#"Income", nil)];
self.netIncomeTitleLabel.text = [NSString stringWithFormat:#"%#%#:",NSLocalizedString(#"Net", nil),NSLocalizedString(#"PerMonth", nil)];
self.incomeBackground.image = [[UIImage imageNamed:#"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
self.incomeValueBackground.image = [[UIImage imageNamed:#"price-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
self.netIncomeBackground.image = [[UIImage imageNamed:#"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
}
#pragma mark Table view delegate methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CategoryCostCell";
CategoryCostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
// Configure the cell layout
MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configure the cell layout
cell.categoryBackground.image = [[UIImage imageNamed:#"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
if(!mainCategory.icon){
cell.categoryImage.image = [UIImage imageNamed:#"DefaultIcon.png"];
} else {
cell.categoryImage.image = [UIImage imageNamed:mainCategory.icon];
}
cell.categoryName.text = mainCategory.name;
NSNumber *expenditures = [mainCategory getMonthlyCostsOfAllSpendingCategories];
double expendituresDouble =-[expenditures doubleValue];
if (expendituresDouble == 0) {
expenditures = [NSNumber numberWithDouble: 0];
} else {
expenditures = [NSNumber numberWithDouble: expendituresDouble];
}
cell.categoryCosts.text = [expenditures getLocalizedCurrencyString];
//Format the text
cell.categoryName.font = [Theme tableCellSmallTitleFont];
cell.categoryName.textColor = [Theme tableCellSmallTitleColor];
cell.categoryCosts.font = [Theme tableCellSmallValueFont];
cell.categoryCosts.textColor = [Theme tableCellSmallValueColor];
return cell;
}
#pragma mark TextField delegate methods
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(self.editing){
return YES;
} else {
return NO;
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
textField.text = [NSString stringWithFormat:#"%.2f",[NSNumber getUnLocalizedCurrencyDoubleWithString:textField.text]];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
textField.text = [[NSNumber numberWithDouble:[textField.text doubleValue]] getLocalizedCurrencyString];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
//Handle the enter button
[textField resignFirstResponder];
[self endEdit];
//Since this method is called AFTER DidEndEditing, we have to call editTable or in this case since we have put all the endEdit code in a seperate method this method directly in order to format the table back from edit mode to normal.
return YES;
}
#pragma mark Edit/Add/Delete action
- (IBAction) editIncome:(id)sender
{
if(self.editing)
{
[self endEdit];
} else {
[self beginEdit];
}
}
- (void) beginEdit
{
//Change to editing mode
[super setEditing:YES animated:YES];
//Exchange the edit button with done button
[self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(#"Done", nil)];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
self.incomeValueTextField.borderStyle = UITextBorderStyleRoundedRect;
self.incomeValueTextField.enabled = YES;
self.incomeValueBackground.hidden = YES;
self.incomeValueTextField.textColor = [Theme budgetValueTitleColor];
}
- (void) endEdit
{
//Change to editing no
[super setEditing:NO animated:YES];
//Remove Done button and exchange it with edit button
[self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(#"Edit", nil)];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
self.incomeValueTextField.borderStyle = UITextBorderStyleNone;
self.incomeValueTextField.enabled = NO;
self.incomeValueBackground.hidden = NO;
self.incomeValueTextField.textColor = [Theme budgetValueColor];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setDouble:[NSNumber getUnLocalizedCurrencyDoubleWithString:self.incomeValueTextField.text] forKey:#"income"];
[self updateNetIncome];
//[defaults synchronize];
}
#pragma mark Net income
- (void) updateNetIncome {
double grossIncome = [NSNumber getUnLocalizedCurrencyDoubleWithString:self.incomeValueTextField.text];
double budget = [[DatabaseFetches budgetPerMonthForManagedObjectContext:self.managedObjectContext] doubleValue];
double netIncome = grossIncome - budget;
if(netIncome >0){
self.netIncomeValueBackground.image = [[UIImage imageNamed:#"price-bkg_green"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
} else if(netIncome <0) {
self.netIncomeValueBackground.image = [[UIImage imageNamed:#"price-bkg_red"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
} else {
self.netIncomeValueBackground.image = [[UIImage imageNamed:#"price-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
}
self.netIncomeValueLabel.text = [[NSNumber numberWithDouble:netIncome] getLocalizedCurrencyString];
}
#end
It looks like you're doing UIImage creation in your cellForRowAtIndexPath method, which would cause a slowdown.
Better to create the background UIImage as an instance variables and set its image in the viewDidLoad, then reference it in the cellForRowAtIndexPath method. Like so:
//Declare the instance variable
UIImage *backgroundImage
//Set it in viewDidLoad
self.backgroundImage = [[UIImage imageNamed:#"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
//Assign it in cellForRowAtIndexPath
cell.backgroundImage = self.backgroundImage;
As for the icon, which has to be set for each row, you'll want to move the actual image loading off the main thread. You can do this either with dispatch_async() or NSOperationQueue. (pulled from here: Understanding dispatch_async)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
UIImage *icon;
if(!mainCategory.icon){
icon = [UIImage imageNamed:#"DefaultIcon.png"];
} else {
icon = [UIImage imageNamed:mainCategory.icon];
}
dispatch_async(dispatch_get_main_queue(), ^(void){
[cell.iconButton setImage:icon forState: UIControlStateNormal];
cell.icon.image = icon;
cell.iconButton.tag = indexPath.row;
});
});
Notice how the imageNamed method is called in the background thread, but the actual assignment takes place on the main thread. You have to do it this way because you're not allowed to update UI elements anywhere except the main thread.

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