Swift init with closures is not visible in Objective C - objective-c

My swift custom initilizer with closure is not visible in the objective c code.
init(url:String,request:ABaseRequest,
type:AnyClass, success:(ABaseResponse)->Void,
failure:(ResponseCode,NSError)->Void) {
......
......
}
where as init without closure is visible
init(url:String,request:ABaseRequest,type:AnyClass) {
......
......
}
Do you guys know how to solve this issue?

After inspecting whole code I found the problem in my code. A class used inside my closure is not annotated with #objc ! . So be careful guys, each and every classes that is going to be exposed to objective c should be annotated with #objc. Thanks.

By now you may have already solved the problem. I've run into a similar one myself.
Unless there are other problems, the visibility issue can be fixed by trying to build the project. If you introduce something new in your Swift code, it may not be immediately visible to Objective-C code, but building the project should fix it.
If there is another problem related to your custom initializer, the compiler will tell you when you try to build. If that is the case, share the problem here.

Related

Intellisense - deduce right Class by its methods

I'm used to work with NetBeans and now I'm trying IntelliJ. So my question is: Does IntelliJ has a way to get right class by its methods?
For example, in NetBeans if I write:
glGenBu // Intellisense will kick in and will suggest me
to use GL15.glGenBuffers() method from GL15 class
This will automatically import the right library.
This is very handy because I'm working with LWJGL and it has a bad way to manage OpenGL methods ('GLXX' where XX is the version of OpenGL and all methods that appeared in that version are stored in that class) and I never remember the right class where my desired method is.
Thank you.
Pressing Ctrl+Space when you already see completion list will show more suggestions, with static methods from the entire project among them. See https://www.jetbrains.com/help/idea/auto-completing-code.html for more details.

Changing the implementation of Objective C method in Swift subclass

I am using an external library in my project. It is integrated via CocoaPods. I have access to the source code. The library is working well, but I need some modifications at some places in order for it to serve my purposes. It is written in Objective C. My project is in Swift.
I need to change the implementation of one method in the library. The problem is it is in the .m file and uses a lot of stuff declared only in the .m file. For example:
-(NSString*)methodToChange
{
NSArray<NSNumber*>* data = [self someInternalMethod:1];
uint value = data[0].unsignedIntValue;
return [self anotherInternalMethod:value];
}
I tried subclassing it like this:
class MySubclass : MySuperclassWithMethodToChange {
override var methodToChange: String {
//trying to use someInternalMethod and anotherInternalMethod
//unsuccessfully because they are not visible
}
}
The internal methods are using and modifying properties from the .m file that are also not accessible. Is there any way to solve this?
I would suggest forking the original library repository and making the necessary changes in your fork. You can then have your Podfile point to that. If your changes could be useful to others, make them in a way that doesn't break existing functionality and contribute them back to the library by opening a pull request.
If the original library gets updated later, you will have to merge those changes from the so-called "upstream" repository into yours. This does not happen automatically, so you'll have full control (and responsibility) over that process. See https://help.github.com/en/articles/syncing-a-fork for how this would look like.

Xcode pluginDidLoad not getting called when adding objective-c file in swift plugin

I'm working on a plugin for Xcode. It is supposed to be written in Swift.
When I start with a fresh plugin project (I'm using this Xcode Plugin template which is also available via Alcatraz) the project compiles and runs fine.
The pluginDidLoad method is getting called right after Xcode starts. As soon as I add any Objective-C file (and a bridging header of course) the pluginDidLoad method is not getting called anymore.
The Objective-C file might be as simple as an empty class that is a subclass of NSObject.
Removing the target-memberbership (for the plugin-target) from the newly created Objective-C (.m) file the aforementioned mentioned method is getting called again.
Has anyone developed a Xcode plugin in Swift that also uses Objective-C files before and got this working?
Update
It seems that my original solution only works with Swift only projects because Xcode always takes the objective c class if you have one.
So here is another trick: Extend the NSObject class by the function class func pluginDidLoad(bundle: NSBundle) {} and initialize your plugin there. Then it doesn't matter on which class it is called. You might have to check that also all Swift classes subclass NSObject. I pushed it to my repository that you can have a look
Original Post
I think I could reproduce the problem now. To simplify the problem, let's say that we have only two swift classes PluginMain and PluginHelper.
As you said, sometimes the plugin isn't getting called for some mysterious reason. I was struggling with the problem again and I was wondering how Xcode knows which class is the main class. So I came up with the idea to put the following initializer in both classes PluginMain and PluginHelper
class func pluginDidLoad(bundle: NSBundle) {
let appName = NSBundle.mainBundle().infoDictionary?["CFBundleName"] as? NSString
if appName == "Xcode" {
//sharedPlugin = SwiftySafe(bundle: bundle)
//initialize your shared plugin
}
}
By putting a breakpoint or log message in pluginDidLoad in both classes, I notices that Xcode isn't ignoring the plugin, it is just loading the wrong class (e.g. PluginHelper instead of PluginMain).
The Solution
It turns out that Xcode uses the class that is compiled first as the main class and calls pluginDidLoad only on that. So you can change that by reordering the "Compiled Sources" under your target settings->Build Phases. Move your main class so that it is on top. In the following image you find an example from my project. SwiftySafe is my main class.
My example
You will find my project here https://github.com/creinders/SwiftySafe if you want to compare the settings.
The pluginDidLoad method is called on the principal class. When the principal class is a Swift class, you have to include the module name in the NSPrincipalClass Info.plist key.
So if your target name is MyPlugin and your principal class is MyClass, set NSPrincipalClass to MyPlugin.MyClass.
Also make sure that MyClass inherits from NSObject.
Sometimes you need to tell Xcode to reload bundle. Run this and restart Xcode
defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcode-7.3

FMDatabaseAdditions methods not accessible in swift?

I am porting some existing code over to swift. I am using FMDB in swift and everything has been good so far, but I do not have access to FMDatabaseAdditions methods in my project in spite of having access to everything else (FMResultSet, FMDatabasePool and so on).
I have the bridging-header file with the #import "FMDB" statement and it has the includes for all the other FMDB files.
I have looked in my build phases and I can see FMDatabaseAdditions.m in the "Compile Sources" and I have moved it to the top of the list.
Still xCode doesn't recognise it or its methods.
Any ideas?
UPDATE: Head over to the link below (in bold) for an unofficial FMDatabaseAdditionsVariadic.swift file as provided by Robert. Also keep an eye out on the repo for when the fix is officially added in.
Thanks again Rob!
-- ORIGINAL MESSAGE --
I found out what is going on from the guys on github over at FMDB repo.. (see original post here):
I notice that some of the FMDatabaseAdditions methods work fine. For example:
if db.tableExists("test") {
println("test table exists")
} else {
println("test table doesn't exist")
}
It looks like Swift is having issues with the variadic methods within the category. This is a known problem with Swift, but while I created the variadic rendition of executeQuery and executeUpdate, I didn't do so for the FMDatabaseAdditions methods. I will take care of this.
Thanks for bringing it to our attention.
Thanks robertmryan for your help.

Objective-C Block Property Defined as Copy Not Working

I am seeing some strange behavior with Objective-C blocks in a large project. Everywhere that there is a Block property that is defined as copy, there is a crash when the app attempts to reference the property later on. Overriding the setter implementation from the #synthesize'd implementation and explicitly calling Block_copy() does the trick, but interestingly when the same code is used in another project context the properties work as expected.
This must be some kind of project setting or dependency issue. Anyone run into this sort of thing before?
Thank you Bavarious. The underlying issue is libSystem library linked into the app.
The fix is to remove "-weak_library /usr/lib/libSystem.B.dylib" from the target's Linker Flags and replace it with "-weak-lSystem".