How to format an XLForm row value - ios

I'm using XLForm in my project and want to display the value of one of the rows in a specific format.
The row is "Annual turnover" and I want to display the value entered by the user as a currency - for example, if the user enters 1000000 into the form field, the field should be updated to display this: $ 1,000,000.00
How do I do that?
This is how the form field is initialised in initializeForm():
-(void)initializeForm
{
// Other fields in the form...
// Annual turnover Section
self.section = [XLFormSectionDescriptor formSectionWithTitle:formLabel8AnnualTurnover];
//section.footerTitle = #"Describe new products";
[self.formDescriptor addFormSection:self.section];
// Annual turnover
self.row = [XLFormRowDescriptor formRowDescriptorWithTag:formField8AnnualTurnover rowType:XLFormRowDescriptorTypeText title:nil];
self.row.required = NO;
rowDescriptor8AnnualTurnover = self.row;
[self.section addFormRow:self.row];
// Other fields in the form...
self.form = self.formDescriptor;
}
According to the documentation, I should catch that the user has interacted with the field and then change the value of the field and update the row.
This is how I catch that the user has entered something into the field:
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)rowDescriptor oldValue:(id)oldValue newValue:(id)newValue
{
[super formRowDescriptorValueHasChanged:rowDescriptor oldValue:oldValue newValue:newValue];
// Get the current form values
formValues = [self.form formValues];
int i = 0;
if ([rowDescriptor.tag hasPrefix:formField8AnnualTurnover]){
NSString *annualTurnoverValue = [(XLFormOptionsObject*)formValues[formField8AnnualTurnover] displayText];
rowDescriptor8AnnualTurnover.value = [NSString stringWithFormat:#"R %#", annualTurnoverValue]; //This breaks.
[self reloadFormRow:rowDescriptor8AnnualTurnover];
}
}

An endless loop was being created by resetting the value of the rowDescriptor in formRowDescriptorValueHasChanged.
I resolved this issue by changing formRowDescriptorValueHasChanged to first check whether or not the rowDescriptor's value already starts with the currency symbol, and only add it if it's missing:
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)rowDescriptor oldValue:(id)oldValue newValue:(id)newValue
{
[super formRowDescriptorValueHasChanged:rowDescriptor oldValue:oldValue newValue:newValue];
// Get the current form values
formValues = [self.form formValues];
if ([rowDescriptor.tag hasPrefix:formField8AnnualTurnover]){
NSString *annualTurnoverValue = [(XLFormOptionsObject*)formValues[formField8AnnualTurnover] displayText];
if([annualTurnoverValue hasPrefix:#"R "]){
// Do nothing - the value will simply be increased.
}else{
rowDescriptor8AnnualTurnover.value = [NSString stringWithFormat:#"R %#", annualTurnoverValue];
[self reloadFormRow:rowDescriptor8AnnualTurnover];
}
}
}

Related

How to get Fields Name of particular Layer with LayerID with ESRI

i actually tried ways , even checked ESRI sample code QueryTaskExample. i need simply to get Fields Names or Attributes of any Layer .
i used following method...
self.queryTask = [AGSQueryTask queryTaskWithURL:[NSURL URLWithString:strMAPURL]]; // here i send like #"http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/3"
self.queryTask.delegate = self;
//return all fields in query
self.query = [AGSQuery query];
self.query.outFields = [NSArray arrayWithObjects:#"*", nil];
self.query.text = #"Fields";
[self.queryTask executeWithQuery:self.query];
i access below delegates :
//results are returned
- (void)queryTask:(AGSQueryTask *)queryTask operation:(NSOperation *)op didExecuteWithFeatureSetResult:(AGSFeatureSet *)featureSet {
//get feature, and load in to table
self.featureSet = featureSet;
[super.tableView reloadData];
}
featureSet.fields // this should be giving me Name of Fields for Layer 3....
but i am getting Array as 0 elements...... i need to get Fields in same order as there in Server Layer.

Xcode label text from date picked

I have a calendar view that displays the days of the month, and I would like to put the output into my label but am unable to. I can NSLog it but not transfer it into a label. Here is my code:
- (void)calendarView:(DSLCalendarView *)calendarView didSelectRange:(DSLCalendarRange *)range {
if (range != nil) {
NSLog( #"%ld/%ld", (long)range.startDay.month, (long)range.endDay.day);
NSString *datechosen = ( #"%ld/%ld", range.startDay.month,range.endDay.day);
DatePicked.text = datechosen;
}
Any help would be appreciated.
try something like this
if(DatePicked)
{
DatePicked.text = datechosen;
}
else
{
NSLog(#"hey look, DatePicked is not connected to an IBOutlet");
}
DatePicked.text = [NSString stringWithFormat:"%ld/%ld",(long)range.startDay.mont, (long)range.endDay.day];
Pleaes read Formatting String Objects.

Extra call to setMarkedText:selectedRange in iOS7?

In my app I have UITextInput implemented so I can handle multi stage key input (Japanese, Chinese keyboards) for my custom text view. I'm noticing in iOS7, when you have some text that is marked, and you tap one of the suggestions above the keyboard to replace it, that setMarkedText:selectedRange is called twice: once where it replaces the marked text with the string selected from the panel above the keyboard (as you'd expect), and once where an empty string is sent as the parameter. In iOS6, it's only called once.
My questions are, is there a reason it's doing this? And how should I adjust my setMarkedText:selectedRange to account for this (listed below):
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
{
NSRange selectedNSRange = self.textView.selectedTextRange;
NSRange markedTextRange = self.textView.markedTextRange;
if (markedTextRange.location != NSNotFound)
{
if (!markedText)
markedText = #"";
[self.text replaceCharactersInRange:markedTextRange withString:markedText];
markedTextRange.length = markedText.length;
}
else if (selectedNSRange.length > 0)
{
[self.text replaceCharactersInRange:selectedNSRange withString:markedText];
markedTextRange.location = selectedNSRange.location;
markedTextRange.length = markedText.length;
}
else
{
[self.text insertString:markedText atIndex:selectedNSRange.location];
markedTextRange.location = selectedNSRange.location;
markedTextRange.length = markedText.length;
}
selectedNSRange = NSMakeRange(selectedRange.location + markedTextRange.location, selectedRange.length);
self.textView.contentText = self.text;
self.textView.markedTextRange = markedTextRange;
self.textView.selectedTextRange = selectedNSRange;
}
My first instinct is to put an if statement around the contents saying
if markedText != #""
but I'm not sure if I'd be messing up some other cases. Does anyone have any suggestions on how to account for this change??
The guy from DTS recommended this solution:
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
{
...
if (markedText == nil || markedText.length == 0 )
{
[self unmarkText];
}
}
And it seems to work fine.

Get an array of 3 ordered values whilst favouring a specified value

Sorry for the somewhat generic title, if anyone has a better suggestion please let me know.
Basically I am writing a custom leaderboard view whereby I want to show 3 scores only. If possible it will show the current user's score in the middle but, if the user is at the top or the bottom of the list, it should still show 3 scores but itll show another users above or below the list.
e.g.
Me (If I am top, then show 2 below)
User 1
User 2
or
User 1
Me (usual case where I am in the middle of two scores)
User 2
or
User 1
User 2
Me (If I am bottom show two scores above me)
I have a function written that does the first part of this but doesnt take into account edge cases which is what I am struggling with. Can anyone please advise?
-(void)getNearbyScores:(int)score{
GCLeaderboardScore *closestScoreAbove = nil; //Custom container for GC properties
GCLeaderboardScore *closestScoreBelow = nil; //Contains playerID, score, alias etc
if ([playerScores count] == 0){ //playerScores is an NSMutableDictionary
return;
}
for (NSString* key in playerScores) {
GCLeaderboardScore *playerScore = (GCLeaderboardScore *)[playerScores objectForKey:key];
if ((closestScoreAbove == nil || closestScoreAbove->score > playerScore->score) && playerScore->score > score){
closestScoreAbove = playerScore;
}
else if ((closestScoreBelow == nil || closestScoreAbove->score < playerScore->score) && playerScore->score < score){
closestScoreBelow = playerScore;
}
}
me->score = score;
me->rank = 1;
if (closestScoreAbove != nil) {
me->rank = closestScoreAbove->rank + 1;
nearbyScores = [NSMutableArray arrayWithObjects: closestScoreAbove, me, closestScoreBelow, nil];
}
else {
nearbyScores = [NSMutableArray arrayWithObjects: me, closestScoreBelow, nil];
}
}
Assuming there is a me GCLeaderboardScore object, the method below should return an array with the desired GCLeaderboardScore objects (untested):
-(NSArray *)getNearbyScores {
if(playerScores.count==0) return nil;
// Create an array sorted by score
NSArray *sortedByScore=[playerScores sortedArrayUsingComparator: ^(id object1, id object2) {
GCLeaderboardScore *score1=object1;
GCLeaderboardScore *score2=object2;
if(score1->score < score2->score) return NSOrderedAscending;
if(score1->score > score2->score) return NSOrderedDescending;
return NSOrderedSame;
}];
// Find index of me
NSUInteger idx=[sortedByScore indexOfObject:me];
// If me not found, return nil
if(idx==NSNotFound) return nil;
// Ideally we want to show the player before and behind
idx=MAX(0,(NSInteger)idx-1);
// maxIdx will be idx+2 or index of last object if lower
NSUInteger maxIdx=MIN(sortedByScore.count-1,idx+2);
// In case we are last, show two previous results (if array large enough)
if (maxIdx > 3)
idx=MAX(0,maxIdx-3);
// And return the objects, may be 1..3 objects
return [sortedByScore subarrayWithRange:NSMakeRange(idx,maxIdx-idx+1)];
}
I assume you have an array of scores. (Actual implementation can be adapted to your code)
Initialize:
firstScoreAbove = VERY_LARGE_SCORE; secondScoreAbove = VERY_LARGE_SCORE + 1;
firstScoreBelow = -1; secondScoreBelow = -2;
Scan the array elements.
if ( newScore > myScore ) {
if ( newScore < firstScoreAbove ) {
secondScoreAbove = firstScoreAbove;
firstScoreAbove = newScore;
} else if ( newScore < secondScoreAbove ) {
secondScoreAbove = newScore;
}
} else {
// similarly for below.
}
After scanning,
If firstScoreAbove has not changed, then myScore is top and output the two below scores.
If firstScoreBelow has not changed, then myScore is lowest and output the two above scores.
Else Output firstScoreAbove, myScore, firstScoreBelow.

Using PIM, how to detect what is the attribute which is retrieved using Contact.TEL and index?

I'm looping over all attributes of the Contact.TEL field to retrieve names and data, so that I can display something like this:
HOME: +2034953213
WORK: +2033923959
MOBILE: +20179083008
I've retrived the values (+2034953213, +2033923959, +20179083008) successfully using PIM api, but I didn't know how to detect what are the attributes corresponding to the values which I retrieved: (HOME, WORK or MOBILE ...etc) ?
How Can I detect that +2034953213 is either the 'HOME' or 'WORK' or 'MOBILE' ?
Same question for the other retrieved values ?
Here's my code:
ContactList contactList = (ContactList)PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
Enumeration contactListItems = contactList.items();
while (contactListItems.hasMoreElements()) {
Contact contact = (Contact)contactListItems.nextElement();
int telephonesCount = contact.countValues(Contact.TEL);
for(int i=0; i< telephonesCount; ++i) {
String number = contact.getString(Contact.TEL, i);
// I want here to know what is the current attribute that i retrieved its value ?
// I mean its value not its index (either HOME, WORK or MOBILE ...etc)
}
}
Here's the answer for those who are interested:
ContactList contactList = (ContactList)PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
Enumeration contactListItems = contactList.items();
while (contactListItems.hasMoreElements()) {
Contact contact = (Contact)contactListItems.nextElement();
int telephonesCount = contact.countValues(Contact.TEL);
for(int i=0; i< telephonesCount; ++i) {
String number = contact.getString(Contact.TEL, i);
int attribute = contact.getAttributes(BlackBerryContact.TEL, i);
if (attribute == Contact.ATTR_MOBILE)
// It's a mobile phone number, do whatever you want here ...
else if (attribute == Contact.ATTR_HOME)
// It's a home phone number, do whatever you want here ...
else if (attribute == Contact.ATTR_WORK)
// It's a work phone number, do whatever you want here ...
// check other types the same way ...
}
}

Resources