Getting number of friends in FBFriendPickerViewController - facebook-ios-sdk

I am using FBFriendPickerViewController to display a list of friends and I'm trying to find an easy way to get the number of friends in the list. I've tried implementing the friendPickerViewControllerDataDidChange:(FBFriendPickerViewController *)friendPicker method but it sometimes (especially while testing on different devices such as 3.5 inch iPhone vs 4.0 inch iPhone) gets fired twice (definitely a bug) and messes up the number. Is there any reliable way to get the number of friends like [friendPicker numberOfFriends]?
Thanks,
Can.

I Don't really like using the tableview to fetch the number of friends, you can simply do that with a graph call, but if you want to use the view, a simple way is to do it as follows:
int sum = 0;
for (int x=0; x< [friendPickerController.tableView numberOfSections]; x++) {
sum+= [friendPickerController.tableView numberOfRowsInSection:x];
}
NSLog(#"You have %d friends", sum);
Again, not the best way to do it, but if that's what you need, there it is.
also you need to make sure the data is already loaded before trying to count the rows, else the sum will be 0
To know when the data has been loaded, create a FBFriendPickerDelegate and use the method:
- (void)friendPickerViewControllerDataDidChange:(FBFriendPickerViewController *)friendPicker;
To know when the data has been loaded.
Here's Facebook's reference
Cheers !

Related

Exposing the current combo selection index for the CGridCellCombo class

For several years I have been using the CGridCellCombo class. It is designed to be used with the CGridCtrl.
Several years ago I did make a request in the comments section for an enhancement but I got no replies.
The basic concept of the CGridCellCombo is that it works with the text value of the cell. Thus, when you present the drop list it will have that value selected. Under normal circumstances this is fine.
But I have places where I am using the combo as a droplist. In some situations it is perfectly fine to continue to use the text value as the go-between.
But is some situations it would have been ideal to know the actual selected index of the combo. When I have a droplist and it is translated into 30 languages, and I need to know the index, I have no choice but to load the possible options for that translation and then examine the cell value and based on the value found in the array I know the index.
It works, but is not very elegant. I did spend a bit of time trying to keep track of the selected index by adding a variable to CInPlaceList and setting it but. I then added a wrapper method to the CGridCellCombo to return that value. But it didn't work.
I wondered if anyone here has a good understanding of the CGridCellCombo class and might be able to advise me in exposing the CComboCell::GetCurSel value.
I know that the CGridCtrl is very old but I am not away of another flexible grid control that is designed for MFC.
The value that is transfered back to the CGridCtrl is choosen in CInPlaceList::EndEdit. The internal message GVN_ENDLABELEDIT is used, and this message always use a text to set it into the grid.
The value is taken here via GetWindowText from the control. Feel free to overwrite this behaviour.
The handler CGridCtrl::OnEndInPlaceEdit again calls OnEndEditCell. All take a string send from GVN_ENDLABELEDIT.
When you want to make a difference between the internal value and the selected value you have to manage this via rewriting the Drawing and selecting. The value in the grid is the GetCurSel value and you have to show something different... There isn't much handling about this in the current code to change.
More information
The key is CInPlaceList::EndEdit(). There is a call to GetWindowText (CInPlaceList is derived from CComboBox), just get the index here. Also in CGridCellCombo::EndEdit you have access to the m_pEditWnd, that is the CInPlaceList object and derived from CComboBox, so you have access here too.
I have found this to be the simplest solution:
int CGridCellCombo::GetSelectedIndex()
{
int iSelectedIndex = CB_ERR;
CString strText = GetText();
for (int iOption = 0; iOption < m_Strings.GetSize(); iOption++)
{
if (strText.CollateNoCase(m_Strings[iOption]) == 0) // Match
{
iSelectedIndex = iOption;
break;
}
}
return iSelectedIndex;
}

When can we get access to nest autoaway status?

Let me stress that I am not a programmer but I like messing around with things. I've been using #ifttt and #nest for years and recently started using #smartthings to do cool things in my house.
I wanted to power off devices such as my lights and water heater based on leaving my house. Rather than having this depend on one device such as a phone or keyfoob, I wanted to use the nest "auto-away" feature.
Auto-away doesn't appear to be exposed to #ifttt or #smartthings. I've asked #nestsupport and they told me to come here :-o.
Does anyone from nest developer team know when developers and other products will be able to consume this from he nest device? Its a real shame that after several years this isn't exposed yet. Not only that but it could be an additional selling point to integrate and turn on/off items in your house.
Thank
I'm not from the Nest developer team, but I've played around with the Nest API in the past, and use it to plot my energy usage.
The 'auto away' information is already accessible in the API, and looks to be used in a number of IFTTT recipes:
https://ifttt.com/recipes/search?q=auto+away&ac=false
Within the (JSON) data received back in the API, the 'auto away' status is accessible via;
shared->{serial_number}->auto_away
This is set as a boolean (0 or 1).
If you like messing around with code, and know any PHP, then this PHP class for the Nest API is very useful at grabbing all information etc;
https://github.com/gboudreau/nest-api
Auto-Away is and always has been readable https://developer.nest.com/documentation/cloud/api-overview#away
There are a few ways you could go about doing this, but if you're writing up a SmartApp just for your own uses, I'd suggest piggybacking off of one of the existing device types for the Nest on SmartThings. As a quick example, I'll use the one that I use:
https://github.com/bmmiller/device-type.nest/blob/master/nest.devicetype.groovy
After line 96, this is to expose the status to any SmartApp you may write:
attribute "temperatureUnit", "string"
attribute "humiditySetpoint", "number"
attribute "autoAwayStatus", "number" // New Line
Now, you'll want to take care of getting the data in the existing poll() method, currently starting at line 459.
After line 480, to update the attribute
sendEvent(name: 'humidity', value: humidity)
sendEvent(name: 'humiditySetpoint', value: humiditySetpoint, unit: Humidity)
sendEvent(name: 'thermostatFanMode', value: fanMode)
sendEvent(name: 'thermostatMode', value: temperatureType)
sendEvent(name: 'autoAwayStatus', value: data.shared.auto_away) // New Line
This will expose a numerical value for the auto_away status.
-1 = Auto Away Not Enabled
0 = Auto Away Off
1 = Auto Away On
Then, in your SmartApp you write, where you include an input of type thermostat like this:
section("Choose thermostat... ") {
input "thermostat", "capability.thermostat"
}
You will be able to access the Auto Away status by referring to
thermostat.autoAwayStatus
From anywhere in your code where you can do something like
if (thermostat.autoAwayStatus == 1) {
// Turn off everything
}

Referencing external doc in CouchDB view

I am scraping an 90K record database using JSON-RPC and I am trying to put in some basic error checking. I want to start by scraping the database twice using two different settings and adding a prefix to the second scrape. This way I can check to ensure that the two settings are not producing different records (due to dropped updates, etc). I wanted to implement the comparison using a view which compares each document from the first scrape with it's twin produced by the second scrape and then emit the names of records with a difference between them.
However, I cannot quite figure out how to pull in another doc in the view, everything I have read only discusses external docs using the emit() function, which is too late to permit me to compare it. In the example below, the lookup() function would grab the referenced document.
Is this just not possible?
function(doc) {
if(doc._id.slice(0,1)!=='$' && doc._id.slice(0,1)!== "_"){
var otherDoc = lookup('$test" + doc._id);
if(otherDoc){
var keys = doc.value.keys();
var same = true;
keys.forEach(function(key) {
if ((key.slice(0,1) !== '_') && (key.slice(0,1) !=='$') && (key!=='expires')) {
if (!Object.equal(otherDoc[key], doc[key])) {
same = false;
}
}
});
if(!same){
emit(doc._id, 1);
}
}
}
}
Context
You are correct that this is not possible in CouchDB. The whole point of the map function is that it must be idempotent, otherwise you lose all the other nice benefits of a pre-calculated index.
This is why you cannot access external resources in the map function, whether they be other records or the clock. Any time you run a map you must always get the same result if you put the same record into it. Since there are no relationships between records in CouchDB, you cannot promise that this is possible.
Solution
However, you can still achieve your end goal, just be different means. Some possibilities...
Assuming there is some meaningful numeric value in each doc, you could use a view to take the sum of all those values and group them by which import you did ({key: <batch id>, value: <meaningful number>}). Then compare the two numbers in your client or the browser to see if they match.
A brute force approach would be to use a view to pair the docs that should match. Each doc is on a different row, but they're grouped by a common field. Then iterate through the entire index comparing the pairs. This would certainly be the quickest to code and doesn't depend on your application or data.
Implement a validation function to enforce a schema on your data. Just be warned that this will reduce your write throughput since each written record will be piped out of Erlang and into the JS engine. Also, this is only applicable if you're worried about properly formed records instead of their precise content, which might not be the case.
Instead of your different batch jobs creating different docs, have them place them into the same doc. The structure might look like this: { "_id": "something meaningful", "batch_one": { ..data.. }, "batch_two": { ..data.. } } Then your validation function could compare them or you could create a view that indexes all the docs that don't match. All depends on where in your pipeline you want to do the error checking and correction.
Personally I like the last option better, but only if you don't plan to use the database as is in production. Ie., you wouldn't want to carry around all that extra data in each record.
Hope that helps.
Cheers.

Creating a pagination index in CouchDB?

I'm trying to create a pagination index view in CouchDB that lists the doc._id for every Nth document found.
I wrote the following map function, but the pageIndex variable doesn't reliably start at 1 - in fact it seems to change arbitrarily depending on the emitted value or the index length (e.g. 50, 55, 10, 25 - all start with a different file, though I seem to get the correct number of files emitted).
function(doc) {
if (doc.type == 'log') {
if (!pageIndex || pageIndex > 50) {
pageIndex = 1;
emit(doc.timestamp, null);
}
pageIndex++;
}
}
What am I doing wrong here? How would a CouchDB expert build this view?
Note that I don't want to use the "startkey + count + 1" method that's been mentioned elsewhere, since I'd like to be able to jump to a particular page or the last page (user expectations and all), I'd like to have a friendly "?page=5" URI instead of "?startkey=348ca1829328edefe3c5b38b3a1f36d1e988084b", and I'd rather CouchDB did this work instead of bulking up my application, if I can help it.
Thanks!
View functions (map and reduce) are purely functional. Side-effects such as setting a global variable are not supported. (When you move your application to BigCouch, how could multiple independent servers with arbitrary subsets of the data know what pageIndex is?)
Therefore the answer will have to involve a traditional map function, perhaps keyed by timestamp.
function(doc) {
if (doc.type == 'log') {
emit(doc.timestamp, null);
}
}
How can you get every 50th document? The simplest way is to add a skip=0 or skip=50, or skip=100 parameter. However that is not ideal (see below).
A way to pre-fetch the exact IDs of every 50th document is a _list function which only outputs every 50th row. (In practice you could use Mustache.JS or another template library to build HTML.)
function() {
var ddoc = this,
pageIndex = 0,
row;
send("[");
while(row = getRow()) {
if(pageIndex % 50 == 0) {
send(JSON.stringify(row));
}
pageIndex += 1;
}
send("]");
}
This will work for many situations, however it is not perfect. Here are some considerations I am thinking--not showstoppers necessarily, but it depends on your specific situation.
There is a reason the pretty URLs are discouraged. What does it mean if I load page 1, then a bunch of documents are inserted within the first 50, and then I click to page 2? If the data is changing a lot, there is no perfect user experience, the user must somehow feel the data changing.
The skip parameter and example _list function have the same problem: they do not scale. With skip you are still touching every row in the view starting from the beginning: finding it in the database file, reading it from disk, and then ignoring it, over and over, row by row, until you hit the skip value. For small values that's quite convenient but since you are grouping pages into sets of 50, I have to imagine that you will have thousands or more rows. That could make page views slow as the database is spinning its wheels most of the time.
The _list example has a similar problem, however you front-load all the work, running through the entire view from start to finish, and (presumably) sending the relevant document IDs to the client so it can quickly jump around the pages. But with hundreds of thousands of documents (you call them "log" so I assume you will have a ton) that will be an extremely slow query which is not cached.
In summary, for small data sets, you can get away with the page=1, page=2 form however you will bump into problems as your data set gets big. With the release of BigCouch, CouchDB is even better for log storage and analysis so (if that is what you are doing) you will definitely want to consider how high to scale.

how about run Subsonic version 2 and 3 together?

Today I compile subsonic version with different namespace (as subsonic3) and place it together with subsonic version 2.
Also create all files (for both versions, in different dlls) for my database with success, and make simple tests, and seams that everything works perfect.
This is my simple test code, and you can see 3 and 2 run together.
var PageTitlesOn3 = from p in ATH_Store_Product.All()
where p.ProductID == 1
select p;
foreach (ATH_Store_Product Ena in PageTitlesOn3)
{
txtOnMe.Text += string.Format("<br />{0} ) {1}",
Ena.ProductID, Ena.ProductName);
}
AthStoreProductCollection AllMyTitlesAgainOn2 = new AthStoreProductCollection()
.Where(AthStoreProduct.Columns.ProductID, 1)
.Load();
foreach (AthStoreProduct Ena in AllMyTitlesAgainOn2)
{
txtOnMe.Text += string.Format("<br />{0} ) {1}",
Ena.ProductID, Ena.ProductName);
}
I did that, because I like to move to subsonic 3, but I need to do that one piece at the time, some part code, then some other part etc.
My project is a little bit huge, and run online, and I do not won't to stop it run.
This way, placing subsonic 2 and 3, working together, I can start migrating my code in time.
Now my question is if I am doing any big error, and if they going to crash after run together all their time, if I eat a lot of resources, etc.
I have looked the source code of subsonic, but I am not that familiar (yet) with what really do, what and how is open the database etc…
Now, my second question is, why not subsonic ver3, permanently renamed to subsonic3, and other users do the same think that I did.
Thank you in advanced.
I can't see anything wrong here, after all, it is as if you have two DAL's, one of which it tends to disappear in favor of the other.

Resources