How to integrate WSAssetPickerController with Appcelerator - objective-c

Since there is no easy way to add multi image selection in Appcelerator, I'd like to incorporate this project: WSAssetPickerController - https://github.com/w5mith/WSAssetPickerController into my Appcelerator project.
I'm able to create a simple custom module in XCode/ObjC, and call it from Appcelerator, but I'm not sure how to call code that has a UI such as WSAssetPickerController does. Any tips would be appreciated.
Here is some code I have working now. This is pretty much boiler plate Appcelerator Custom Module stuff contained in an ObjC implementation class:
https://gist.github.com/3976969
Then in my Appclerator project, I load this module like this:
// in app.js
var myModule = require('com.example.test');
Ti.API.info("--->module loaded is ---> "+myModule);
// in testing.js
function createFoo() {
myModule.sayHello();
}
So, with this in place I am able to create a custom module in ObjC, load it up into Appcelerator and call a method on it.
I now want to the open source module WSAssetPickerController - however, this is quite a bit more sophisticated than my sayHello() method, as it contain a user interface view that needs to be loaded and displayed from Appcelerator. The documentation says to include all the code from the "src" directory (which I have done) into my ObjC project, then use code like this to load it:
WSAssetPickerController *controller = [[WSAssetPickerController alloc] initWithDelegate:self];
[self presentViewController:controller animated:YES completion:NULL];
But, this not working for me. Within XCode, I get a compiler warning on the first line of:
"Sending 'ComExampleTestModule *' to parameter of incompatiple type 'id
UPDATE: after some changes here is what I have now:
I modified the #interface line in ComExampleTestModule.h to:
#interface ComExampleTestModule : TiModule <WSAssetPickerControllerDelegate>
and I added this import statement:
#import "WSAssetPicker/WSAssetPicker.h"
but I am still getting compiler warnings in my .m file like this: "Instance method '-dismissViewControllerAnimated:completion' not found (return type defaults to 'id'.......
Thanks for the help.

what have you got written so far? Can you post it somewhere??
also take a look at some code I have in my repo... it might get you started
http://blog.clearlyinnovative.com/post/27531529814/titanium-appcelerator-quickie-cardio-integration

Related

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.

Cannot extend CocoaPods class in my Swift class

I've tried following the tutorial at https://vimeo.com/107295686, and failed very early.
Basically, I've:
created project
created Podfile which requires BDBOAuth1Manager and AFNetworking
installed cocoapods, closed XCode, and reopened it in my MyProject.xcworkspace directory.
Created and deleted a dummy Objective-C file, because I needed bridging header
Added #include directive to this header, which asks for BDBOAuth[...].h
Created Cocoa Touch class which extends BDBOAuth1RequestOperationManager
This is my code:
import UIKit
class RESTClient: BDBOAuth1RequestOperationManager {
}
And now I can't instantiate my new Cocoa Touch class.
When I try to call constructor, this is the hint I get
Note that method description says "Initializes an instance of the class that implements the video compositing protocol", which has nothing to do with my OAuth intentions. When I switch back to my class, and command-click the class I've tried to extend, I get the correct file with correct init params.
Any help will be appreciated
When I was trying to do this exact thing (same library), I had to change the import statements in BDBOAuth1Manager to use
#import <AFNetworking/xxx.h>.
My project wouldn't build without it. Have you checked the header search paths?

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

Restrict usage/generate a compile error when someone uses a particular method in an Objective-C class/object

Suppose I have an AwesomeClass but I cannot change it's implementation (ie it is from a static library or framework). I like everything about AwesomeClass except for - (void)thatOneBadMethod. I can subclass AwesomeClass to be MyAwesomeClass and override that method with an empty implementation (not calling super) but the problem is that if my fellow developer is using MyAwesomeClass and is unaware of my actions he may try to use thatOneBadMethod thinking that it is doing something it is not.
Is there some preprocessor directive that I can put in the override for thatOneBadMethod so that he gets a compiler error or warning when he tries to use it?
You can deprecate the method in the header file:
-(void)thatOneBadMethod __attribute__ ((deprecated("Unsupported, please call 'thatOneGoodMethod' instead!")));
But I'd also suggest generating an error when people try to call it:
-(void)thatOneBadMethod {
NSAssert(NO, #"Unsupported, please call 'thatOneGoodMethod' instead!");
}

Xcode can't find headers in given framework

Messing round a little in Xcode, and I was trying to get my app to look at the users music library with the use of MPMediaPickerController.
Following Apples documentation, I added the MediaPlayer.framework to the project, and in my header I've imported , giving me something like this:
#import <GameKit/GameKit.h>
#import <MediaPlayer/MediaPlayer.h>
#interface HelloMusic : UIViewController
{
}
So far so simple. Now, as far as I'm aware I should be able to do
MPMediaPickerController *mp = [[MPMediaPickerController alloc] init];
in my main file and set about launching my picker. Unfortunately XCode stubbronly refuses to admit that there is such a thing as an MPMediaPickerController - if I type MP and hit escape to get code complations I am without any of the MPMedia family. Annoyingly Xcode does recognise any MPMovie... class (from the same framework!). If I try and run the app it compiles fine so it must at least recognise the header from the framework, then chunters along until I get to the assignment of MPMediaPickerController, at which point I get an EXC_BAD_ACCESS, with a console output of
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
pthread_mutexattr_destroy$UNIX2003 called from function _ZN4llvm3sys5MutexC2Eb in image
libLLVMContainer.dylib.
I'm... certain I'm doing something beyond stupid, but I'm stuck nevertheless.
As the class reference states, it's declared in MPMediaPickerController.h. As such, simply adding...
#import <MediaPlayer/MPMediaPickerController.h>
...should solve your problems. :-)