URLLoader at Actionscript - actionscript

At the URLLoader reference there is the following example:
private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
}
I cannot understand the URLLoader(event.target) syntax. It's not a call to the constructor, it's not a method invocation or a static method invocation. What is it?

It's a cast. In this example they are simply casting the event.target, which was a URLLoader as such.

Related

Programming Asynchronous Delegate methods in Swift

I have an application which talks to a device over a BLE UART connection.
When data is received, a didReceiveData() delegate is called.
Here I need determine who called the data and trigger the corresponding method (of another delegate).
I was planning on creating a connections dictionary keyed by a connectionID string created when the connection is established, along with a selector to the callback (may not always be supplied).
class Connection: NSObject {
var selectr: Selector
var dataString: String?
init(selectR:Selector,dString:String) {
selectr = selectR
dataString = dString
}
}
connections[String:Connection]()
func sendData(dataString:String,callbackSelector:Selector){
con = Connection(selectR: callbackSelector, dString:"")
connections[cid] = con
}
...
When calling:
let sel = Selector(anotherDelegate?.didReceiveLocation(""))
self.sendData("sendMe",Selector(anotherDelegate?.didReceiveLocation))
I get a few errors doing this, first a Type NSData does not conform to protocol StringLiteralConvertible. NSData referring to the argument of didReceiveLocation.
The second is on the self.sendData line: Cannot invoke 'init' with an argument list of type (StringLiteralConvertible,Selector).
Does this approach make sense? How can I store the callback method of another delegate in a dictionary or other struct to make it accessible from the didReceiveData delegate method?
Selectors are so Objective-C... why not just use a closure?
To declare a dictionary with String as keys and functions that take a String as a parameter and return nothing:
connections = [String:String->()]()
To declare a function that takes a closure with a single String argument and no return value, use something like:
func sendData(dataString:String, callback:String->()) {
...
connections[cid] = callback
...
}
To invoke that closure later, you can call it as a subroutine (in this case after performing a dictionary lookup, using optional chaining in case it hasn't been assigned yet):
func didReceiveData(...) {
...
connections[cid]?(response)
}
Then to call the sendData routine declared above and pass in a closure using one of the several abbreviated syntaxes:
self.sendData("sendMe") { response in
...
}
Note that this is actually short-hand for:
self.sendData("sendMe", callback:{ response:String in
...
})
Note that this mechanism can also be used by an Objective-C caller, since closures map more or less directly to Objective-C blocks.
For more information on closures, their definition and invocation, I'd strongly recommend downloading the free Swift book from the iTunes book store.

Method swizzling a private framework iOS API

I know there are countless resources on method swizzling. However is it possible to swizzle a method from a private API? The problem is that there are no header files. I would like to swizzle a method from a private class in a PrivateFramework such as (random example) Message.framework methods
This is for personal testing, I understand that it will get rejected to oblivion by Apple.
You can use NSClassFromString to get Class and use runtime library to perform method swizzling. No header files required. You just need to know class name and method signature.
sel_getUid can be used when #selector(somePrivateMethod) give your error about somePrivateMethod is not valid selector (because header is not available)
Code taken from my Xcode plugin
SEL sel = sel_getUid("codeDiagnosticsAtLocation:withCurrentFileContentDictionary:forIndex:");
Class IDEIndexClangQueryProviderClass = NSClassFromString(#"IDEIndexClangQueryProvider");
Method method = class_getInstanceMethod(IDEIndexClangQueryProviderClass, sel);
IMP originalImp = method_getImplementation(method);
IMP imp = imp_implementationWithBlock(^id(id me, id loc, id dict, IDEIndex *idx) {
id ret = ((id (*)(id,SEL,id,id,id))originalImp)(me, sel, loc, dict, idx);
// do work
return ret;
});
method_setImplementation(method, imp);
Create a category on the class and add the declaration for the method you want to call. Then you can just instantiate an instance of the class and call the method.
This also works for unit testing private methods in your code.

How to pass objective-c function as a callback to C function?

I want to call a c function from objective-c and pass objective-c function as a callback
the problem is this function has a callback as parameter, so I have to pass objective-c function as a call back to c function
here is the header of the c function
struct mg_context *mg_start(const struct mg_callbacks *callbacks,
void *user_data,
const char **configuration_options);
here is where I try to call it
- (void)serverstarted
{
NSLog(#"server started");
}
- (IBAction)startserver:(id)sender {
NSLog(#"server should start");
const char *options[] =
{
"document_root", "www",
"listening_ports", "8080",
NULL
};
mg_start(serverstarted(), NULL, options);
}
I have tried several ways to do it and searched the web to just get a clue how to do it but with not luck
here is the library I am incuding in my code
https://github.com/valenok/mongoose
Your chief problem is the first parameter to mg_start(), which is described in the declaration as const struct mg_callbacks *callbacks. You are trying pass a pointer to a function. (Actually you are trying to pass the result of a call to that function, which is even further from the mark.) That isn't what it says: it says a pointer to a struct (in particular, an mg_callbacks struct).
The example code at https://github.com/valenok/mongoose/blob/master/examples/hello.c shows you how to configure this struct. You have to create the struct and put the pointer to the callback function inside it. Then you pass the address of that struct.
Other problems with your code: your callback function itself is all wrong:
- (void)serverstarted
{
NSLog(#"server started");
}
What's wanted here is a C function declared like this: int begin_request_handler(struct mg_connection *conn), that is, it takes as parameter a pointer to an mg_connection struct. Your serverstarted not only doesn't take that parameter, it isn't even a C function! It's an Objective-C method, a totally different animal. Your use of the term "Objective-C function" in your title and your question is misleading; C has functions, Objective-C has methods. No Objective-C is going to be used in the code you'll be writing here.
What I suggest you do here is to copy the hello.c example slavishly at first. Then modify the content / names of things slowly and bit by bit to evolve it to your own code. Of course learning C would also help, but you can probably get by just by copying carefully.
As matt already said, you cannot pass an Objective-C method as callback where a C function
is expected. Objective-C methods are special functions, in particular the receiver ("self")
is implicitly passed as first argument to the function.
Therefore, to use an Objective-C method as request handler, you need an (intermediate) C function as handler and you have to pass self to that function, using the user_data argument. The C function can then call the Objective-C method:
// This is the Objective-C request handler method:
- (int)beginRequest:(struct mg_connection *)conn
{
// Your request handler ...
return 1;
}
// This is the intermediate C function:
static int begin_request_handler(struct mg_connection *conn) {
const struct mg_request_info *request_info = mg_get_request_info(conn);
// Cast the "user_data" back to an instance pointer of your class:
YourClass *mySelf = (__bridge YourClass *)request_info->user_data;
// Call instance method:
return [mySelf beginRequest:conn];
}
- (IBAction)startserver:(id)sender
{
struct mg_callbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.begin_request = begin_request_handler;
const char *options[] =
{
"document_root", "www",
"listening_ports", "8080",
NULL
};
// Pass "self" as "user_data" argument:
mg_start(&callbacks, (__bridge void *)self, options);
}
Remarks:
If you don't use ARC (automatic reference counting) then you can omit the (__bridge ...)
casts.
You must ensure that the instance of your class ("self")
is not deallocated while the server is running. Otherwise the YourClass *mySelf
would be invalid when the request handler is called.

What does Cannot create delegate without target for instance method or closure mean

I am using vala.
This is the source code that gives that compile time bug :
private Gee.HashMap<string,VoidFunc> fill_actions()
{
var actions = new Gee.HashMap<string,VoidFunc>();
MainWindow win = window;
actions["t"] = () => _puts(win.title);
return actions;
}
First I tried to access this.window directly but that gave another error so I tried this with a local scope variable.
Error when doing directly this.window :
This access invalid outside of instance methods
It sounds like VoidFunc is declared with [CCode (has_target = false)]. What that means is that no context information is passed to it, and AFAIK that is the only way delegates work as generic type arguments. The reason for this is limitations in C, so assuming VoidFunc looks like this:
[CCode (has_target = false)]
public delegate void VoidFunc ();
What you'll get in C is something like this:
typedef void (*VoidFunc)();
As opposed to something like this if you didn't have the [CCode (has_target = false)]:
typedef void (*VoidFunc)(gpointer user_data);
When you pass around callbacks in C you generally do so with between one and three arguments. Something with all three would look like this:
void foo (VoidFunc void_func, gpointer user_data, GDestroyNotify notify);
The first parameter is the actual function. The second parameter is the value to pass as user_data to the callback, and is what Vala uses to pass context information to the callback (which is what allows it to act as an instance method, or even a closure). The third parameter is used to specify a function to free user_data when it is no longer needed.
What [CCode (has_target = false)] means is that the delegate doesn't have a user_data argument, and therefore cannot be used as a closure or instance method.
The reason this is necessary with a generic argument is that generics look something like this at the C level:
void foo_bar (gpointer data, GDestroyNotify notify);
The first parameter is the data that you want to use as a generic value, the second is actually only added if the generic argument is owned (as it is in the case of the set methods in Gee), and is called with user_data as an argument when user_data is no longer needed.
As you can see, when trying to use a delegate as a generic, there is nowhere to put the user_data argument, which is why Vala only allows delegates without targets to be generic arguments.
The solution is basically to wrap the delegate in a class:
public delegate void VoidFunc ();
public class YourClass {
private class VoidFuncData {
public VoidFunc func;
public VoidFuncData (owned VoidFunc func) {
this.func = (owned) func;
}
}
private Gee.HashMap<string,VoidFuncData> fill_actions() {
var actions = new Gee.HashMap<string,VoidFuncData>();
string win = "win";
actions["t"] = new VoidFuncData (() => GLib.debug (win));
return actions;
}
}

how do I override a setter function at runtime in actionscript?

I have an AS class with setter and getter functions.
I need to tweak one of this class's instances so that it's setter function will process the input before assigning it to the local variable.
or, in a more elaborated way, what should I use instead of $$$ in the example below?
class MyClass{
private var _legend:Array;
function set legend(legend:Array):void{
_legend= legend;
}
function get legend():Array{
return _legend;
}
function someFunction():void{
foo();
}
}
var mc:MyClass = new MyClass();
mc.someFunction = function():void{
bar();
}
mc.$$$ = new function(legend:Array):void{
_legend = process(legend);
}
Normally you would subclass MyClass to modify the behavior (polymorphism) of MyClass.
class MySubClass extends MyClass {
function set legend(legend:Array):void{
// do your checking here. Then call the
// setter in the super class.
super.legend = legend;
}
}
Why don't you pass the instance a processed input?
mc.legend = process(legend);
If this is not possible, you can modify the setter in MyClass and take an optional boolean to do processing.
function set legend(legend:Array, flag:bool = false):void{
_legend = flag ? process(legend) : legend;
}
Note that prototype inheritance does not restrict itself to a particular instance. From the documentation:
Prototype inheritance - is the only inheritance mechanism in previous versions of ActionScript and serves as an alternate form of inheritance in ActionScript 3.0. Each class has an associated prototype object, and the properties of the prototype object are shared by all instances of the class.

Resources