When I create a new value on Firebase does it automatically create a createdAt and updatedAt field or am I supposed to handle that on my own? I've noticed there's a constants kFirebaseServerValueTimestamp which is essentially a dictionary. How can I use that to retrieve that value after creating my object?
You can get the value by listening to the location:
Firebase *ref = [[Firebase alloc] initWithUrl:#"<my-firebase-app>/timestamp"];
// listen for update
[ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%#", snapshot.value);
}];
// save timestamp
[ref setValue: kFirebaseServerValueTimestamp];
Related
I'm trying to retrieve data from firebase and I an using the guide given by firebase but I am not able to create the reference with my firebase database.
FIRDatabaseReference * ref = [[FIRDatabase alloc]
referenceFromURL:#"https://project-8326407164650950213.firebaseio.com"];
NSLog(#"%#",ref);
I am using this code to create the reference with my database but app crash.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: key cannot be nil'
I am new in iOS and first time using firebase. Please tell me the solution as I am going according to firebase guide.
I'm no firebase expert, but when you're working with a class in Obj-C, you'll either invoke its class methods (e.g. [FIRDatabase database]), or you'll first allocate and initialize it ([[FIRDatabase alloc] <an initializer>]), and secondly use an instance method on the instance.
In your code sample above, I see an alloc without an initializer, which makes me think you're missing something.
If I look at the iOS quick start, I see a call to initWithURL, which is one of the initializers.
Firebase *messagePath = [[Firebase alloc] initWithUrl:[NSString stringWithFormat:#"%#%#%#", MAIN_URL,MESSAGES_DIRECTORY,conversationId]];
[[messagePath queryLimitedToLast:10] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSMutableArray *messages = [[NSMutableArray alloc] init];
[messages addObject:snapshot.value];
observingBlock(true,messages);
}];
Here is the code with you can get the data and value of the node. First make url till your node.
Still you have any problem just add comment here. now a days working on Firebase chat in swift.
You can do it easily. If you want to fetch all info using this you can do this. Make sure you have made your db public then no auth needed
#property (strong, nonatomic) FIRDatabaseReference *ref;
Define Property on interface then
self.ref = [[FIRDatabase database] reference];
[self.ref observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
NSDictionary *usersDict = snapshot.value;
NSLog(#"Information : %#",usersDict);
}];
If you want to fetch specific portion using this you can do this
[[self.ref child:#"results"] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
NSDictionary *usersDict = snapshot.value;
NSLog(#"Info : %#",usersDict);
}];
My Fetched Json From Firebase
{
"results" : [
{
"name":"test 1",
"URL" : "URL STRING"
},
{
"name":"test 1",
"URL" : "URL STRING"
},
{
"name":"test 1",
"URL" : "URL STRING"
},
{
"name":"test 1",
"URL" : "URL STRING"
}
]
}
This question already has an answer here:
Querying for existing nodes in Firebase is returning null
(1 answer)
Closed 6 years ago.
I am trying to understand how i can do a search in my Firebase database to check if a record exists and if so to grab details under that specific branch.
Currently i can accomplish what i need to by grabbing a specific record and placing it into a textfield and going from there, however i need to do a check on multiple records in the database till a specific record is found and from there load all the details under that branch.
Heres what i am doing currently;
Firebase *ref = [[Firebase alloc] initWithUrl: #"https://sizzling-inferno-255.firebaseio.com/"];
//Refer to users entity
Firebase *usersRef = [ref childByAppendingPath: #"id/"];
// Read data and react to changes
[usersRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%# -> %#", snapshot.key, snapshot.value);
NSDictionary *dict=[NSDictionary dictionaryWithDictionary:snapshot.value];
NSString *stri=[NSString stringWithFormat:#"%#",dict];
_textview1.text = stri;
string1 = snapshot.key;
_label1.text = string1;
}];
Feel free to check for yourself using the URL, i only use this for testing anyway.
I found something close to what i need however it is not in Objective C.
I'm new in firebase, but I've been working too much on the new version.
Is Record the name of your key inside of sizzling-inferno-255? So if it is. In this new version you can retrieve some info by:
FIRDatabaseReference *usersRef = [[FIRDatabase database] reference];
[[[[usersRef child:#"results"] child:#"sizzleing-inferno-255"] child:#"record"] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
NSString *record = snapshot.value;
if(record.length > 0) {
// Yes! there is a record.
}
}
Is that what you want? Let me know.
I cant seem to retrieve any information from my firebase database. I created a table with both author and title available.
This is the code i ran in my ios app, but the app just keeps crashing.
// Get a reference to our posts
Firebase *ref = [[Firebase alloc] initWithUrl: #"**********"];
[ref observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%#", snapshot.value[#"author"]);
NSLog(#"%#", snapshot.value[#"title"]);
}];
}
I cant tell whats going wrong, any help with this i will be appreciated.
Thank you
change event type to
[ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%#", snapshot.value[#"author"]);
NSLog(#"%#", snapshot.value[#"title"]);
}];
You would generally not store data like that right under your root node - it would generally be a child node(s) stored under the root node, like this:
sizzling-inferno-255
book_node_0
author: test_author
title: test title
book_node_1
author: another author
title: another title title
Firebase *ref = [[Firebase alloc] initWithUrl: #"sizzling-inferno-255"];
[ref observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSLog(#"%#", snapshot.value[#"author"]);
NSLog(#"%#", snapshot.value[#"title"]);
}];
will iterate over each book node and return a snapshot of that node. So the first time a snapshot is returned, it will be
book_node_0
author: test_author
title: test title
and the second time a snapshot is returned will be
book_node_1
author: another author
title: another title title
the book_node keys are generated with childByAutoId.
ChildAdded reads in each child node one at a time as a snapshot.
Value reads in everything in the node; all child nodes, those children etc and can be a large amount of data. If the ref node contains children, like in this answer, all of the nodes are returned and they need to be iterated over to get the child data, so within the observe block...
for child in snapshot.children {
NSLog(#"%#", child.value[#"author"]);
}
Edit - and to specifically answer the OP question, here's how you do it with the Firebase structure in the question:
self.myRootRef = [[Firebase alloc] initWithUrl:#"https://**********"];
[ref observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSString *key = snapshot.key;
NSString *value = snapshot.value;
if ( [key isEqualToString:#"author"] ) {
NSLog(#"author = %#", value);
} else if ([snapshot.key isEqualToString:#"title"] ) {
NSLog(#"title = %#", value);
}
}];
I've read that it's important to keep data flatter for Firebase and to also only nest data that you intend to call. I've done those things, but Firebase is still too slow at retrieving data. Here's an example:
My data looks like this:
--English
----Ari : 4
----Philip : 2
----John : 6
And my code looks like this:
[super viewDidLoad];
[[DataSource sharedInstance].selectedLanguageMutableArray removeAllObjects];
//Retrieving Data From Firebase
NSString* selectedLanguagePath = [NSString stringWithFormat:#"languages/%#", [DataSource sharedInstance].languageSelected];
Firebase *languagesRef = [[DataSource sharedInstance].ref childByAppendingPath:selectedLanguagePath];
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
[self.distanceMutableArray addObject:snapshot.key];
NSLog(#"%#", snapshot.key);
NSLog(#"%#", snapshot.value);
NSLog(#"%#", self.distanceMutableArray);
}];
//Selected Languages Mutable Array
[[DataSource sharedInstance].selectedLanguageMutableArray removeAllObjects];
for (NSInteger i = 0; i < self.distanceMutableArray.count; i++) {
UserCustomizationData *item = [[UserCustomizationData alloc] init];
NSString* selectedUser = self.distanceMutableArray[i];
Firebase* selectedUserRef = [[DataSource sharedInstance].usersRef childByAppendingPath:selectedUser];
if (selectedUser.length > 0) {
Firebase* profilePicRef = [selectedUserRef childByAppendingPath:#"profilePicture"];
[profilePicRef observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSString* profPicString = snapshot.value;
NSData *dataFromBase64=[NSData base64DataFromString:profPicString];
UIImage *profPicImage = [[UIImage alloc]initWithData:dataFromBase64];
item.profilePicture = profPicImage;
}];
[[DataSource sharedInstance].selectedLanguageMutableArray addObject:item];
}
}
However, the for loop runs before the self.distanceMutableArray can populate. This throws everything off because the for loop relies on the self.distanceMutableArray being populated.
Is there a way to retrieve data such that the code will run fluidly and in the order that it is written?
The issue here is that Firebase works via asynchronous calls; your code will not work consistently because the code below the Firebase block may be called before the block completes.
You will need to start coding asynchronously and only perform actions on snapshot data after you know for sure it has been populated (inside the block)
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
//at this point, firebase has loaded the snapshot
// so its available to work with
[self.distanceMutableArray addObject:snapshot.key];
for (NSInteger i = 0; i < self.distanceMutableArray.count; i++) {
//do some stuff with the items in snapshot
}
}];
//don't work with anything that was from the snapshot as it may have not been filled yet
However there's an issue as the code is using childAdded, so that will iterate over each item in the firebase node, so that code won't work either as it won't load the array correctly (yes we can fix that by populating the array during each loop).
The additional challenge here is that you need to retrieve data from Firebase based on the result of your first snapshot. Again, same situation exists; only perform actions on that retrieved data after you know for sure it has been retrieved.
One solution is to load in the entire dataset at one time and iterate over it (by value instead of added). If your data sets are smaller that works. However, for big datasets that can be too much.
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
//at this point, firebase has loaded the snapshot
// so its available to work with and loaded with
//everything in the node
for ( FDataSnapshot *child in snapshot.children) {
NSDictionary *dict = child.value;
NSString *uid = child.key;
[self.distanceMutableArray addObject:uid];
}
// now the array is loaded do something with it
}];
Another option is to change how your data is stored in firebase so you can retrieve data together so you dont have to make multiple observe calls.
I am struggling to use Parse to save an array of data - or at least I am finding I can't verify that my data is being saved.
I have a PFObject (journey) and I want to update it with my location (a string in the format: #"{lat, long}").
Eventually though I want to update and save my location every 10-30 seconds meaning I don't want to create a new object each time rather I want to add an array to the object and then update the array each time I have a new location.
Currently my code looks like this:
- (IBAction)startJourneyButtonPressed:(id)sender {
PFObject * journey = [PFObject objectWithClassName:#"Journey"];
journey[#"company"] = _companyNameTextField.text;
journey[#"destination"] = _destinationTextField.text;
[journey saveInBackground];
NSData * faceImageData = UIImagePNGRepresentation([_faceButton imageForState:UIControlStateNormal]);
PFFile * faceImageFile = [PFFile fileWithName:#"faceImage.png" data:faceImageData];
[faceImageFile saveInBackground];
NSData * carImageData = UIImagePNGRepresentation([_carButton2 imageForState:UIControlStateNormal]);
PFFile * carImageFile = [PFFile fileWithName:#"carImage.png" data:carImageData];
[carImageFile saveInBackground];
journey[#"faceImage"] = faceImageFile;
journey[#"carImage"] = carImageFile;
[journey saveInBackground];
NSMutableArray * locationArray = [NSMutableArray new];
[locationArray addObject:[self getCurrentLocationString]];
journey[#"location"] = locationArray;
[journey saveInBackground];
}
The strings are saving fine and so are the images but the dataBase doesn't seem to be getting uploaded with the array.
Here is a screenshot of my database:
I am expecting to see a "location" heading but obviously it isn't appearing.
Reading up on other forums it says that I have to have an object in JSON format for this to work but as I am only storing Strings and I am not receiving and JSON errors I don't think this is the issue.
Any help would be very appreciated
Probably it is saving your array, you should just manually in your database add column with name "location" (do not forget to set it as array type) to see the values.