Get label names for ABPerson properties - cocoa

I want to get all label names for properties of ABPerson object. For example: record ABPerson has three phone numbers defined: Mobile, Other, Work. I use labelAtIndex method to get label name but returned string contains needed value wrapped in characters $!!$. Instead of returning just "Mobile" I get these "_$!<" wrap-characters.
I have following code:
//person object points to ABPerson record from addressBook
ABMultiValue *phoneNumbers = [person valueForProperty:kABPhoneProperty];
NSUInteger count = [phoneNumbers count];
for (int i = 0; i < count; i++) {
NSLog(#"Phone numbers label: %# value: %#", [phoneNumbers labelAtIndex:i], [phoneNumbers valueAtIndex:i]);
}
In log I get following:
2012-01-23 01:14:04.234 FixMyAddressBook[3667:707] Phone numbers label: _$!<Mobile>!$_ value: +327382738273
2012-01-23 01:14:04.370 FixMyAddressBook[3667:707] Phone numbers label: _$!<Work>!$_ value: +3293829328
Could someone point me please how can I get label names for properties without special characters?

As far as I'm aware you need to get the localized label for that item, you'll need to make sure you're using the right reference code.
// Grab the right property first
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneNumberCount = ABMultiValueGetCount(phoneNumbers);
for(int k = 0; k < phoneNumberCount; k++)
{
//Get phone number label by iterating across this
CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, k );
CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
CFStringRef phoneNumberLocalizedLabel = ABAddressBookCopyLocalizedLabel( phoneNumberLabel );
// converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile"
//do whatever you want to do here
//release your references
CFRelease(phoneNumberLocalizedLabel);
CFRelease(phoneNumberValue);
}

Related

Copying rendered value instead of the data value

I use Handsontable and in one column, the data type is an integer that is an index of a vector of strings v. So, instead of showing the integer index i, I have to show v[i]. I do so by declaring a custom renderer in handsontable:
var annotationTableSettings = {
data: componentAnnotation,
columns: [
{renderer: annotationId2StringRenderer},
...
However, when I copy the value of the cell (Ctrl+c in windows/linux or cmd+c in mac), the integer is copied instead of the rendered value. Does anyone know how to copy the rendered value (I would like to keep the integer data type and the custom renderer).
An example can be seen here: http://leoisl.gitlab.io/DBGWAS_support/full_dataset_visualization_0_4_6/components/comp_2.html
Just copy the first cell of the first line of the first table (in the north panel) - the cell with value "(Phe)CML" and you will copy the value 3, instead of "(Phe)CML" itself.
Thanks in advance!
you can use the beforeCopy hook.
var annotationTableSettings = {
data: componentAnnotation,
beforeCopy: data => {
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j++) {
if (!isNaN(data[i][j])) {
data[i][j] = v[data[i][j]]
}
}
}
}
columns: [
{renderer: annotationId2StringRenderer},
...

Should I have used a CoreData predicate to populate my UITableview?

I had an old app that I rebuilt using CoreData and Swift 2. This is my first go at Coredata, so I'm sure I'm not doing everything the most efficient way possible. For example, I have 2 entities in Coredata, a Person entity and a Statement entity. The person entity has a relationship of "to many" to the Statement entity, the Statement entity has a relationship of "To One" to the Person entity. So basically my Person object is able to have multiple Statement objects. This is all working and I am able to add them into CoreData successfully.
Next I have a UIViewController with a UITableView inside of it. I have the tableview's Selection dropdown set to Multiple Sections. I have 2 sections assigned for the table view.
When I grab the CoreData Entities I place them into an array so that I am able to use that array and fill the tableview.
var persons: [Person]!
persons = try coreDataStack.context.executeFetchRequest(fetchRequest) as! [Person]
After that (and I think this is where things could be simplier) I break that array into 2 different arrays so that each Section in the Table view has it's own data source. I think this is where I could use a CoreData NSPredicate, but after looking at some tutorial and reading a couple of chapters of a book I have on Coredata, I still don't really understand how to use them. So instead this is what I'm doing to make 2 different arrays from the array I created from Coredata.
for(var i = 0; persons?.count > i; i++){
newNumber = 0.00
print("\(persons?[i].statements?.count) this is the statements count")
if(persons?[i].statements?.count > 0){
print("YES statements")
//persons[i].statements
for(var x = 0; persons[i].statements?.count > x; x++){
//print( "\(persons[i].statements?[x].name) this is the name " )
let statementNumber = persons[i].statements?[x] as? Statement
//print(statementNumber?.amount)
newNumber = newNumber + Double((statementNumber?.amount)!)
//print(newNumber)
}
// check the new number and see if it's positive or negative
if(newNumber >= 0){
positiveeArray.append(persons[i])
//print("\(positiveArray.count) This is the count of the posve array")
}
else{
negativeArray.append(persons[i])
//print("\(negativeArray.count) This is the count of the negative array")
}
}else{
print("there are no statements add this person to the positive array")
positiveArray.append(persons[i])
}
}
Basically each Statement entity has a property of amount. I want to check to see if that property is a positive or negative number. Again this system works, but it just seems like it's a ton of hoops to jump through to access that data.
After this I take these 2 arrays (positive & negative) and use them to populate the different sections of my UITableView.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("personCell", forIndexPath: indexPath) as! PersonTableViewCell
//print("\(persons?[indexPath.row].statements?.count) this is the count to use")
//print("\(indexPath.row) this is the index row")
var numberForDispay = 0.00
switch(indexPath.section) {
case 0:
if(positiveArray[indexPath.row].statements?.count != 0){
for(var i = 0; positiveArray[indexPath.row].statements?.count > i; i++){
let statementNumber = positiveArray[indexPath.row].statements?[i] as? Statement
//print(statementNumber?.amount)
numberForDispay = numberForDispay + Double((statementNumber?.amount)!)
// this will make negative numbers positive
numberForDispay = fabs(numberForDispay)
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
cell.statementAmount.text = formatter.stringFromNumber(numberForDispay)
//print("\(formatter) this is the number to use")
}
}else{
cell.statementAmount.text = "$0.00"
}
case 1:
if(negativeArray[indexPath.row].statements?.count != 0){
for(var i = 0; negativeArray[indexPath.row].statements?.count > i; i++){
let statementNumber = negativeArray[indexPath.row].statements?[i] as? Statement
//print(statementNumber?.amount)
numberForDispay = numberForDispay + Double((statementNumber?.amount)!)
// this will make negative numbers positive
numberForDispay = fabs(numberForDispay)
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
cell.statementAmount.text = formatter.stringFromNumber(numberForDispay)
//print("\(formatter) this is the number to use")
}
}else{
cell.statementAmount.text = "$0.00"
}
default: ""
}
switch(indexPath.section) {
case 0:
cell.personName.text = postitiveArray[indexPath.row].name
cell.backgroundColor = Styles.blueColor();
case 1:
cell.personName.text = negativeArray[indexPath.row].name
cell.backgroundColor = Styles.redColor();
default: cell.personName.text = "hello"
}
cell.personName.textColor = Styles.whiteColor()
cell.statementAmount.textColor = Styles.whiteColor()
// will make the divide line full width
cell.separatorInset = UIEdgeInsetsMake(0, 0, cell.frame.size.width, 0)
if (cell.respondsToSelector("preservesSuperviewLayoutMargins")){
cell.layoutMargins = UIEdgeInsetsZero
cell.preservesSuperviewLayoutMargins = false
}
// set the accessory icon color
cell.tintColor = UIColor.whiteColor()
return cell
}
Again this works, but i'm hoping that I'm able to clean up the amount of code that I have and streamline this process. I am coming from a flash / AS3 background. I know this is a long post, so if you got this far, THANK YOU! I just want to make sure I'm not creating more work for myself when I work on these apps.
I would recommend using a NSFetchedResultsController. You could even use two, one for each section. You get a lot of optimizations in memory, database access and performance.
Here are the 2 predicates, which you add to the fetch request of the fetched results controllers (fetching Statement objects):
NSPredicate(format: "amount < 0")
NSPredicate(format: "amount >= 0")
Return 2 as number of sections, and the fetchedObjects.count of the corresponding fetched results controller as numberOfRowsInSection.
You could do this with a single fetched results controller as well. But you would have to hard-code into the database a flag indicating to which section each amount belongs to. So whenever you set the amount, you would automatically have the entity object set its plus/minus flag.
BTW, rather than iterating through items, you can be much more concise in Swift (not only with managed objects but with any kind of object). E.g.
let negative = allStatements.filter { $0.amount < 0 }
let positive = allStatements.filter { $0.amount >= 0 }
Note that there are also aggregate functions available to Core Data. The sum of all statement amounts of a person would be
let sum = person.valueForKeyPath("#sum.amount") as! NSNumber
With this technique, you could have a sum attribute of Person that is updated whenever you set the amount of a Statement.
So your to Person predicates would be
NSPredicate(format: "sum < 0")
NSPredicate(format: "sum >= 0")

Getting Glyph names using Core Text

For a small side project, I need to have all glyph names available in a font. So, I thought to make this:
CTFontRef f = CTFontCreateWithName(CFSTR("Zapfino"), 40, NULL);
CFIndex count = CTFontGetGlyphCount(f);
printf("There are %ld glyphs\n", count);
for (CGGlyph i = 1; i < count + 1; i++)
{
CTGlyphInfoRef gi = CTGlyphInfoCreateWithGlyph(i, f, CFSTR("(c)"));
CFStringRef name = CTGlyphInfoGetGlyphName(gi);
CGFontIndex idx = CTGlyphInfoGetCharacterIdentifier(gi);
printf("Glyph: %4hu, idx: %4hu ", i, idx);
CFShow(name);
printf("\n");
}
Creating the font and getting the glyph count works just fine. The name of the glyph is always NULL though. The CTGlyphInfoRef variable 'gi' gets a value. Any thoughts? What am I missing here?
You've misunderstood what CTGlyphInfo is about. It's not a way to query for information about a glyph. It's a representation of a substitution of a glyph for a string. You can set a glyph info object as the value for the kCTGlyphInfoAttributeName attribute in an attributed string. That glyph then replaces that range of attributed text, if the text matches the base string.
You can use CGFontCopyGlyphNameForGlyph() to get the name for a glyph from a font. You can create the CGFontRef directly using the CGFontCreate...() functions. You can also create one from a CTFont using CTFontCopyGraphicsFont().

BIRT Palette scripting: How to access dataset row

If I want to change the color of circles in scatter chart based on a field not being used in the chart, then how do i use that column in script. I mean how can i get the that data...for example
If (row[v_count])>2
fill red color...
The exact code is below
function beforeDrawDataPoint(dph, fill, icsc)
{
//Fill implements Fill interface
//ImageImpl
//ColorDefinitionImpl
//GradientImpl
//MultipleFillImpl
//EmbeddedImageImpl
//PatternImageImpl
importPackage( Packages.org.eclipse.birt.chart.model.attribute.impl );
val = dph.getOrthogonalValue();
if( fill.getClass().isAssignableFrom(ColorDefinitionImpl)){
if (row[v_count]>2){
fill.set(255, 0, 0);
}
}
}
but i dont know do i get that v_count column in the script. is there some function to get that column ?
I mean if we are making some calculations based on a column from databinding columns..that is not being used in x or y axis, then how do we access that column in the script..is there some kind of function for that.. I tried row["v_count"], but it is not working.
Arif
You could use "persistent global variables". In any place of your report you can write the following to store and load a global variable. Note that you cannot store Integers but only Strings (but after loading you can cast your Strings back to other types). You could store the Value of your column in the Script of an invisible data field located above your chart, so inside your chart you can read the value.
//store a value
reportContext.setPersistentGlobalVariable("varName", "value");
//load the value
var load = reportContext.getPersistentGlobalVariable("varName");
I spend my day look but I did not find the solution, this is my colleague who give me :)
So I share.
in my example I had to create a vertical marker for every new year
function beforeGeneration(chart, icsc)
{
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl);
var chart = icsc.getChartInstance();
var yAxis = chart.getBaseAxes()[0];
//get date series for my case
series = yAxis.getRuntimeSeries();
// but if you have multiple series ... (for exemple xaxis)
for (i = 0; i < series.length; i++){
var values = series[i].getDataSet().getValues();
for (j = 0; j < values.length; j++){
if(j > 1){
var date1 = values[j-1];
var date2 = values[j];
if(date1.getYear() < date2.getYear()){
min_ml = MarkerLineImpl.create(yAxis, NumberDataElementImpl.create(j));
min_ml.getLabel().getCaption().setValue("Nouveau boitier");
min_ml.getLineAttributes().getColor().set(255,0,0);
}
}
}
}
}

Displaying different values for each row in NSTableView

I am trying to make a program that will have an NSTableView that I can add and remove values from, and for each value it will store a few different variables that will be displayed in text boxes when a user selects an item from the table. I've already wrote the code to add and remove values, but can't seem to find a way to get the rest of the functionality to work. How can I do this?
I suggest that you you represent each element in your tableview datasource (your array of objects) as a NSDictionary. This enables you to keep several variables for each tableview item, which can be displayed in textboxes when an item is clicked. Apple has a very good example that illustrates what I think you are trying to do. Take a look at the NSTableViewBinding example. In the example, when the user double-clicks an item in the tableview an inspect method is called. You can use this method to display your variables from the dictionary in textboxes:
- (void)inspect:(NSArray *)selectedObjects
{
// this is an example of inspecting each selected object in the selection
int index;
int numItems = [selectedObjects count];
for (index = 0; index < numItems; index++)
{
NSDictionary *objectDict = [selectedObjects objectAtIndex:index];
if (objectDict != nil)
{
NSLog(#"inspect item: {%# %#, %#}",
[objectDict valueForKey:#"firstname"],
[objectDict valueForKey:#"lastname"],
[objectDict valueForKey:#"phone"]);
[myTextBox1 setStringValue:[objectDict valueForKey:#"firstname"]];
[myTextBox2 setStringValue:[objectDict valueForKey:#"lastname"]];
}
}
}

Resources