I have been trying to use NSSet and NSMutable set to compare a set of numbers using the IntersectSet function. However, I believe I m going against type by using integers. Is there a way to create an NSSet and use the IntersectsSet function for integers. Is there another way of accomplishing this altogether?
Here is a code snippet:
NSSmutableArray *compareRow [[NSMutableArray alloc] init];
NSSet *A_Table = [[NSSet alloc] initWithObjects:#"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", #"9", #"10", #"11", #"12",nil];
//...
//Reading some data from a file.
//Populate the tables with the third arrays
[currentHistoryRow addObject:[NSNumber numberWithInt:post1]];
[currentHistoryRow addObject:[NSNumber numberWithInt:post2]];
[currentHistoryRow addObject:[NSNumber numberWithInt:post3]];
[currentHistoryRow addObject:[NSNumber numberWithInt:post4]];
[currentHistoryRow addObject:[NSNumber numberWithInt:post5]];
NSSet *compareRow = [[NSSet alloc] initWithArray:currentHistoryRow];
if ([compareRow intersectsSet:A_Table]) {
// You'll see this message
NSLog(#"subset present");
}
I figure A_Table and compareRow are not of the same type so the condition is never true.
Wrap the integers in NSNumber and then add them to an NSSet. Intersection will work as advertised.
NSSet *set = [NSSet setWithObjects: #10, #20, nil];
// etc.
Related
I tried to add object to my mutable array using TFHlle parse html in this code but it return null for object in my array, but in the for loop, I log the result of '[element objectForKey:#"title"]' and it returns result I want.
How I can add the result of element [objectForKey:#"title"] to my array?
TFHpple *htmlParseResult = [TFHpple hppleWithHTMLData:self.responseData];
NSString *coursesXpathQueryString = #"//h2[#class='main']/a";
NSArray *coursesNodes = [htmlParseResult searchWithXPathQuery:coursesXpathQueryString];
NSMutableArray *fitCourse = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in coursesNodes) {
[fitCourse addObject:[element objectForKey:#"title"]];
}
I think
NSArray *coursesNodes = [htmlParseResult searchWithXPathQuery:coursesXpathQueryString];
should be change to:
NSArray *coursesNodes = [NSArray arrayWithArray:[htmlParseResult searchWithXPathQuery:coursesXpathQueryString]];
I am not sure this works but you can try.
I have an entity called Rounds that has basic data about golf rounds. I am trying to calculate the number of rounds as well as the average score. However, every time I try and calculate these values it returns 0 (zero). There are no errors, and no crashes.
I have the following function in Rounds.m:
+(NSNumber *)aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate inManagedObjectContext:(NSManagedObjectContext *)context
{
NSExpression *ex = [NSExpression expressionForFunction:function
arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:attributeName]]];
NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
[ed setName:#"result"];
[ed setExpression:ex];
[ed setExpressionResultType:NSInteger64AttributeType];
NSArray *properties = [NSArray arrayWithObject:ed];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setPropertiesToFetch:properties];
[request setResultType:NSDictionaryResultType];
if (predicate != nil)
[request setPredicate:predicate];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Rounds"
inManagedObjectContext:context];
[request setEntity:entity];
NSArray *results = [context executeFetchRequest:request error:nil];
NSDictionary *resultsDictionary = [results objectAtIndex:0];
NSNumber *resultValue = [resultsDictionary objectForKey:#"result"];
return resultValue;
}
I then call this method from my view controller to set the values of the labels for number of rounds and scoring average:
-(NSNumber*) scoringAverageCalc
{
NSNumber *scoreAverage = [Rounds aggregateOperation:#"average:" onAttribute:#"roundScore" withPredicate:nil inManagedObjectContext:_managedObjectContext];
return scoreAverage;
}
-(NSNumber*)countOfRounds
{
NSNumber *roundCount = [Rounds aggregateOperation:#"count:" onAttribute:#"roundDate" withPredicate:nil inManagedObjectContext:_managedObjectContext];
return roundCount;
}
Can someone please tell me why I am not getting the correct value?
I think NSExpression is overkill for simple sums. I would do it like this: fetch your rounds as normal managed objects (NSManagedObjectResultType) and then use KVC which should have just the aggregators you need.
NSNumber *sum = [rounds valueForKeyPath:#"#sum.score"];
NSNumber *avg = [rounds valueForKeyPath:#"#avg.score"];
Simple, isn't it? Check it out here.
Your code works for me. Are you sure there are no misspellings in your entity or attribute names?
I need to use some core data managed objects in an NSOperation. The problem is that core data is not thread safe and apparently the object can't be loaded from the new thread. Does anybody know a good tutorial for this? I need the object read only... so the thread will not modify them in any way. Some other, unrelated entities may be added on the main thread while these objects are used in the background, but the background entities don't need to be modified at all..
Hmm seemed I fixed the background running issue, but now the problem is nothing is returned to the delegate... Why? In the thred if I nslog the results are all shown but that call to the delegate never happens
This is the code:
-(void)evaluateFormula:(Formula *)frm runNo:(NSUInteger)runCount{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:2];
NSManagedObjectID *formulaId = frm.objectID;
for (int i = 0; i < runCount; i++) {
NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(runFormula:) object:formulaId];
[queue addOperation:op];
}
}
-(void)runFormula:(NSManagedObjectID *)fId {
NSManagedObjectContext *thredContext =[[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *coord = (NSPersistentStoreCoordinator *)[(PSAppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
[thredContext setPersistentStoreCoordinator:coord];
Formula *f = (Formula *)[thredContext objectWithID:fId];
NSDictionary *vars = [self evaluateVariables:[f.hasVariables allObjects]];
NSMutableString *formula = [NSMutableString stringWithString:f.formula];
for (NSString *var in [vars allKeys]) {
NSNumber *value =[vars objectForKey:var];
[formula replaceOccurrencesOfString:var withString:[value stringValue] options:NSCaseInsensitiveSearch range:NSMakeRange(0, [formula length])];
}
//parse formula
NSNumber *result = [formula numberByEvaluatingString];
// NSLog(#" formula %# result : %d",formula,[result intValue]);
//aggregate results
[self performSelectorOnMainThread:#selector(aggregate:) withObject:result waitUntilDone:YES]; // the delegate doesn't get called ...
}
-(void)aggregate:(NSNumber *)res {
[self.delegate didReceiveResult:res];
}
This one has been a big problem for me, and i´m still stuck with it so i was hopping that someone could give me some kind of guidance.
What i have is:
3 tableviews with multiple cells and each cell with several textfields.
1 tableview that appears inside a popover every time a specific textfield on those cells is pressed. This tableview has all!! the core data methods to retrieve the necessary data from my database.
Everything works ok...but i need to distinguish what kind of data shall appear in tableview 1 or 2 or 3...So i know i have to use predicate!.
What i have done: ( and i have tried other things)
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController == nil)
{
NSFetchRequest *fetchRequestList = [[NSFetchRequest alloc] init];
NSEntityDescription *entityList = [NSEntityDescription entityForName:#"List" inManagedObjectContext:self.managedObjectContext];
[fetchRequestLista setEntity:entityList];
TableViewOne *table1 = [[Cobertura alloc]init];
TableViewTwo *table2 = [[Cobertura alloc]init];
if (table1 textFieldShouldBeginEditing:table1.textFieldPressed)
{
fetchRequestList.predicate = [NSPredicate predicateWithFormat:#"%K IN %#", #"reference", arrayTableview1];
}
if (table2 textFieldShouldBeginEditing:table2.textFieldPressed)
{
fetchRequestList.predicate = [NSPredicate predicateWithFormat:#"%K IN %#", #"reference", arrayTableview2];
}
NSSortDescriptor *cellTitle = [[NSSortDescriptor alloc] initWithKey:#"reference" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:cellTitle, nil];
[fetchRequestLista setSortDescriptors:sortDescriptors];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequestLista managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"referencia" cacheName:nil];
_fetchedResultsController.delegate = self;
self.fetchedResultsController = _fetchedResultsController;
return _fetchedResultsController;
}
In each of my tableviews, i have an instance of the "popoverTableview" in my method textFieldShouldBeginEditing:
popoverTableview = [self.storyboard instantiateViewControllerWithIdentifier:#"popoverTableview"];
popover = [[UIPopoverController alloc] initWithContentViewController:popoverTableview];
[popover presentPopoverFromRect:textField.bounds inView:textField permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
popoverTableview.delegate = self;
popoverTableview.popView = self.popover;
So, if i´m in tableview1 i need to get [NSPredicate predicateWithFormat:#"%K IN %#", #"reference", arrayTableview1];
Should i be creating some kind of method that my tableviewS could access? What am i forgetting here or not paying attention?
Thanks in advance, and any kind of advise would be welcome!
Regards
For everyone that was experiencing the same problem that i was, here is what i have done to resolve:
This is when i´m creating the popoverview when a specific textfield is pressed:
popoverTableview = [self.storyboard instantiateViewControllerWithIdentifier:#"popoverTableview"]initWithTextFieldTag:myTextFieldThatWasPressed.tag]
popover = [[UIPopoverController alloc] initWithContentViewController:popoverTableview];
[popover presentPopoverFromRect:textField.bounds inView:textField permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
popoverTableview.delegate = self;
popoverTableview.popView = self.popover;
popoverTableview.aIntVariable = myTextFieldThatWasPressed;
then in my popovertableview:
- (id)initWithTextFieldTag:(int)textFieldTag
{
self.aIntVariable = textFieldTag;
return self;
}
Then in the fetchedResultsController method, you´ll just have to create simple if´s telling wich predicate you want...
Regards
If the fetched results controller is for the popover table and you need to know in which table the text field was selected, I'd recommend tagging each of the text fields when you create them and creating an int _currentTable instance variable. That way, when your textFieldShouldBeginEditing: method is called, you can set the ivar's value with the tag and check that tag when creating the fetched results controller for the popover table.
So, instead of
if (table1 textFieldShouldBeginEditing:table1.textFieldPressed)
{
fetchRequestList.predicate = [NSPredicate predicateWithFormat:#"%K IN %#", #"reference", arrayTableview1];
}
if (table2 textFieldShouldBeginEditing:table2.textFieldPressed)
{
fetchRequestList.predicate = [NSPredicate predicateWithFormat:#"%K IN %#", #"reference", arrayTableview2];
}
you'll have
if (_currentTable == 1) {
fetchRequestList.predicate = // table one predicate
} else if (_currentTable == 2) {
fetchRequestList.predicate = // table two predicate
}
UPDATE:
This is how I would override the init from code. In your popover table view controller implementation:
- (id)initWithTableTag:(int)tableTag
{
self = [super init];
if (self) {
_currentTable = tableTag;
}
return self;
}
(Make sure you also declare - (id)initWithTableTag:(int)tableTag; in your header.) Then, when you create and present the popover controller (which I'm assuming you're doing in the textFieldShouldBeginEditing: delegate call):
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// ...
YourPopoverTableViewControllerClass *vc = [[YourPopoverTableViewControllerClass alloc] initWithTableTag:textField.tag];
// ...
// display the popover
return YES;
}
Unfortunately, I don't know how to do this using storyboards.
How would you implement the following instance method for NSSet:
- (BOOL)containsMemberOfClass:(Class)aClass
Here's why I want to know:
Core Data model:
How do I add a Facebook authorization to a user's authorizations NSSet, but only if one doesn't already exist. In other words, a user can have many authorizations (in case I choose to add a Twitter (e.g.) authorization in the future) but should only have one of each kind of authorization. So, if (![myUser.authorizations containsMemberOfClass:[Facebook class]]), then add a Facebook authorization instance to myUser.
Unfortunately, you have to loop through all of the authorizations and check:
#interface NSSet (ContainsAdditions)
- (BOOL)containsKindOfClass:(Class)class;
- (BOOL)containsMemberOfClass:(Class)class;
#end
#implementation NSSet (ContainsAdditions)
- (BOOL)containsKindOfClass:(Class)class {
for (id element in self) {
if ([element isKindOfClass:class])
return YES;
}
return NO;
}
- (BOOL)containsMemberOfClass:(Class)class {
for (id element in self) {
if ([element isMemberOfClass:class])
return YES;
}
return NO;
}
#end
With Core Data it is actually best practice to use an NSFetchRequest with an NSPredicate. To do that you would have to add an attribute to your Authorization object, something like authorizationType. You could then do the following:
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY user.authorizations.authorizationType == %#", #"facebook"];
[request setEntity:[NSEntityDescription entityForName:#"Authorization" inManagedObjectContext:moc]];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *result = [moc executeFetchRequest:request error:&error];
You can then check the count of result to see if it exists or not. Using NSPredicate allows you to use any optimizations Apple has added around CoreData. Here are the Apple Docs.
What if you add this instance method to the User class?
- (BOOL)hasFacebookAuthorization {
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"user.id == %#", [self id]];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"Facebook"
inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:predicate];
NSError *error;
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (!result) {
// TODO: Handle the error appropriately.
NSLog(#"hasFacebookAuthorization error %#, %#", error, [error userInfo]);
}
return [result count] > 0;
}
Your going about this the wrong way. If the types of authorization are something common and important then you should model that in your data model directly instead of trying to impose that structure in external controller code.
If you have a fixed set of authorizations then you should create an entity to model those authorizations.
Facebook{
accessToken:string
experationDate:date
authorization<-->Authorizations.facebook
}
Google{
username:string
password:string
authorization<-->Authorizations.google
}
Authorizations{
user<-->User.authorizations
facebook<-->Facebook.authorization
google<-->Google.authorization
}
Now you have all your authorizations captured in the data model where they belong. To tighten things up more. You could add a custom method to the User class to control adding and removing authorizations.
The key idea here is that all the logic that manages data should be encapsulated in the data model to the greatest extent possible. This allows you to (1) test all data operations independent of the interface and (2) easily add and remove interface elements without breaking the data model.
Old question, but slightly different answer:
NSPredicate *objectTypeFilter = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject isKindOfClass:NSClassFromString(#"MyObject")];
}];
NSSet *myObjects =[allObjects filteredSetUsingPredicate:objectTypeFilter];
if (myObjects.count>0) {
// There was at least one object of class MyObject in the allObjects set
}