i create a subclass of managedObject from the core data file.its created a new class name Books.
i make in the code property book to the Book class and write that code:
_book.name = title.text;
but the name property is not assign and show me null value when i'm trying
NSlog(#" %#", _book.name)
what could be the problem??????
Related
I have data recorded in the attributes of a entities in coredata.
I would like to erase the data saved in each attribute of an entity.
Please is there a way to do it and if so, how?
Thank you
Get the NSEntityDescription of that object (that's the entity property of the NSManagedObject).
And then you can simply iterate on the names (via the attributesByName property) and set all values to nil
for (name, attributes) in entity.attributesByName { setValue(nil, forKey: name) }
You can do the same for the relationships of that object (via the relationshipsByName property)
for (name, relationship) in entity.relationshipsByName { setValue(nil, forKey: name) }
With this methods you can also exclude specific properties (if there are some you don't want to clear).
public class ABC
{
}
public class DEF : ABC
{
}
public class Class1
{
ABC abc = new DEF(); //No error
DEF def = new ABC(); //Compile time error
}
Can anyone explain to me this scenario.
and under what circumstances we might use it.
Its because as per the OOD rule you can assign child to parent but you cannot assign parent to child.
//this possible as you re assigning child to parent
ABC abc = new DEF(); //No error
//this is illegal as you are trying to assign child to parent directly
DEF def = new ABC(); //Compile time error
Reconsider your design again or if you want to convert parent object to child than you need method for that conversion directly its not possible to do it as per OOD rules.
Consider real time example relation of Customer and RetailCustomer or Corporatecustomer of bank. Where you can easily say RetailCustomer or CorporateCustomer is Customer, but you cannot say Customer is RetailCustomer or CorporateCustomer because customer can be of any type.
Same goes for relation between Parent Shape Class and Child Rectangle,Circle etc. class.
This is called as Ploymorphism .
As explained in MSDN
At run time, objects of a derived class may be treated as objects of a
base class in places such as method parameters and collections or
arrays. When this occurs, the object's declared type is no longer
identical to its run-time type.
Base classes may define and implement virtual methods, and derived
classes can override them, which means they provide their own
definition and implementation. At run-time, when client code calls the
method, the CLR looks up the run-time type of the object, and invokes
that override of the virtual method. Thus in your source code you can
call a method on a base class, and cause a derived class's version of
the method to be executed.
The answer of for this question is best explained here MSDN Polymorphism
Let's say ABC is Person, while DEF is Student (which is a subclass of Person). You can always treat a Student as a Person, so the assignment to abc (of type Person) of a Student is correct, but you cannot treat a generic Person as Student, so the assignment to def is wrong (for instance, you cannot get the student number of a person which is not a student)
I am preloading data on an app's first launch into Core Data, need to point to objects yet to be instantiated and can't figure out how to do this. I saw a similar question, though the solution isn't applicable in this situation.
Say I have 3 classes
class Person {
var nationOfBirth: Nation
...
}
class City {
var mayor: Person
...
}
class Nation {
var capitalCity: City
...
}
If i am loading an initial data set of nations, then cities, then people (or any other order) then no matter which order I load them in I will need to set instances yet to be instantiated (though I know they will be) and I'm struggling to figure out how to do this and will appreciate any help
One of this fields must be optional, because in your example you have cycle references. Also Optional field in this case must have week reference for another field to clear memory correctly in the end. Your code:
class Person {
var nationOfBirth: Nation
init(nation: Nation) {
nationOfBirth = nation
}
}
class City {
var mayor: Person
init(person: Person) {
mayor = person
}
}
class Nation {
weak var capitalCity: City?
}
//initialization
let nation = Nation()
let person = Person(nation: nation)
let city = City(person: person)
nation.capitalCity = city
In swift if you are declaring field in class without default initialisation you must initialise it in constructor(init). In your case you have 3 classes, each with one field of another class without default initialisation. So you need to initialise then in init method.
To initialise Person you need object of Nation, to initialise Nation you need object of City, to initialise City you need object of Nation, and again you need object of Person, than City, than Nation. As you you see it is infinity loop.
To solve this problem you need to break this loop. You can do it only with setting field of One class as optional (with ? in the end of type). After that you don't need to initialise that field in initialiser, because now it can contain nil(nothing).
If you don't need to initialise it in initialiser, you can now create member of class with optional field without object of another class and just set it in the end. In my code you can see, that City field in Nation is set as optional, so i can create member of Nation without initial City value(let nation = Nation()).
After that, as i have member of class Nation, i can create Person with initialiser that takes Nation object(let person = Person(nation: nation)).
In the same way as now we have created member of person we can create member of city(let city = City(person: person)).
In the end we have member of city, so we can set it to nation object, that was created at the beginning without city(nation.capitalCity = city).
About why we need weak reference in this case you can read hear - https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_92
Today I've faced a very strange behavior of NSFetchedResultsController which I use to fill UITableView with Core Data records.
I have two entities in Core Data model: Parent and Child. Each entity has Int16 attribute typeNumber and string attribute name. Parent has to-many relationship to Child called children.
NSFetchRequest for NSFetchedResultsController selects Child entities sorted by name with predicate [NSPredicate predicateWithFormat:#"parent.typeNumber == 1"]. Looks very simple.
Before NSFetchedResultsController performs fetch there is a following structure in CoreData: one Parent with typeNumber = 1 named parent1 with two children: child1 (name) with typeNumber = 1 and child2 with typeNumber = 2. So right after performFetch it shows those two child1 and `child2. So far so good.
But then following action is triggered: new Parent object is added to the same NSManagedObjectContext with typeNumber = 1 named parent2 and with two children: child3 with typeNumber = 1 and child4 with typeNumber = 2. This fires controller: didChangeObject: atIndexPath: forChangeType: newIndexPath: selector of NSFetchedResultsControllerDelegate protocol two times. Now I see all 4 children in UITableView. Ok.
Then I change parent1.typeNumber to 2 with following code: parent1.typeNumber = [NSNumber numberWithInt:2];. But no NSFetchedResultsControllerDelegateselectors are fired! How's that? Now child1 and child2 won't match NSFetchedResultsController fetchRequest, right? Why NSFetchedResultsController did not react on that? I thought it somehow knows when properties of NSManagedObject subclasses that used by CoreData are changed.
You can only use the access form e.g.
parent1.typeNumber = [NSNumber numberWithInt:2];
... if you have created a custom Parent subclass of NSManagedObject and instantiated the parent1 object as that subclass. Otherwise, the parent1 is just a generic NSManagedObject and you have to make a change with key-value coding:
[parent1 setValue:[NSNumber numberWithInt:2] forKey:#"typeNumber];
If you don't use the proper access form, the changes are actually never made so the controller never sends its delegate the change messages.
As per the title really. I have an entity which has a property "idNumber". Just as I can bind a text box to the array controller's arrangedObjects with Model Key Path "#count" to provide a count of all the objects in the array, I would like to be able to bind a text field to the array controller's arrangedObjects with a value transformer to return a count of a filtered subset of the array (those objects with an idNumber >5).
I'm assuming this is possible??
My attempt is:
I have bound the text box to the array controller, Controller Key "arrangedObjects" Model Key Path "" Value Transformer "AllToSomeTransformer".
The code for the AllToSomeTransformer is:
-(id)transformedValue:(id)value {
NSArray *arrayOfAllCars;
if (value == nil) return nil;
if ([value respondsToSelector: #selector(count)]) {
arrayOfAllCars = [NSArray arrayWithArray:value];
} else {
[NSException raise: NSInternalInconsistencyException
format: #"Value (%#) does not respond to -count.",
[value class]];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"idNumber > %#", [NSNumber numberWithInt:5]];
NSArray *arrayOfBlueCars = [arrayOfAllCars filteredArrayUsingPredicate:predicate];
return [NSNumber numberWithInt:[arrayOfBlueCars count]];
}
I believe my value transformer is correctly registered etc. By way of trying to figure out what's going on I added some NSLog outputs through to above code. It appears the above method is only called once, on app startup, and not again when new objects are added to the array. Could this be why the text field is not being updated with values??
Thanks, Oli
Since the transformer is called and does work but only once, that suggest there is something wrong with the bindings such that the transformer is not observing the changes in arrangedObjects. I'm not sure what that would be.