I notice theos could build library and produce dylib, I try the simple code like
static UIAlertView *alert_view;
static void showAlert() {
alert_view = [[UIAlertView alloc] initWithTitle:#"Welcome"
message:#"Welcome to your iPhone Brandon!"
delegate:nil
cancelButtonTitle:#"Thanks"
otherButtonTitles:nil];
[alert_view show];
[alert_view release];
}
after make I got a dylib, but I try to build a test project to use this dylib, failed.
My test code like
void* sdl_library = dlopen("/tmp/AlertDylib.dylib", RTLD_LAZY);
if(sdl_library == NULL) {
NSLog(#"fail load");
} else {
// use the result in a call to dlsym
void* showAlert = dlsym(sdl_library,"showAlert");
if(showAlert == NULL) {
NSLog(#"fail got function");
} else {
// cast initializer to its proper type and use
}
}
I'm sure I put dylib file under /tmp/, but log said "fail got function", any steps I missed?
Related
I want to transition all my old usages of -beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo: to the recommended -beginSheetModalForWindow:completionHandler:. How do I define contentInfo: and get it in the completionhandler?
Here is an example of how the old code looks like:
[alert beginSheetModalForWindow:window
modalDelegate:self
didEndSelector:#selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:(void *)CFBridgingRetain(fc)];
The endSelector method looks like this:
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if (returnCode == NSAlertDefaultReturn)
{
FileController *fc = (__bridge FileController *)(contextInfo);
[...]
}
}
}
I guess the new method should look somewhat like this:
[alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse alertReturnCode)
{
if (alertReturnCode == NSAlertFirstButtonReturn)
{
// evaluate contextInfo here ...
}
}];
But I have no clue how to get the contextInfo into the completionhandler.
Any help is appreciated.
There is no context info because the completion handler block can simply look right at the surrounding environment.
NSString* s = #"heyho";
[alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse alertReturnCode) {
if (alertReturnCode == NSAlertFirstButtonReturn)
{
// s is visible here
}
}];
In other words, we don't need to pass a context because we are in a context. If you have a FileController to pass down into the block, just let it pass down into the block.
I modified a function in objective C to throw errors. I then want to catch these errors in Swift. I implemented the Bridging function, and it looks that everything is in order. I am getting the error:
Consecutive statements on a line must be separated by ';'
just right after the command:
try rfduino.send(data)
If I don't use try, it starts asking me for a second parameter. The function worked before I implemented this error handling. I am using XCode 6.4.
I also read in http://blog.benjamin-encz.de/swift-error-handling-and-objective-c-interop-in-depth/
that XCode only translate the function to a Swift-like error throwing function when the function returns a BOOL or an ObjectiveC type. I also tried that.
What can it be?
My .h file looks like:
- (BOOL)send:(NSData *)data
error:(NSError**) errorPtr;
in .m file:
- (BOOL)send:(NSData *)data
error:(NSError**)errorPtr
{
if (! loadedService) {
if (errorPtr) {
*errorPtr = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSFileNoSuchFileError
userInfo:#{NSLocalizedDescriptionKey: NSLocalizedString(#"No Device Connected.", nil),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(#"The connection is not loaded.", nil),
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(#"Try disconnecting and connecting again", nil)
}];
} else {
#throw [NSException exceptionWithName:#"sendDataNoDevice" reason:#"please wait for ready callback" userInfo:nil];
}
return(NO);
}
if ([data length] > max_data) {
if (errorPtr) {
*errorPtr = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSFileNoSuchFileError
userInfo:#{NSLocalizedDescriptionKey: NSLocalizedString(#"No Device Connected.", nil),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(#"The connection is not loaded.", nil),
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(#"Try disconnecting and connecting again", nil)
}];
} else {
#throw [NSException exceptionWithName:#"sendDataTooLarge" reason:#"max data size exceeded" userInfo:nil];
}
return(NO);
}
[peripheral writeValue:data forCharacteristic:send_characteristic type:CBCharacteristicWriteWithoutResponse];
return(YES);
}
thanks!
You have to update Xcode.
Consecutive statements... usually appears when Xcode doesn't understand the syntax: indeed do try catch is only available in Xcode 7+ with Swift 2.
I'm having trouble converting this objective C to swift blocks
you can see here Code on Github, but i don't have any background in objective C, so i don't really understand this block, here is the code
- (LinkedStringTapHandler)exampleHandlerWithTitle:(NSString *)title
{
LinkedStringTapHandler exampleHandler = ^(NSString *linkedString) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title
message:[NSString stringWithFormat:#"Handle tap in linked string '%#'",linkedString]
delegate:nil
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil, nil];
[alert show];
};
return exampleHandler;
}
you can see this code on github https://github.com/evilBird/HBVLinkedTextView/blob/master/HBVLinkedTextViewExample/HBVLinkedTextViewExample/ViewController.m , take a look at that code, Im trying to use it in swift using bridging header. Everything i converted but this line i dont understand.
LinkedStringTapHandler exampleHandler = ^(NSString *linkedString)
this is what i have done so far
func exampleHandlerWithTitler(title:NSString)->LinkedStringTapHandler {
exampleHandler: LinkedStringTapHandler = (linkedString:NSString) -> () {
// alert view code here
}
return exampleHandler (ERROR here Use of unresolved identifier exampleHandler)
}
Where Objective-C has blocks, Swift has functions. So it's just a matter of knowing how to read Objective-C block syntax - not easy, I know:
^(NSString *linkedString)
That means: "This is a block taking an NSString parameter (and returning nothing)." So you want to supply here a Swift function that takes an NSString parameter (and returns nothing).
In other words, the definition of LinkedStringTapHandler is equivalent to saying this in Swift:
typealias LinkedStringTapHandler = (linkedString:NSString) -> ()
So in your code you would form a function of that type and return it:
func f(linkedString:NSString) -> () {
// do stuff
}
return f
You could do the same thing with an anonymous function but that's neither here nor there, really.
finally this is working
func exampleHandlerWithTitler(title:NSString)->LinkedStringTapHandler {
let exampleHandler: LinkedStringTapHandler = {(linkedString:String) in {
// alert view code here
}
return exampleHandler
}
My IDE show warning "Obsolete: Deprecated in iOS 7.0" this methods:
(GKScore) ReportScore()
(GKAchievement) ReportAchievement()
This methods it works on iOS 7, but use not problem? Exist other methods on iOS 7?
Thanks!
I used this method to report score in game center and it works.
-(void)reportScore
{
if(isIOS7)
{
// Create a GKScore object to assign the score and report it as a NSArray object.
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
score.value = _score;
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"score reporting error : %#", [error localizedDescription]);
}
else
{
NSLog(#"score reported.");
}
}];
}
else
{
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:_leaderboardIdentifier];
scoreReporter.value = _score;
scoreReporter.context = 0;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
// Do something interesting here.
if (error != nil) {
NSLog(#"score reporting error : %#", [error localizedDescription]);
}
else
{
NSLog(#"score reported.");
}
}];
}
}
Objective-C methods start with a lower-case method. They are not called with rounded brackets. So, I:
opened the documentation for GKScore;
looked for anything deprecated and found -reportScoreWithCompletionHandler:;
saw that +reportScores: withCompletionHandler: isn't deprecated.
And saw pretty much the same thing with the singular instance method being deprecated in favour of the collection class method in GKAchievement.
So: just use the collection methods. Deprecated methods hang around being unsupported for a while and then disappear. You can find out what's currently supported, very very quickly, by reading the documentation.
Having a heck of a time with this one.
I've got a super-simple Cocoa app containing one WebView, a WebScripting API defined in the page, and a single NSObject defined on that API. When I turn on the debugger tools (in the embedded WebView), I can see the API on the JavaScript window object, and I can see my "api" property defined on that -- but when I call the API's "get" method, the arguments aren't being serialized -- when the Obj-C method gets called, the arguments are missing. See below, which hopefully illustrates:
I've combed through the docs, I've (apparently) set the appropriate methods to expose everything that needs to be exposed, and I can see the method being called. There has to be something stupid I'm missing, but as a relative newbie to this environment, I'm not seeing it.
Thanks in advance for your help!
Have you set WebKitDeveloperExtras to YES in your default user defaults when you send -[NSUserDefaults registerDefaults:]?
Depending on what version of Xcode you're using you could be getting a known error. If you're using LLDB on anything but the most recent version, it might not be giving you the right variables in the debugger. The solution has been to use GDB instead of LLDB until Apple fixes the problem. But I think they fixed the problem in the latest version. I'd change the debugger to use GDB and see if you're getting the right variables in Xcode. (Product-> Edit Scheme...-> Run -> Debugger). I came across this problem in iOS, though, so I don't know its applicability to OSX. Worth a try anyway.
I originally came across the problem here: https://stackoverflow.com/a/9485349/1147934
I process javascript in the main thread of my app from a local file stored in the apps directory. I check for beginning and ending tokens for the js functions I am executing and whether the function contains a variable.
Hopefully this can give you some good ideas for your issue. You could also do alerts in the js to see if the values post correctly as you run the app (I am sure you thought of that already, but it's worth mentioning.) Happy coding! I hope this helps!
in the .h file define:
NSMutableString *processedCommand;
NSArray *commandArguments;
In the .m file:
// tokens
#define kOpenToken #"<%%"
#define kCloseToken #"%%>"
// this will throw
-(void)executeJScriptCommand:(NSString *)aCommand {
[self performSelectorOnMainThread:#selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES];
}
// this will throw
-(NSString *)executeCommand:(NSString *)command {
NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:#""]
stringByReplacingOccurrencesOfString:kCloseToken withString:#""]
stringByTrimmingLeadingAndTrailingWhitespaces];
if ([aCommand hasPrefix:#"="])
{
// variable. get value
[self getVariableFromCommand:aCommand];
}
else {
[self executeThisCommand:aCommand];
}
NSString *returnValue = [NSString stringWithString:processedCommand];
self.processedCommand = nil;
self.commandArguments = nil;
return returnValue;
}
-(void)executeThisCommand:(NSString *)aCommand {
BOOL hasError = NO;
// clear result
self.processedCommand = nil;
self.commandArguments = nil;
BOOL isFromJS = NO;
NSString *function = nil;
NSMutableArray *commandParts = nil;
#try {
// first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments
commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:#":"]];
if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:#"js-call"]) {
isFromJS = YES;
[commandParts removeObjectAtIndex:0];
}
// get our function, arguments
function = [[commandParts objectAtIndex:0] retain];
[commandParts removeObjectAtIndex:0];
if ([commandParts count] > 0){
if (isFromJS == YES) {
NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([arguments length] > 0) {
self.commandArguments = [arguments JSONValue];
}
}
else {
self.commandArguments = [NSArray arrayWithArray:commandParts];
}
}
// build invoke
SEL sel = NSSelectorFromString(function);
if ([self respondsToSelector:sel]) {
[self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES];
// using invocation causes a SIGABORT because the try/catch block was not catching the exception.
// using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected)
}
else {
[appDelegate buildNewExceptionWithName:#"" andMessage:[NSString stringWithFormat:#"Object does not respond to selector %#", function]];
}
}
#catch (NSException * e) {
hasError = YES;
[self updateErrorMessage:[NSString stringWithFormat:#"Error processing command %#: %#", aCommand, [e reason]]];
}
#finally {
[function release];
[commandParts release];
}
if (hasError == YES) {
[appDelegate buildNewExceptionWithName:#"executeThisCommand" andMessage:self.errorMessage];
}
}
// this can return nil
-(NSString *)getQueryStringValue:(NSString *)name {
NSString *returnValue = nil;
if (queryString != nil) {
returnValue = [queryString objectForKey:[name lowercaseString]];
}
return returnValue;
}