Whenever I try to put NSData.dataWithContentsOfURL(), Xcode doesn't recognise it. The only one it recognizes is
NSData.dataWithContentsOfMappedFile(<#path: String#>)
Here's what it looks like:
When Swift imports interfaces from ObjC, it treats factory class methods that use Cocoa naming conventions into initializers.
In general, a class method on NSThing called thingWithNumber: turns into the initializer init(number:) and you call it with initializer syntax and the name of the class: NSThing(number: 42). In the case of classes that have both a thingWithNumber:-style class method and an initWithNumber:-style instance method that does the same thing, both map to the same Swift initializer.
In this case, dataWithContentsOfURL: and initWithContentsOfURL: become init?(contentsOfURL:). You can find these conversions and more by looking at the Swift interface for a class in Xcode (command-click the class name) or in the class documentation.
Related
I'm new to method swizzling and now I'd like to do a little more with that on iOS:
Is there an easy/elegant way in Objective-C to redirect all calls of an existing class (ClassA) to another class (ClassB, provided it has the exact same methods). I know it's possible to do so with a single method (method swizzling), but what about an entire class?
getting the list of all the class's methods and swizzling them one by one?
swizzling only the init method of the class?
any other way?
The class I want to replace has a lot of static methods and I don't want to touch the original code.
This question isn't about bridging headers and all that. I've got all that working. My question is specifically about what I need to do to my Swift classes to get them to show up in Obj-C code.
Take, for example, this simple class:
class MyClass {
var value: String = ""
}
If I have this class in my Project, it doesn't get included in the MyProject-Swift.h file that gets auto-generated. My understanding is that in order to use a Swift class in Objective-C, my class needs to derive from a class that Objective-C knows about. This is where I start to doubt the actual requirements.
If my class were derived from a UIViewController, then no problem. But if this is just a model object, then it's not deriving from anything. While it is entirely possible to easily make my class derive from NSObject, and thus, it gets properly imported into the Obj-C code, deriving from NSObject can cause other issues down the road.
So if I don't want to make my class derive from NSObject, what can I do to make it visible to my Obj-C files? Is there a doc I just couldn't find that explains how to do this?
As far as I am aware currently, Only Swift classes that inherit from NSObject can be declared #objc and bridged into an Objective-C project.
Without that conformance/inheritance, you'll end up missing some crucial functionality to Objective-C like message sending.
All of that being said, an Objective-C class has to inherit from a parent class and the default root class is NSObject. You almost definitely want to just inherit and make your class a PONSO.
I have one singleton class written in Objective C which is being used in helper class which is also written in Objective C. I am writing a test case for the helper class, but instead of making changes directly to singleton class methods, I want to create a mock singleton class, but I'm not sure how to do that. I don't want to make any changes in helper class either like creating a init method which takes singleton class object and initialise it like mention on other threads for test cases for singleton class.
Thanks for looking the question.
You can use OCMock for mocking objects in your project OCMock
Then you can mock your singleton like this
YOUR_SINGLETON *mock = OCMClassMock([YOUR_SINGLETON class]);
And stub function like this
OCMStub([(id) mock YOUR_FUNCTION:PARAMETER]).andReturn(VALUE_FOR_TEST_CASE);
When I declare static parameter in extension of class then I have to write #nonobjc before variable like:
#nonobjc static let test = "test"
and sometimes I have to write #objc before method, so what is use of #objc and #nonobjc in Swift.
Can anyone help me for this problem?
This is explained in the Apple's official documentation about Objective-C - Swift interoperability:
When you use the #objc(name) attribute on a Swift class, the class is
made available in Objective-C without any namespacing. As a result,
this attribute can also be useful when migrating an archivable
Objective-C class to Swift. Because archived objects store the name of
their class in the archive, you should use the #objc(name) attribute
to specify the same name as your Objective-C class so that older
archives can be unarchived by your new Swift class.
Conversely, Swift also provides the #nonobjc attribute, which makes a
Swift declaration unavailable in Objective-C. You can use it to
resolve circularity for bridging methods and to allow overloading of
methods for classes imported by Objective-C. If an Objective-C method
is overridden by a Swift method that cannot be represented in
Objective-C, such as by specifying a parameter to be a variable, that
method must be marked #nonobjc.
To summarize, use #objc when you want to expose a Swift attribute to Objective-C without a namespace . Use #nonobjc if you want to keep the attribute available and accessible only in Swift code.
(Addendum/additional official details to #bontoJR well summarizing answer)
From the Swift Language Reference - Attributes [emphasis mine]:
objc
Apply this attribute to any declaration that can be represented in
Objective-C — for example, non-nested classes, protocols, nongeneric
enumerations (constrained to integer raw-value types), properties and
methods (including getters and setters) of classes and protocols,
initializers, deinitializers, and subscripts. The objc attribute tells
the compiler that a declaration is available to use in Objective-C
code.
...
nonobjc
Apply this attribute to a method, property, subscript, or initializer
declaration to suppress an implicit objc attribute. The nonobjc
attribute tells the compiler to make the declaration unavailable in
Objective-C code, even though it is possible to represent it in
Objective-C.
...
Here you can find more details in this Swift Documentation : InteractingWithObjective-C
As an answer of your question, overview from attached link is as below.
#objc : You can use attribute to change the name of a class, property, method, enumeration type, or enumeration case declaration in
your interface as it’s exposed to Objective-C code.
Example : if the name of your Swift class contains a character that isn’t supported by Objective-C, you can provide an alternative name to use in Objective-C.
#nonobjc : It makes a swift declaration unavailable in Objective-C. You can use it to resolve circularity for bridging
methods and to allow overloading of methods for classes imported by
Objective-C.
I got a .framework file, and I use class-dump to know there is a class named ABC inside and don't expose anything, and ABC have a useful method for me, so I wonder know can I call ABC's method dynamic by Objective-C runtime.
Wait for your help!
To create an instance of class if by it's name use NSClassFromString:
Class myPrivateClass = NSClassFromString(#"MyPrivateClass");
myPrivateClass *myPrivateObj = [myPrivateClass new];
Now that you have the instance of the class call the select, to make it easier you can cast the instance to NSObject
[(NSObject *)myPrivateClass performSelector:#selector(description) withObject:nil];
Or the class method:
[myPrivateClass performSelector:#selector(description)];
Here I'm calling description on the instance and class.