I have an issue where in Swift I have a class defined named Person, and when talking to some objective-c code, it will try to create new instances of that class.
Obviously NSClassFromString(#"Person") fails, because it needs to be a fully qualified name such as DBAccess_Test.Person.
My question is, am I able to programatically generate the DBAccess_Test. portion, by possibly searching through a registry of classes perhaps?
The reason being, that for an ORM we maintain, a Swift programmer may well decide to have all of his storage classes within a separate namespace to the application. But we wish to maintain standard table naming practices that match the names of the class as understood by the developer.
For instance, instead of a query being:
NSArray* r = [[[[Person query]
where:#"surname IN (SELECT surname FROM Employees)"]
orderBy:#"forename"]
fetch];
it would become:
NSArray* r = [[[[Person query]
where:#"surname IN (SELECT surname FROM DBAccess_Test_Employees)"]
orderBy:#"forename"]
fetch];
The ORM already has a bit of an identity crisis. We just wish to keep in check the table names, with the class names that the programmer will use.
Thanks in advance foe your help.
Annoyingly, I stumble across the answer as soon as I post this (Despite searching for hours).
You must put #objc(SwiftClassName) above your swift class.
Like:
#objc(SubClass)
class SubClass: SuperClass {...}
Then all of your original Objective-c code will see these classes and not try to do anything funky with them!
Thanks to #klaus
Original post can be found here:
https://stackoverflow.com/a/24448786/846035
Related
I am writing a static library in Swift that will be reused in multiple projects. The problem is class and struct names I am using are common and can easily conflict with other libraries/frameworks. I don't see any obvious way to create my own namespace in Swift. What's the best way to avoid name collision between classes in multiple libraries/frameworks?
You don't to have to avoid. Just use the name you like. Then when you want to access to your class/struct/protocol..., just use your module name as a namespace.
Example:
import MyModule
let a: MyModule.Result // the Result type defined inside the `MyModule`
let b: Result // Swift's Result type
As others have said, if there is a conflict, you can always fully qualify the symbol name with the module name (See Cong's answer.)
Apple's suggested way to handle this in the days of Objective-C was to use your intials or your company's initials as a prefix for your symbol names. I'm not a big fan of that since it creates ugly names that obscure the underlying meaning.
Using an abbreviated version of the module name/framework name is a little better, and what Apple tends to do, e.g. UIKit views are UIViews, and AFNetworking's connection object might be an AFNConnection.
Others are arguing strongly in the comments that this is no longer needed and no longer recommended. (Like I said, I've never liked it anyway.)
I'm very new to the Grails framework, so please bear with me.
Nonetheless, I am a bit confused on the functionality difference between extending a domain class and embedding objects.
From a database point of view, they both do the same thing. When embedding an object, all the properties of all the classes are stored in one table. Similarily, when extending a class (using table-per-hierarchy), all the properties of all the classes are stored in one table.
I'm sure there is a functionality difference between these two, and so I figured I ask this question.
When do you use either one?
The only technical difference is the ability to have multiple tables through the table per subclass property when extending a class. Otherwise, they are identical in use.
However, that said, by extending another class you are also modeling that within the class structure so you can make use of instanceof and polymorphic features of Java/Groovy.
There are quite a few subjects on this already, but I have yet to find a solution that is workable for Swift (Xcode 6.2).
To test Core Data backed classes in Swift, I generate new Managed Object Contexts that I then inject into my classes.
//Given
let testManagedObjectContext = CoreDataTestComposer.setUpInMemoryManagedObjectContext()
let testItems = createFixtureData(testManagedObjectContext) as [TestItem]
self.itemDateCoordinator.managedObjectContext = testManagedObjectContext
//When
let data = self.itemDateCoordinator.do()
//Then
XCTAssert(data.exists)
The issue comes from passing a MOC created in the Test to the class that's doing. Because entity classes are namespaced, Core Data won't fetch your the appropriate ManagedObject subclass and instead hands back a NSManagedObject set. When looping or doing anything with these objects (which in your class would be an array of test items ([TestItem]).
For example, the offending class ItemDateCoordinator would execute this loop (after pulling the relevant data from a NSFetchRequest)"
for testItem in testItems {
testItem.doPart(numberOfDays: 10)
}
would result in:
fatal error: NSArray element failed to match the Swift Array Element type
Also, I have come across a collection of information without much of a solid answer:
To cast entities when creating them, I have been using a solution by Jesse, but that doesn't work on a larger scope of testing.
A solution has been posted on another question that involved swapping out the classes at runtime, but that hasn't worked for me with entity inheritance.
Is there another method to testing your objects with Core Data in this case? How do you do it?
I was about to point you toward Swift, Core Data, and unit testing but see you've already found it. :)
That post doesn't elaborate much on where your files should exist (i.e., in which Target). You should not add NSManagedObject subclasses (or any files really) to both targets. I've found that this leads to all kinds hard discover bugs and cryptic errors.
And definitely DO NOT do this. That is a terrible hack.
Instead, make your classes public and import MyAppTarget in your XCTestCase files. Better yet, your model should be in its own framework as I mention in my recent talk (a video will be posted in a few weeks on realm.io). Doing this makes your models namespace very clear and generally easier to deal with. Then you'll need to import MyAppModel everywhere you access your managed objects.
I also have a new framework, JSQCoreDataKit that intends to make Core Data easier to use in Swift. One key part of this framework is the CoreDataStack which you can initialize using an in-memory store for your tests. There's demo app with examples, and well-commented unit tests.
I believe this was updated recently (iOS 9/Swift 2.0) to have the testable keyword on an imported target, mean that the target's internal classes (the default) become public. From the docs:
So to add to jessesquires answer above, append #testable to your import, and this should solve the unit test errors:
#testable import MyAppTarget
Is it ok to create dependencies between categories in Objective C? Also between the categories and their base class?
I know that there should be no difference at runtime, they probably are just merged together at compile-time. For instance, let us say i break down my class B into:
B(base class)
B+categ1
B+categ2
B+categ3
My question is, is it wrong to either:
a) import B+categ2 and B+categ3 in B.m
b) import B+categ1 in B+categ3?
I'm asking both performance-wise and conceptually.
EDIT:
What would you suggest for a single screen app? Categories or Extending that class?
There's nothing deeply wrong with it, but it may suggest an overuse of categories. While they are a powerful tool for certain problems, and definitely can create some conveniences, I generally wouldn't build a complex system on them.
I usually find that overuse of categories is based on too much IS-A thinking rather than HAS-A thinking. In other words, if you're putting a lot of categories on an class to act as a fancy kind of subclassing, you may be better off using composition instead. Rather than adding lots of category methods to NSArray (as an example), you would want an data object that has an NSArray property and provides the interface you want.
But this is just advice if you're overusing categories. There's no fundamental problem with having categories import other categories. However, this claim is incorrect:
I know that there should be no difference at runtime, they probably are just merged together at compile-time.
Categories are resolved at runtime, not compile-time. The one major danger of that is that if two categories implement the same method, then the behavior is undefined. This is why you should never use categories to override methods, only to add them.
Avoid having a base class depend on a category of itself. Exceptions to this rule are made for private categories (use extensions instead) and categories intended to be used by subclasses of the base class. These are specialized exceptions and should not be thought of as a proper general purpose solution.
For categories depending on categories, if you make sure the dependency graph never has a cycle, then you should be fine.
As a final bit of advice, be explicit about dependencies.
// A+c2
#import "A+c1.h" // A(c2) relies on A(c1) declared methods/properties.
…
// A+c3
#import "A+c1.h" // A(c3) relies on A(c1) declared methods/properties.
#import "A+c2.h" // A(c3) relies on A(c2) declared methods/properties.
Even though A(c3) is implicitly including A(c1) by importing "A+c2.h", I still explicitly import it. This will save frustration as code changes in the future.
I'm new in Db4o
As far as I checked, when I do a refactoring of a class name or path (packages),
db4o doesnt recognizes the class anymore and creates a new 'category'.
I want to make an API, so that any class refactoring in my app won't affect the database.
I've created the following function ...
public void saveClassAs(Class objClass, String nameInDB){
configuration.common().objectClass(objClass).rename(nameInDB);
}
and have it called for each of my classes. Since the nameInDB will be constant for each class, no matter where the class is located or its name.
The problem is that Im not sure if will this work and I don't know if this is a good idea in matters of speed ... I didn't find any details on db4o documentation about how the renaming API works. Any help?
If you want to use constant class names (irrespective to the real classes names) my best bet is to use aliases.
Regarding renaming configuration you can find details here.