I have a table view with 40 objects. I have to filter them by gender when Click in a UISegment (male, female and both). It seems to be working, but table view does not refresh. Please any help would be appreciatte.
-(void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"People";
[self loadall];
[[NSBundle mainBundle] loadNibNamed:#"FilterSortView" owner:self options:nil];
self.filterControl.selectedSegmentIndex = -1;
[self.filterControl addTarget:self action:#selector( changeSegge ) forControlEvents:UIControlEventValueChanged];
}
#
My second method to filter by gender
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}
Thanks a lot.
You forgot to fill people array after predicate set to fetch request.
Here is updated changeSegge method:
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data >records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}
Related
I need to update the value of the desired cell in my core data. I have a cell (ID) with a known value to me. I need to find the value and replace. I know how to change the elements of the array. The following shows how I do it. But I have to change the field (ID) in MyBase. value that I need to change will be equal to fromIndexPath.row. The value on which I need to change toIndexPath.row.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath
*)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
if (fromIndexPath.section == toIndexPath.section) {
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:#"MyBase"
inManagedObjectContext:self.objectContext];
[fetchRequest setEntity:entityDescription];
empArray = [(NSArray*)[self.objectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
MyBase *employee = [empArray objectAtIndex:fromIndexPath.row];
[empArray removeObjectAtIndex:fromIndexPath.row];
[empArray insertObject:objectToMove atIndex:toIndexPath.row];
}
}
for update core data, you can try this:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#:#"Employee"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"empId = %d", 12345]];
[request setPredicate:pred];
NSArray *empArray=[self.managedObjectContext executeFetchRequest:request error:nil];
[request release];
if ([empArray count] > 0){
Employee *employee = [empArray objectAtIndex:fromIndexPath.row];;
employee.empSalary=[NSNumber numberWithInt:45000];
employee.empName=#"John";
employee.empDesignation=#"Analysist";
employee.empExp=#"4 Years";
[self.managedObjectContext save:nil];
I'm getting this error while trying to use Core Data:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext'
I traced the error back to this in my modal view controller which contains the Table View:
- (void)setupFetchedResultsController
{
NSString *entityName = #"Location";
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
// ERROR OCCURS IN THE LINE BELOW vvv
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self performFetch];
}
This is what I have in my AppDelegate:
- (void)setupFetchedResultsController
{
NSString *entityName = #"Location";
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self.fetchedResultsController performFetch:nil];
}
I get no errors there, and here's more of the App Delegate:
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
// Using abort() right now just for development
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil)
{
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Model" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Forecaster.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
and in my Model.xcdatamodeid:
Any help would be great! Thanks!
Here is the Method:
- (void)setupFetchedResultsController
{
NSManagedObjectContext *moc = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Location" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
else
{
// your data is in array
}
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FailedBankInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (FailedBankInfo *info in fetchedObjects) {
NSLog(#"Name: %#", info.name);
FailedBankDetails *details = info.details;
NSLog(#"Zip: %#", details.zip);
}
My table is scrolling incredibly slow, and I think it's caused by the Core Data methods within my cellForRowAtIndexPath. Below is my cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSManagedObject *info = [buildingArray objectAtIndex: [indexPath row]];
// all rooms have been scanned for building
if([self allRoomsScanned: [[info valueForKey:#"buildingid"] intValue]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[cell.textLabel setTextColor: [UIColor lightGrayColor]];
}
else {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell.textLabel setTextColor: [UIColor blackColor]];
}
[cell.textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:16.0]];
[cell.textLabel setText:[info valueForKey:#"buildingname"]];
return cell;
}
And here is the allRoomsScanned method and allDevicesScanned method:
- (BOOL) allRoomsScanned: (int) buildingID {
NSMutableArray *scannedRoomArray = [[NSMutableArray alloc] init];
// Get all user_device
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"user_device" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
NSNumber *deviceid = [NSNumber numberWithInt: 0];
NSNumber *roomid = [NSNumber numberWithInt: 0];
//int lastRoomID = 0;
for (NSManagedObject *info in fetchedObjects) {
// Get all device
deviceid = [info valueForKey:#"deviceid"];
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription
entityForName:#"device" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(deviceid = %d)", [deviceid intValue]];
[fetchRequest setPredicate:predicate];
NSArray *fetchedDevices = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *infod in fetchedDevices) {
// Get all room
roomid = [infod valueForKey:#"roomid"];
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription
entityForName:#"room" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(roomid = %d) AND (buildingid = %d)", [roomid intValue], buildingID];
[fetchRequest setPredicate:predicate];
NSMutableArray *fetchedRoom = [[context executeFetchRequest:fetchRequest error:&error] mutableCopy];
// add room to array if room belongs to selected building and room not already added
if([fetchedRoom count] > 0) { //&& lastRoomID != [roomid intValue]) {
for (NSManagedObject *info in fetchedRoom) {
NSLog(#"room id: %#", [info valueForKey:#"roomid"]);
// add room ids to array if not already there
if (![scannedRoomArray containsObject:[info valueForKey:#"roomid"]] && [self allDevicesScanned:[[info valueForKey:#"roomid"] intValue]])
[scannedRoomArray addObject: [info valueForKey:#"roomid"]];
}
//lastRoomID = [roomid intValue];
}
}
}
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription
entityForName:#"room" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(buildingid = %d)", buildingID];
[fetchRequest setPredicate:predicate];
NSArray *fetchedRoomTotal = [context executeFetchRequest:fetchRequest error:&error];
//NSLog(#"Total Rooms for Building: %d", [fetchedRoomTotal count]);
//NSLog(#"Scanned Rooms for Building: %d", [scannedRoomArray count]);
//NSLog(#"Scanned rooms: %#", scannedRoomArray);
if([fetchedRoomTotal count] == [scannedRoomArray count] && [fetchedRoomTotal count] > 0) {
return YES;
}
else {
return NO;
}
}
- (BOOL) allDevicesScanned: (int) roomID {
NSMutableArray *scannedDeviceArray = [[NSMutableArray alloc] init];
// Get all user_device
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"user_device" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
NSNumber *deviceid = [NSNumber numberWithInt: 0];
//NSNumber *roomid = [NSNumber numberWithInt: 0];
for (NSManagedObject *info in fetchedObjects) {
// Get all device
deviceid = [info valueForKey:#"deviceid"];
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription
entityForName:#"device" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(deviceid = %d) AND (roomid = %d)", [deviceid intValue], roomID];
[fetchRequest setPredicate:predicate];
NSArray *fetchedDevices = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *infod in fetchedDevices) {
// add device to array
if([fetchedDevices count] > 0) {
NSLog(#"room id: %d", roomID);
// add device ids to array if not already there
if (![scannedDeviceArray containsObject:deviceid])
[scannedDeviceArray addObject: deviceid];
}
}
}
fetchRequest = [[NSFetchRequest alloc] init];
entity = [NSEntityDescription
entityForName:#"device" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(roomid = %d)", roomID];
[fetchRequest setPredicate:predicate];
NSArray *fetchedDeviceTotal = [context executeFetchRequest:fetchRequest error:&error];
//NSLog(#"Total Devices for Room: %d", [fetchedDeviceTotal count]);
//NSLog(#"Scanned Devices for Room: %d", [scannedDeviceArray count]);
//NSLog(#"Scanned Devices: %#", scannedDeviceArray);
if([fetchedDeviceTotal count] == [scannedDeviceArray count] && [fetchedDeviceTotal count] > 0) {
return YES;
}
else {
return NO;
}
}
Any idea on how to get rid of the latency when scrolling? I'm assuming I may be doing something inefficiently with either my core data calls or the way I'm calling the method in cellForRowAtIndexPath.
Thank for any help. It is greatly appreciated.
You really should not make Fetch Requests and processing like that on the main thread while scrolling a table view.
As rokjarc said, you should definitely save the result of your (quite heavy) allRoomsScanned method. I'd suggest adding a new style, i.e. with an activity indicator, that the cell gets when you don't have a result for that input yet. As soon as the load is complete you refresh the table view cell.
Attention: You can't use your default NSManagedObjectContext in allRoomsScanned and allDevicesScanned.
You need to initialize a new context in the background thread. Either initialize a new context at the beginning of the block and pass it as a method parameter or create a new one right in the methods.
NSManagedObject *info = [buildingArray objectAtIndex: [indexPath row]];
NSNumber *cachedResult = [self.scanResults objectForKey:info.objectID];
if (cachedResult == nil) {
// style loading state
int scanInfo = [[info valueForKey:#"buildingid"] intValue];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL result = [self allRoomsScanned: scanInfo];
[self.scanResults setObject:[NSNumber numberWithBool:result] forKey:info.objectID];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]
});
} else if (cachedResult.boolValue == YES) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[cell.textLabel setTextColor: [UIColor lightGrayColor]];
} else if (cachedResult.boolValue == NO) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell.textLabel setTextColor: [UIColor blackColor]];
}
[cell.textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:16.0]];
[cell.textLabel setText:[info valueForKey:#"buildingname"]];
return cell;
I get this error when trying to add a record to my database:
2012-02-12 20:15:18.187 Flavma[3197:707] CoreData: error: Serious application error.
An exception was caught from the delegate of NSFetchedResultsController during a call to -
controllerDidChangeContent:. *** -[__NSArrayI objectAtIndex:]:
index 1 beyond bounds [0 .. 0] with userInfo (null)
I tried adding every way I can, but what I'm currently using is this category:
#import "Patient+Create.h"
#implementation Patient (Create)
+ (Patient *)patientWithLastName:(NSString *)lastName inManagedObjectContext:(NSManagedObjectContext *)context
{
Patient *patient = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Patient"];
request.predicate = [NSPredicate predicateWithFormat:#"lastName = %#", lastName];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"lastName" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *patients = [context executeFetchRequest:request error:&error];
if (!patients || ([patients count] > 1)) {
//handle error
} else if (![patients count]) {
//create a new one
patient = [NSEntityDescription insertNewObjectForEntityForName:#"Patient" inManagedObjectContext:context];
patient.lastName = lastName;
} else {
patient = [patients lastObject];
}
return patient;
}
#end
I am able to add data to my database when it's first created (if I delete the app from my device), like so:
- (void) fetchPatientDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchQ = dispatch_queue_create("Patient fetcher", NULL);
dispatch_async(fetchQ, ^{
[document.managedObjectContext performBlock:^{
[Patient patientWithLastName:#"Johnson" inManagedObjectContext:self.patientDatabase.managedObjectContext];
}];
});
dispatch_release(fetchQ);
}
But after that, I keep getting the same error. Any ideas?
#import "Patient+Create.h"
#implementation Patient (Create)
+ (Patient *)patientWithLastName:(NSString *)lastName inManagedObjectContext:(NSManagedObjectContext *)context
{
Patient *patient = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Patient"];
request.predicate = [NSPredicate predicateWithFormat:#"lastName = %#", lastName];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"lastName" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *patients = [context executeFetchRequest:request error:&error];
if (!patients || [patients count]<=0) {
//create a new one
patient = [NSEntityDescription insertNewObjectForEntityForName:#"Patient" inManagedObjectContext:context];
patient.lastName = lastName;
[context performSelectorOnMainThread:#selector(save:) withObject:nil waitUntilDone:YES];
} else {
patient = [patients lastObject];
}
return patient;
}
#end
Just save the newly created object on main thread.
Reason for this, you are creating the object on a secondary thread(GCD), those changes will not effect until you save the context on main thread
[context performSelectorOnMainThread:#selector(save:) withObject:nil waitUntilDone:YES];
I am working with coredata and successfully saved the data in data storage but when I try to output what I stored using table view ,I am not able to do it.
Here the user will enter and click save ..so when he goes back..I want the table to populated with what name he or she has entered.
So I wrote the below code for saving and find data:
- (void) saveData
{
coredata123AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
Contacts *newContact;
newContact = [NSEntityDescription
insertNewObjectForEntityForName:#"Contacts"
inManagedObjectContext:context];
[newContact setValue:name.text forKey:#"name"];
[newContact setValue:address.text forKey:#"address"];
[newContact setValue:phone.text forKey:#"phone"];
name.text = #"";
address.text = #"";
phone.text = #"";
NSError *error;
[context save:&error];
status.text = #"Contact saved";
}
- (void) findContact
{
coredata123AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
NSEntityDescription *entityDesc =
[NSEntityDescription entityForName:#"Contacts"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred =
[NSPredicate predicateWithFormat:#"(name = %#)",
name.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request
error:&error];
for(Contacts *info in objects)
{
NSLog(#"Name:%#",info.name);
NSLog(#"Address:%#",info.address);
}
if ([objects count] == 0) {
status.text = #"No matches";
} else {
matches = [objects objectAtIndex:0];
address.text = [matches valueForKey:#"address"];
phone.text = [matches valueForKey:#"phone"];
status.text = [NSString stringWithFormat:
#"%d matches found", [objects count]];
}
[request release];
}
And to populate the table view i have written this code..
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Contacts" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
self.contacts = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
Contacts *info =[contacts objectAtIndex:indexPath.row];
cell.textLabel.text =info.name;
cell.detailTextLabel.text=info.address;
// Configure the cell...
return cell;
}
Are you getting proper number of elements in this objects array?
NSArray *objects = [context executeFetchRequest:request
error:&error];
if not, try changing the predicate with,
[NSPredicate predicateWithFormat:#"name=%#", name.text];
Otherwise, your code seems correct to me.