Using self in a Swift closure with SIOSocket - objective-c

I am hoping someone can help me. I trying to use SIOSocket with a Swift project.
I am using the example at https://github.com/MegaBits/SIOSocket/issues/30 which seems to work, but i want to be able to declare a socket as a var like the Objective-C project example at https://github.com/MegaBits/WorldPin. so i can use it in else where in the code to call emit.
I assume i am not understanding the Obj-C block and Swift closure fundamentals and the use of self or the need to declare the var as block but can’t seem to wrap my head around it. Any help will be much appreciated.
SIOSocket is on Github
Objective-C code:
#property SIOSocket *socket;
[SIOSocket socketWithHost: #"http://localhost:3000" response: ^(SIOSocket *socket)
{
self.socket = socket; //I Want to do this in swift
__weak typeof(self) weakSelf = self;
self.socket.onConnect = ^()
{
weakSelf.socketIsConnected = YES;
[weakSelf mapView: weakSelf.mapView didUpdateUserLocation: weakSelf.mapView.userLocation];
};
[self.socket on: #"join" callback: ^(SIOParameterArray *args)
{
[weakSelf mapView: weakSelf.mapView didUpdateUserLocation: weakSelf.mapView.userLocation];
}];
[self.socket on: #"update" callback: ^(SIOParameterArray *args)
{
NSString *pinData = [args firstObject];
etc etc …
Swift Code:
private func connectToHost() {
SIOSocket.socketWithHost(host, reconnectAutomatically: true, attemptLimit: 0, withDelay: 1, maximumDelay: 5, timeout: 20, response: {
socket in
self.socket = socket // This gives me a use of unresolved identifier self error
socket.onConnect = {
println("Connected to \(host)")
socket.emit("add user", args: [username])
}
socket.on("login", callback: {(AnyObject data) -> Void in
println(["login": data])
socket.emit("new message", args: [message])
})
socket.onDisconnect = {
println("Disconnected from \(host)")
}
})
}

Your code should work, make sure you have all the right types and optional types, make sure socket is a read-write variable by defining it with var and not with let.
Try defining the closure before the method call by using let response: (SIOSocket) -> Void = {...}.

Try changing it to this:
SIOSocket.socketWithHost(host, reconnectAutomatically: true, attemptLimit: 0, withDelay: 1, maximumDelay: 5, timeout: 20, response: {(socket: SIOSocket) in
self.socket = socket // This gives me a use of unresolved identifier self error
//...
})
I changed socket in to (socket: SIOSocket) in

Related

Objective C - UICollectionViewListCell swipe to delete

Trying to implement "Swipe to Delete" API for UICollectionViewListCell.
I'm writing in Objective-C
the compiler is not auto-completing the code.
Any reasons? example code?
Swift example:
let listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
listConfig.trailingSwipeActionsConfigurationProvider = { [weak self] indexPath in
guard let self = self else { return nil }
let action = UIContextualAction(style: .normal, title: "Done!", handler: actionHandler)
return UISwipeActionsConfiguration(actions: [action])
}
Any code example for Objective C?

NSApp: Hide main window until proper ViewController can be loaded

I have a MacOS app that is a registered custom URL handler.
I'm trying to make it show a specific NSViewController if the app is started via the url handler or the regular window and ViewController if no parameters are used.
In my AppDelegate.swift I have this:
func application(_ application: NSApplication, open urls: [URL]) {
AppDelegate.externalCaller = true;
NSApp.hide(self)
let url: URL = urls[0];
// Process the URL.
let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true);
let method = components?.host;
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if (method == "DO_STH") {
// do something with no window
NSApplication.shared.windows.last?.close();
} else if (method == "DO_STH_2") {
// do something with no window
NSApplication.shared.windows.last?.close();
} else if (method == "PROCESS_STUFF") {
// Show window
DispatchQueue.main.async {
let mainStoryboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil);
let restoringViewController = mainStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("restoringData")) as! RestoringViewController;
if let window = NSApp.mainWindow {
window.contentViewController = restoringViewController;
}
NSApp.activate(ignoringOtherApps: true);
AppDelegate.restoreData();
}
}
}
}
}
The problem is that by the time NSApp.hide(self) runs, there's already a window visible with the default viewController, creating some flickering effect.
What's the best way to make the app start without any visible window by default and only show the window if it wasn't started with any URL parameter and later on demand if a specific URL parameter exists?
Unchecking "Is initial Controller" and adding this to AppDelegate solved my issue
func applicationDidFinishLaunching(_ notification: Notification) {
if (!AppDelegate.externalCaller) {
showWindow();
}
}
func showWindow() {
let mainStoryboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil);
let windowController = mainStoryboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("MainWindowController")) as! NSWindowController;
windowController.showWindow(self);
}

unresolved identifier in swift 3

My code is trying to download some JSON data and save it to an array, then loop through the array and create a button for each item. I am having trouble assigning my function to the buttons for giving them functionality. Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//connect to website
let SongArray: Array<Any>
let url = URL(string:"*******")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil
{
print("error")
}
else
{
if let content = data
{
do
{
//download JSON data from php page, display data
let SongArray = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as! [[String]]
print(SongArray)
//Make buttons with JSON array
var buttonY: CGFloat = 20
for song in SongArray {
let SongButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // 50px spacing
SongButton.layer.cornerRadius = 10 //Edge formatting for buttons
SongButton.backgroundColor = UIColor.darkGray //Color for buttons
SongButton.setTitle("\(song[0])", for: UIControlState.normal) //button title
SongButton.titleLabel?.text = "\(song[0])"
SongButton.addTarget(self,action: #selector(songButtonPressed(_:)), for: UIControlEvents.touchUpInside) //button press / response
self.view.addSubview(SongButton) // adds buttons to view
}
}
catch
{
}
}
}
}
task.resume()
}
} //close viewDidLoad
func songButtonPressed(_sender:UIButton!) { // function for buttons
if sender.titleLabel?.text == "\("Song[0]")" {
print("So far so good!!")
}
}
I am getting an error on the line with SongButton.addTarget...
the error says 'Use of Unresolved Identifier "SongButtonPressed"' even though its declared right after the viewDidLoad function.
Since you declared the selector SongButtonPressed(_:) it's (note the underscore)
func SongButtonPressed(_ sender: UIButton) { // no implicit unwrapped optional !!
By the way the proper selector syntax is #selector(SongButtonPressed(_:))
Two notes:
.mutableContainers has no effect in Swift at all. Omit the parameter. And delete the line let SongArray: Array<Any>. You should get an unused warning.
Functions, methods and variables are supposed to start with a lowercase letter.

How do i request mic record permission from user

I am using the new iOS7 developer SDK and now the app request from the user his permission to record from mic when the App try to record in the first time.
My App will record after a countdown,so the user can't see this request.
I use this code to check the requestRecordPermission:
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
if (granted) {
// Microphone enabled code
}
else {
// Microphone disabled code
}
}];
But how can i trigger the request by myself before i start to record ?
In the new iOS7 it's very simple try this:
if([[AVAudioSession sharedInstance] respondsToSelector:#selector(requestRecordPermission)])
{
[[AVAudioSession sharedInstance] requestRecordPermission];
}
Here is final code snippet that does work for me. It support both Xcode 4 and 5, and works for iOS5+.
#ifndef __IPHONE_7_0
typedef void (^PermissionBlock)(BOOL granted);
#endif
PermissionBlock permissionBlock = ^(BOOL granted) {
if (granted)
{
[self doActualRecording];
}
else
{
// Warn no access to microphone
}
};
// iOS7+
if([[AVAudioSession sharedInstance] respondsToSelector:#selector(requestRecordPermission:)])
{
[[AVAudioSession sharedInstance] performSelector:#selector(requestRecordPermission:)
withObject:permissionBlock];
}
else
{
[self doActualRecording];
}
As "One Man Crew" claimed you can use requestRecordPermission.
Important thing to be aware of is that you must check that requestRecordPermission is implemented. The reason is that if your app would run on older iOS version (iOS 6.x for example) it would crash after this call.
To prevent that you must check that this selector is implemented (this is a good practice anyway).
Code should be something like this:
if([[AVAudioSession sharedInstance] respondsToSelector:#selector(requestRecordPermission:)]){
[[AVAudioSession sharedInstance] requestRecordPermission];
}
Using this method your app would support the new OS and also previous versions of the OS.
I'm using this method every time Apple add more functionality to new OS (that way I can support older versions pretty easy).
AVAudioSession.sharedInstance().requestRecordPermission({ (granted) -> Void in
if !granted
{
let microphoneAccessAlert = UIAlertController(title: NSLocalizedString("recording_mic_access",comment:""), message: NSLocalizedString("recording_mic_access_message",comment:""), preferredStyle: UIAlertControllerStyle.Alert)
var okAction = UIAlertAction(title: NSLocalizedString("OK",comment:""), style: UIAlertActionStyle.Default, handler: { (alert: UIAlertAction!) -> Void in
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
})
var cancelAction = UIAlertAction(title: NSLocalizedString("Cancel",comment:""), style: UIAlertActionStyle.Cancel, handler: { (alert: UIAlertAction!) -> Void in
})
microphoneAccessAlert.addAction(okAction)
microphoneAccessAlert.addAction(cancelAction)
self.presentViewController(microphoneAccessAlert, animated: true, completion: nil)
return
}
self.performSegueWithIdentifier("segueNewRecording", sender: nil)
});
Based on https://stackoverflow.com/users/1071887/idan's response.
AVAudioSession *session = [AVAudioSession sharedInstance];
// AZ DEBUG ## iOS 7+
AVAudioSessionRecordPermission sessionRecordPermission = [session recordPermission];
switch (sessionRecordPermission) {
case AVAudioSessionRecordPermissionUndetermined:
NSLog(#"Mic permission indeterminate. Call method for indeterminate stuff.");
break;
case AVAudioSessionRecordPermissionDenied:
NSLog(#"Mic permission denied. Call method for denied stuff.");
break;
case AVAudioSessionRecordPermissionGranted:
NSLog(#"Mic permission granted. Call method for granted stuff.");
break;
default:
break;
}
Swift 4:
let session = AVAudioSession.sharedInstance()
if (session.responds(to: #selector(AVAudioSession.requestRecordPermission(_:)))) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("granted")
} else {
print("not granted")
}
})
}

OOP Programming in Javascript with Node.js

I am actually playing with Javascript doing a small game and I would like to implement what I've found on http://www.crockford.com/javascript/inheritance.html which is something similar to:
ZParenizor.method('toString', function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-";
});
I can't find any reference the the library used to make such development possible. Any ideas? Otherwise, I'm looking for a good library that will aid my OOP developments.
Thank you
Edit:
I am looking for a OOP solution / library for Node.js. Please note that I'm new to Node.js
2 months later
Maybe you do need a library, ES5 is verbose as hell so I've created pd
Original answer
I am looking for a OOP solution / library for Node.js.
You don't need a library. You have ES5.
JavaScript does not have classical OOP. It has prototyping OOP.
This means you have only objects. The only thing you can do with objects is extend, manipulate and clone them.
Manipulate
var o = {};
o.foo = "bar";
Extend
var o = someObject;
Object.defineProperties(o, {
"foo": { value: "foo" },
"bar": { value: "bar" }
"method": { value: function () { } }
}
Clone
var o = someObject;
var p = Object.create(o);
Clone and extend
var o = someObject;
var p = Object.create(o, {
"foo": { value: "foo" },
"bar": { value: "bar" }
"method": { value: function () { } }
}
It's important to understand how Object.create, Object.defineProperty and Object.defineProperties work.
The cloning operation isn't actually cloning. It's creating a new object from a blueprint. A blueprint is an object. It places the blueprint in the [[Prototype]]. The [[Prototype]] lives in the .__proto__ property which I'll use for demonstration.
var o = {};
var p = Object.create(o);
p.__proto__ === o; // true
var q = Object.create(p);
q.__proto__.__proto__ === o;
var r = Object.create(q);
r.__proto__.__proto__.__proto__ === o;
Disclaimer: .__proto__ is deprecated. Don't use it in code. It has it's uses for debugging and sanity checks though.
The main point here is that accessing properties from o in r it has to walk 3 levels up the prototype chain and this gets expensive. To solve that problem, rather then cloning random objects you should clone specific blueprints (and you should have one blueprint per object).
// Parent blueprint
var Parent = (function _Parent() {
// create blank object
var self = Object.create({});
// object logic
return self;
}());
// factory function
var createParent = function _createParent(foo) {
// create a object with a Parent prototype
return Object.create(Parent, {
foo: { value: foo }
});
}
var Child = (function _Child() {
var self = Object.create(Parent);
// other stuff
return self;
}());
var createChild = function _createChild(bar) {
return Object.create(Child, {
bar: { value: bar }
})
};
Here's a snippet from some code I'm working on that you can use as an example:
var Sketchpad = (function _SketchPad() {
var self = Object.create({});
var mousemove = function _mousemove(e) {
this.drawLine(e);
};
self._init = function _init() {
this.$elem.bind({
"mousemove": mousemove.bind(this),
});
this.pens = {};
$("#clear").bind("click", this.clear.bind(this));
$("#undo").bind("click", (function _undoPath() {
this.pen.undo();
}).bind(this));
return this;
};
self.clear = function() {
this.paper.clear();
};
return self;
}());
createSketch = function _createSketchPad(id, w, h) {
var paper = Raphael(id, w, h);
var pen = createPen(paper);
var o = Object.create(Sketchpad, {
paper: { value: paper },
$elem: { value: $("#" + id) },
pen: {
get: function() { return pen; },
set: function(v) { pen = v; }
}
});
return o._init();
};
MooTools is one of the best libraries in terms of OOP Javascript.
You can create classes, interfaces, use inheritance, etc.
Documentation
http://mootools.net/docs/core
Tutorial - MooTools OOP
http://www.phpeveryday.com/articles/MooTools-Basic-Creating-Classes-MooTools-P919.html
You might also be interested in GNU ease.js. If you are not interested in the library itself, its manual goes extensively into the implementation details.
You could also see the author's paper on Classical OOP in ECMAScript.
You could try Joose, https://github.com/SamuraiJack/Task-Joose-NodeJS. Although, I'd personally recommend to stick with Javascript's object functionality as provided by ES5.
In the article you referenced, he was simply giving an example of what was possible with inheritance in javascript. He was not using a framework, but showing you how to extend your own classes you have written.
Frameworks for javascript include Backbone.js (mvc), and MooTools (oop).
extjs has support for OOP with Ext.define and Ext.extend (and Ext.ns). See this example on Sencha.com
Ext.extend is the older method, but is still sometimes useful. You would do something like this:
Ext.ns('myApp.myPackage'); // create a namespace
(function() { // this adds it to the namespace
var MyClass = Ext.extend(BaseClass, {
property: 1,
constructor: function(config) {
Ext.apply(this, config);
},
method: function(a, b) {
this.property = a + b;
}
});
myApp.myPackage.MyClass = MyClass;
}) ()
With Ext.define in Ext 4+ you can do:
Ext.define('myApp.myPackage.MyClass', // don't need to define the namespace first
extend: 'BaseClass' // notice the base class is referenced by a string,
requires: 'AnotherClass',
mixins: { mixin : 'MixinPackage' },
property: 1,
constructor: function(config) {
//...
}
method: function(a, b) {
this.property = a + b;
}
});
Note that you can also use traditional OOP in javascript with 'new' and function.prototype
If you want to do a real strong OOP in Javascript/Node, you can have a look at the full-stack open source framework Danf.
It allows you to use OOP (and so the same classes) on both the server (node) and client (browser) sides.
It also provides a nice dependency injection mechanism (looking as the one of Symfony2 if you come from the PHP community).