Something weird is going on with NSManagedObject.description() it prints nothing but a blank line.
import Foundation
import CoreData
#objc(MyEntity)
class MyEntity: NSManagedObject {
#NSManaged var title: String
}
Then I create an Object and set its title. When I call println("\(myObject)") it will print a blank line instead of <xSomEtHinG : MyEntity>
(the object es creates and persists ok. println("\(myObject.title)") works like expected)
Any ideas?
You can create Extension and override description property as you want.
extension MyEntity {
override public var description: String {
return "Title= \(title)"
}
}
Related
I'm new to Swift and I'm trying to learn how to use Core Data. But I'm getting this error and I'm not sure what I've done wrong. I've searched online and tried a few things but I can't get it right.
Failed to call designated initializer on NSManagedObject class 'FirstCoreData.Course'
When this line executes:
ncvc.currentCourse = newCourse
In this function:
class TableViewController: UITableViewController, AddCourseViewControllerDelegate {
var managedObjectContext = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "addCourse" {
let ncvc = segue.destinationViewController as! NewCourseViewController
ncvc.delegate = self
let newCourse = NSEntityDescription.insertNewObjectForEntityForName("Course", inManagedObjectContext: self.managedObjectContext) as! Course
ncvc.currentCourse = newCourse
}
}
Class generated by "Create NSManagedObject Subclass..." for Course entity:
import Foundation
import CoreData
class Course: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
}
And:
import Foundation
import CoreData
extension Course {
#NSManaged var title: String?
#NSManaged var author: String?
#NSManaged var releaseDate: NSDate?
}
The problem lies not in the code in your question, but in the snippet you included as comments to the other answer:
var currentCourse = Course()
This doesn't just declare currentCourse to be of type Course, it also creates an instance of the Course entity using the standard init method. This is expressly not allowed: You must use the designated initialiser: init(entity entity: NSEntityDescription,
insertIntoManagedObjectContext context: NSManagedObjectContext?). This is described in the Apple Documentation here.
I suspect you do not ever use the instance created by the above var definition, so just define it as being of type Course?:
var currentCourse : Course?
Since it is optional, you do not need to set an initial value, though you will need to unwrap the value whenever it is used.
The simplest way is this:
Define in the applicationDelegate a reference for the context
Instantiate the variable by passing the context
In the AppDelegate (outside the brackets):
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
And in the code:
let currentCourse = Course(context:context)
Now you have your entity created. But don't forget to save with:
appDelegate.saveContext()
I had the same issue. And instantiating the object like this worked, for your course it would be something like this:
var currentCourse = Course.init(entity: NSEntityDescription.entityForName("Course", inManagedObjectContext:mox)!, insertIntoManagedObjectContext: mox)
instead of:
var currentCourse = Course()
I used this in Xcode 8.3.2 with Swift 3.1.
NSEntityDescription.insertNewObject(forEntityName: String(describing: type(of: Record())), into: managedObjectContext) as! Record
And got the same error message. But this data was inserted into db. So maybe this doesn't matter.
Your currentCourse should be NSManagedObject class
Please refer this CoreData: error: Failed to call designated initializer on NSManagedObject class
I am using Swift in Core Data generated subclass of NSManagedObject. There is a transient optional property title.(The optional is not Swift's optional, but Core Data's optional.)
So I need a custom getter. My code is
class ShoppingList: NSManagedObject {
#NSManaged var title: String
func title() -> String {
return "something"
}
}
The Objective-C version of the getter works fine. However, Xcode tells me that "the func title() is an invalid redeclaration". I tried to use computed property, but get that "#Managed property can not use computed property".
So my question is, is there an alternative way to get custom accessors(getters) in Swift version of NSManagedObject subclassing?
You could use a different name for a computed property, and have it return the title variable.
#NSManaged var title: String
var myTitle : String {
return self.title
}
Would that work for you?
Apple does it like this in many places by naming the actual var with an underscore in front, and the computed property with the same name but without the underscore
From the documentation of a bound API I'm using:
overrideClassNames
Use this to use specific subclasses instead of the default PSPDF*
classes. e.g. add an entry of [PSPDFAnnotationParser class] /
[MyCustomAnnotationParser class] as key/value pair to use the custom
subclass. (MyCustomAnnotationParser must be a subclass of
PSPDFAnnotationParser) Throws an exception if the overriding class is
not a subclass of the overridden class. Note: does not get serialized
when saved to disk.
#property (nonatomic, strong) NSDictionary *overrideClassNames
Here's what I tried but doesn't work. Appearently not strings are required but actual types or something. How can I use this in MonoTouch?
var oClassDic = new NSMutableDictionary();
oClassDic.Add(new NSString("[PSPDFAnnotationParser class]"), new NSString("[PSPDFKitAnnotationParser class]"));
oDoc.OverrideClassNames = oClassDic;
The PSPDFKitAnnotationParser I created like this:
[Register("PSPDFKitAnnotationParser")]
public class PSPDFKitAnnotationParser : PSPDFAnnotationParser
{
public PSPDFKitAnnotationParser () : base()
{
}
public PSPDFKitAnnotationParser (PSPDFDocumentProvider provider) : base(provider)
{
}
public PSPDFKitAnnotationParser (IntPtr handle) : base(handle)
{
}
public PSPDFKitAnnotationParser (NSObjectFlag t) : base(t)
{
}
public PSPDFKitAnnotationParser (NSCoder coder) : base(coder)
{
}
MonoTouch's own bindings generally hides the class and replace them with, the more .NETy, System.Type.
However the MonoTouch.ObjCRuntime.Class type exists and can also be used. If the native code expects class instances then you should be able to do something like:
var oClassDic = new NSMutableDictionary();
oClassDic.Add(new Class("PSPDFAnnotationParser"), new Class("PSPDFKitAnnotationParser"));
oDoc.OverrideClassNames = oClassDic;
You might have to tweak this a bit since a Class instance is not an NSObject, it's a NativeObject in MonoTouch, so you might have to go one level deeper and use the Handle properties (IntPtr) when adding values/keys to your dictionary.
Following #poupou answer this might work, I have not tested it this is what you have to do, It Works (TM)
var oClassDic = new NSMutableDictionary();
var key = new Class("PSPDFAnnotationParser");
var val = new Class("PSPDFKitAnnotationParser");
IntPtr selSetObjectForKey = Selector.GetHandle ("setObject:forKey:");
Messaging.void_objc_msgSend_IntPtr_IntPtr (oClassDic.Handle, selSetObjectForKey, val.Handle, key.Handle);
oDoc.OverrideClassNames = oClassDic;
Selector setObject: forKey: expects an ObjC id type on both params
"id" its just a special type that can hold a pointer to any object you can construct with ObjC
So this should work :)
Hope this helps
Alex
I have subclassed a ViewController that was created via XCode Interface Builder. my subclass is defined like so
public MyViewControllerGeneric<T> : MyViewController{
public MyViewControllerGeneric(IntPtr handle) : base(handle){}
}
I can use Storyboard.InstantiateViewController("MyViewController") to get an instance of MyViewController. However how do I create an instance of MyViewControllerGeneric and pass a handle to it?
Tried
var vc = new MyViewControllerGeneric<MyType>(this.Handle)
var vc = new MyViewControllerGeneric<MyType>(new IntPtr(DateTime.Now.Ticks)
both throw a SigAbort
Any Help highly appreciated.
The IntPtr handle is not something you should be passing in.
Use this constructor instead:
public MyViewControllerGeneric<T> : MyViewController{
public MyViewControllerGeneric() : base(){ }
}
Or this if you need a NIB loaded, depending on your base class:
public MyViewControllerGeneric<T> : MyViewController{
public MyViewControllerGeneric() : base("MyViewControllerGeneric", null){ }
}
I'm tying to collect all Custom Attributes placed over a Property. There are more than one Attributes of the same type assigned to the Property, but when collecting them , the resulting collection only contains the first Attribute of the specific type:
The Attribute class
[AttributeUsage(System.AttributeTargets.Property,
AllowMultiple = true)]
public class ConditionAttribute : Attribute{...}
Usage:
[ConditionAttribute("Test1")]
[ConditionAttribute("Test2")]
[ConditionAttribute("Test3")]
public Color BackColor{get; set;}
Now when looping through all Props of the object 'value' whose class contains the Prop "BackColor":
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value))
{
foreach (Attribute attribute in property.Attributes)
{ ... }
....
}
the collection property.Attributes only contains ONE Attribute of type "ConditionAttribute" : The one with "Test1". The others are ignored;-(
So does AllowMultiple not work for Property Attributes ?
Thanks in advance
henrik
According to a post on MSDN, this is by design as part of the PropertyDescriptor class.
However, you can actually solve the problem by overriding TypeId in your custom attribute (Thanks to Ivan from Mindscape for pointing this out):
public override object TypeId
{
get
{
return this;
}
}
Yes, it does work. Not sure why it does not work via PropertyDescriptors.
You can always do: Attribute.GetCustomAttributes(methodInfo, typeof(ConditionAttribute))
Another way to tweak this,
[ConditionAttribute("Test1,Test2,Test3")]
public Color BackColor{get; set;}
and in your validation code,
Dim lstProperties() As String = _ChkColors.Split(",")
For each strProp as string in lstPropertyes
' your validation
' return
Next