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
}
Related
I have a Swift app, with some Objective-C code mixed in. It was working yesterday, but this morning I updated XCode and now everything had gone to hell!
Firstly, after updating, I clicked the XCode popup box to allow it to upgrade my app to Swift4. This is where the problems started.
I have a Swift class called RestClient with the following 4 functions (among others):
class func getInstance() -> RestClient {
if (gRestClient == nil) {
let prefs:UserDefaults = UserDefaults.standard
return RestClient(username: prefs.string(forKey: "username")!, password: prefs.string(forKey: "password")!)
}
return gRestClient!
}
class func getUsername() -> String {
if (gUsername == nil) {
let prefs:UserDefaults = UserDefaults.standard
gUsername = prefs.string(forKey: "username")!
}
return gUsername!
}
class func getPassword() -> String {
if (gPassword == nil) {
let prefs:UserDefaults = UserDefaults.standard
gPassword = prefs.string(forKey: "password")!
}
return gPassword!
}
public func getServer() -> String {
return MAIN_SERVER;
}
Then in my /Objective-C/ folder, I have some more files, once of which is called RestClientObj.m. In here, I have this lines of code:
NSString* url = [NSString stringWithFormat:#"%#/receipt/email/%#/%#/", [[RestClient getInstance] getServer], rrn, emailAddress];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", [RestClient getUsername], [RestClient getPassword]];
So as you can see, I'm calling the RestClient.swift from here. The RestClientObj.h is as follows:
#ifndef RestClientObj_h
#define RestClientObj_h
#endif /* ResClientObj_h */
#interface RestClientObj : NSObject {
}
+(BOOL) sendSMS:(NSString *)rrn mn:(NSString *)mobileNumber;
+(BOOL) sendEmail:(NSString *)rrn mn:(NSString *)emailAddress;
#end
This whole upgrade is causing other problems too. I have another class with the following error:
No visible #interface for 'AppDelegate' declares the selector 'managedObjectContext'
on the line:
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext]; <-ERROR
Can anyone shed any light on this?
EDIT: Here's some code from the AppDelegate class:
lazy var managedObjectContext: NSManagedObjectContext? = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
Just to close this off.
The issue was missing the #obj identifier before the variable declaration to make it visible to my objective-c code, in combination with the XCode Swift Upgrade wizard renaming some functions.
I am trying to call a Swift function that contains a completion handler in an objective C class, but I am not sure how to implement it.
This is my Swift Code
#objc class textToSpeech:NSObject{
func toSpeech(word: NSString, sucess:()->Void) -> NSURL {
let tempDirectory = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let tempFile = tempDirectory.URLByAppendingPathComponent((word as String) + ".wav")
let tts = TextToSpeech(username: "xxxxxx", password: "xxxxxx")
tts.synthesize(word as String,
voice: SynthesisVoice.GB_Kate,
audioFormat: AudioFormat.WAV,
failure: { error in
print("error was generated \(error)")
}) { data in
data.writeToURL(tempFile, atomically: true)
print("createdURL")
print(tempFile)
sucess();
}
return tempFile
}
How would I write the function call in objective c. I have already completed setting up the project so that I can call swift functions from objective c.
For example you have this code:
#objc class PDTextToSpeech: NSObject{
func toSpeech(word: NSString, success: () -> Void) -> NSURL {
// ...
return NSURL()
}
}
So you could easily bridge you Swift code in obj-c with #import "<ModuleName>-Swift.h"
where you project name.
Then you can call:
[[PDTextToSpeech new] toSpeech:#"String" success:^{
NSLog(#"Success");
}];
I was using PDTextToSpeech as class name, because it's preferable to call classes in obj-c with uniq prefix. If you project called TestProject - you can use TP prefix.
I guess it should look like this:
textToSpeech* text = [[textToSpeech alloc] init];
[text word:#"some text" sucess:^{
NSLog(#"success");
}];
How write this Objective C code in Swift?
#import "FFTViewController.h"
//only this part
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
#implementation FFTViewController
My idea is
let vDSP: vDSP_Length = 4096
i'm sure that is not correct, but i have no idea.
thanks for help
Update:
I want port this Objective C code to swift
#import "FFTViewController.h"
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
#implementation FFTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//
// Setup the AVAudioSession. EZMicrophone will not work properly on iOS
// if you don't do this!
//
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (error)
{
NSLog(#"Error setting up audio session category: %#", error.localizedDescription);
}
[session setActive:YES error:&error];
if (error)
{
NSLog(#"Error setting up audio session active: %#", error.localizedDescription);
}
//
// Setup time domain audio plot
//
self.audioPlotTime.plotType = EZPlotTypeBuffer;
self.maxFrequencyLabel.numberOfLines = 0;
//
// Setup frequency domain audio plot
//
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
self.audioPlotFreq.shouldCenterYAxis = NO;
//
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
//
self.microphone = [EZMicrophone microphoneWithDelegate:self];
//
// Create an instance of the EZAudioFFTRolling to keep a history of the incoming audio data and calculate the FFT.
//
self.fft = [EZAudioFFTRolling fftWithWindowSize:FFTViewControllerFFTWindowSize
sampleRate:self.microphone.audioStreamBasicDescription.mSampleRate
delegate:self];
//
// Start the mic
//
[self.microphone startFetchingAudio];
}
This is my beginning
import UIKit
import Accelerate
class ViewController: UIViewController, EZMicrophoneDelegate{
var mic: EZMicrophone!
var fft: EZAudioFFTRolling!
private let FFTViewControllerFFTWindowSize: vDSP_Length = 4096
override func loadView() {
super.loadView()
mic = EZMicrophone(delegate: self, startsImmediately: true)
fft = EZAudioFFTRolling(windowSize: FFTViewControllerFFTWindowSize, sampleRate: mic.audioStreamBasicDescription().mSampleRate, delegate: self)
}
}
I becoming the following error:
compile fails with the following error:
"Cannot invoke initializer for type 'EZAudioFFTRolling' with an argument list of type '(windowSize: vDSP_Length, sampleRate: Float64, delegate: ViewController)'"
How is my problem?
Sorry for this question i have no ObjectiveC background, is little challenge this port for me.
Thanks for Help
The problem you're getting an error is in types. When you start typing EZAudioFFTRolling initializer in XCode, autocompletion helps you by displaying specification. It looks like this:
EZAudioFFTRolling(windowSize: vDSP_Length, sampleRate: Float, delegate: EZAudioFFTDelegate!)
If you compare parameters types from specification with actual values you're passing, you will figure out that mic.audioStreamBasicDescription().mSampleRate has Float64 type but should be Float (they're actually not the same) and self is not conforming to EZAudioFFTDelegate protocol. So after changing your line to this
fft = EZAudioFFTRolling(windowSize: FFTViewControllerFFTWindowSize, sampleRate: Float(mic.audioStreamBasicDescription().mSampleRate), delegate: self)
and adding protocol conformance you will be able to build your code.
Swift is type safety in contradistinction to Objective-C, so it's common issues that all Objective-C developers have when start working with Swift. But errors are actually helping you, so read them attentively.
i am using cocos2d-js , that's a in purchase app,when purchase success ,i need to notify the message to cocos2d-js to update ui or something else,
i know call objective-c from cocos2d-js is like:
in js:
jsb.reflection.callStaticMethod("objective-cClass","methodName:", "parm");
but,how to call cocos2d-js from objective-c...
May it help someone, as we know, objective-c can easily call c++ methods, so we can use like this:
jsval ret;
ScriptingCore::getInstance()->evalString("CommonFun.setDiamond(88)", &ret);
and dont forget include head file, for cocos2d-x 3.8:
#include "cocos/scripting/js-bindings/manual/ScriptingCore.h"
1:how js call objc methods like this, js call only static method
(1)//NativeOcClass.mm filename
import <Foundation/Foundation.h>
#interface NativeOcClass : NSObject
+(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content;
#end
#implement NativeOcClass
+(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[alertView show];
return true;
}
#end
(2)for js file
var ret = jsb.reflection.callStaticMethod("NativeOcClass",
"callNativeUIWithTitle:andContent:",
"cocos2d-js",
"Yes! you call a Native UI from Reflection");
2:objc call js method
(1)js method,e.g.//Test.js
var Test={
myMethod:function(){
console.log("call js");
}
}
(2)objc //filename.mm
#include "cocos/scripting/js-bindings/manual/ScriptingCore.h"
....
-(void)callJsMethod
{
jsval ret;
ScriptingCore::getInstance()->evalString("Test.myMethod()", &ret);
}
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?