I'm trying to write a simple command line app that can display some info on a notification. But, the Delegate is not being called, and neither is the Notification and I'm not sure what's missing here.
Judging from my output, I think the whole problem stems from the AppDelegate not being instantiated. But I am creating one just before I show call showNotification.
What am I missing here?
src/main.swift
import Foundation
import AppKit
var sema = DispatchSemaphore( value: 0 )
let server: String = "http://jsonip.com"
let port: String = "80"
let path: String = "/"
let todoEndpoint: String = server + ":" + port + path
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let url = URL(string: todoEndpoint)!
let task = session.dataTask(with: url, completionHandler: {
(data, response, error) in
if error != nil {
print(error!.localizedDescription)
} else {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
print(json)
let ad = AppDelegate()
ad.showNotification(title: "Title", subtitle: "SubTitle", informativeText: String(describing: json))
sema.signal()
}
} catch {
print("error in JSONSerialization")
}
}
})
print("Resume Task")
task.resume()
print("Wait for Semaphore")
sema.wait()
src/AppDelegate.swift
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
func applicationDidFinishLaunching(aNotification: Notification) {
NSUserNotificationCenter.default.delegate = self
print("Delegate Self")
}
// NSUserNotificationCenterDelegate implementation
private func userNotificationCenter(center: NSUserNotificationCenter!, didDeliverNotification notification: NSUserNotification!) {
//implementation
}
private func userNotificationCenter(center: NSUserNotificationCenter!, didActivateNotification notification: NSUserNotification!) {
//implementation
}
private func userNotificationCenter(center: NSUserNotificationCenter!, shouldPresentNotification notification: NSUserNotification!) -> Bool {
//implementation
return true
}
func showNotification(title: String, subtitle: String, informativeText: String) -> Void {
let notification: NSUserNotification = NSUserNotification()
print("Show Notification")
notification.title = title
notification.subtitle = subtitle
notification.informativeText = informativeText
//notification.contentImage = contentImage
notification.soundName = NSUserNotificationDefaultSoundName
NSUserNotificationCenter.default.deliver(notification)
print(notification.isPresented)
}
}
Output
Resume Task
Wait for Semaphore
["about": /about, "reject-fascism":
Impeach Trump!, "ip": 110.50.73.141, "Pro!": http://getjsonip.com]
Show Notification
false
Program ended with exit code: 0
Related
I am trying to capture my system's screen and process the data. But I get nil value for CMSampleBufferGetDataBuffer for the sample buffer I get in captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) delegate method. Any idea? below is my code:
import Cocoa
import AVFoundation
class ViewController: NSViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
private lazy var sampleBufferDelegateQueue = DispatchQueue(label: "VideoCapture")
private lazy var captureSession: AVCaptureSession = {
let session = AVCaptureSession()
session.sessionPreset = .hd1280x720
if let input = AVCaptureScreenInput.init(displayID: CGMainDisplayID()) {
session.addInput(input)
}
let output = AVCaptureVideoDataOutput()
output.videoSettings = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
kCVPixelBufferMetalCompatibilityKey as String: true
]
output.setSampleBufferDelegate(self, queue: self.sampleBufferDelegateQueue)
session.addOutput(output)
return session
}()
#IBAction func startAction(_ sender: Any) {
self.start()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func start() {
guard !self.captureSession.isRunning else {
return
}
self.captureSession.startRunning()
}
func stop() {
guard self.captureSession.isRunning else {
return
}
self.captureSession.stopRunning()
}
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
print(blockBuffer ?? "nil")
}
}
I’m new to RxSwift and I’m looking for a basic example of how to print in console live data streaming from an backend. I have a backend which is streaming some dummy data every 1 second, I can see it with a curl request and I want to be able to observe and subscribe and print it out in console automatically, please help!
I assume you are opening a socket connection to your server in order to receive live data. You can use RxWebSocket to handle this data flow. There are examples in the documentation/readme for the API.
https://github.com/daltoniam/Starscream/tree/master/examples/SimpleTest/SimpleTest
import UIKit
import Starscream
class ViewController: UIViewController, WebSocketDelegate {
var socket: WebSocket!
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
var request = URLRequest(url: URL(string: "wss://echo.websocket.org")!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
// MARK: Websocket Delegate Methods.
func websocketDidConnect(socket: WebSocketClient) {
print("websocket is connected")
}
func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
if let e = error as? WSError {
print("websocket is disconnected: \(e.message)")
} else if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
self.label.text = text
print("Received text: \(text)")
}
func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
print("Received data: \(data.count)")
}
// MARK: Write Text Action
#IBAction func send(_ sender: UIButton) {
socket.write(string: "Hello \(textField.text!)")
}
// MARK: Disconnect Action
#IBAction func disconnect(_ sender: UIBarButtonItem) {
if socket.isConnected {
sender.title = "Connect"
socket.disconnect()
} else {
sender.title = "Disconnect"
socket.connect()
}
}
}
extension URL {
init(staticString string: StaticString) {
guard let url = URL(string: "\(string)") else {
preconditionFailure("Invalid static URL string: \(string)")
}
self = url
}
}
I'm trying to upgrade mi app to swift 4, but the barcode reader is not working.
I have isolated the barcode reader code, and still not working. The camera works but it does not detect the barcode.
The code worked just fine on swift 3 iOS 10.
This is the complete code
import AVFoundation
import UIKit
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
var captureSession: AVCaptureSession!
var previewLayer: AVCaptureVideoPreviewLayer!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black
captureSession = AVCaptureSession()
let videoCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video)
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice!)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed();
return;
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.ean8, AVMetadataObject.ObjectType.ean13, AVMetadataObject.ObjectType.pdf417]
} else {
failed()
return
}
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.frame = view.layer.bounds;
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill;
view.layer.addSublayer(previewLayer);
captureSession.startRunning();
}
func failed() {
let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
captureSession = nil
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if (captureSession?.isRunning == false) {
captureSession.startRunning();
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if (captureSession?.isRunning == true) {
captureSession.stopRunning();
}
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
captureSession.stopRunning()
if let metadataObject = metadataObjects.first {
let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
found(code: readableObject.stringValue!);
}
dismiss(animated: true)
}
func found(code: String) {
print(code)
}
override var prefersStatusBarHidden: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}
I am using iOS 11 on my iPhone, upgraded to beta 9.
Any idea? Thank you.
I figured it out but Apple didn't make it so obvious. The callback function from the delegate AVCaptureMetadataOutputObjectsDelegate has been renamed and the parameter names are different!
So, replace
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)
to
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
My view controller is now scanning QR Codes as before after this. It has the same parameters but the first parameter name is different. Change the function and parameter names and build/run.
After changing the delegate call back :
From
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)
To
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
I need to set all available types for metadataObjectTypes too as below-
output.metadataObjectTypes=output.availableMetadataObjectTypes
After changing your code from:
func metadataOutput(captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {}
to:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {}
everything works again.
You can use QRCodeScanner83 to scan barcodes:
import QRCodeScanner83
import AVFoundation
...
guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "CodeScannerViewController") as? CodeScannerViewController else {
return
}
vc.callbackCodeScanned = { code in
print("SCANNED CODE: \(code)")
vc.dismiss(animated: true, completion: nil)
}
self.present(vc, animated: true, completion: nil)
If you need custom UI, then you can nest from CodeScannerViewController and set CodeScannerViewController.delegate to receive updates of the scanner state.
I'm new to Swift, and trying my hands with UIWebView app that loads default url, with option to perform quick action and load a different url.
Problem is when I request the quick action url, code executes but the new url is not loading. So I'm missing something in the flow somewhere.
Here is the code:
import UIKit
import WebKit
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var webView: UIWebView!
override func loadView() {
super.loadView()
self.webView = UIWebView()
self.view = self.webView!
}
override func viewDidLoad() {
print("view did load")
super.viewDidLoad()
let url = NSURL(string: "google.com")
let req = NSURLRequest(URL:url!)
webView.loadRequest(req)
webView.delegate = self
}
func loadUrl2() {
loadView()
let url = NSURL(string: "example.com")
print(url)
let req = NSURLRequest(URL:url!)
self.webView!.loadRequest(req)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I was experimenting and added loadView to loadUrl2, as I was getting
fatal error: unexpectedly found nil while unwrapping an Optional value
before that.
Edited to Include loading secondary link:
Here are the changes and files you'll need to make to the App Delegate
enum ShortcutIdentifier: String {
case OpenNewLink
case OpenBetterLink
init?(fullIdentifier: String) {
guard let shortIdentifier = fullIdentifier.componentsSeparatedByString(".").last else {
return nil
}
self.init(rawValue: shortIdentifier)
}
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsAnnotationKey] as? UIApplicationShortcutItem {
handleShortcut(shortcutItem)
return false
}
return true
}
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
completionHandler(handleShortcut(shortcutItem))
}
private func handleShortcut(shortcutItem: UIApplicationShortcutItem) -> Bool {
let shortcutType = shortcutItem.type
guard let ShortcutIdentifier = ShortcutIdentifier(fullIdentifier: shortcutType) else {
return false
}
return selectLinkForIdentifier(ShortcutIdentifier)
}
private func selectLinkForIdentifier(identifier: ShortcutIdentifier) -> Bool {
guard let mainView = self.window?.rootViewController as? ViewController else {
return false
}
switch identifier {
case .OpenNewLink:
mainView.urlString = "http://www.bing.com"
mainView.loadWebView(mainView.urlString)
return true
case.OpenBetterLink:
mainView.urlString = "http://www.duckduckgo.com"
mainView.loadWebView(mainView.urlString)
return true
}
}
I also made changes in the MainVC
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var webView: UIWebView!
var urlString: String? = nil
override func viewDidLoad() {
super.viewDidLoad()
setUpWebView()
webView.delegate = self
view.addSubview(webView)
}
func setUpWebView() {
webView = UIWebView()
webView.frame = CGRectMake(0, 0, view.frame.width, view.frame.height)
loadWebView(urlString)
}
func loadWebView(var urlString: String?) {
if urlString == nil {
urlString = "http://www.google.com"
}
let url = NSURL(string: urlString!)
let req = NSURLRequest(URL:url!)
webView.loadRequest(req)
}
}
Be sure to add NSAppTransportSecurity dictionary to your .plist and add NSAllowsArbitraryLoads key set to YES.
I tested it and it should work for you.
I have a Consumable in-app-purchase in my OS X app that purchases a certain number of coins. However, the second time I purchase the consumable, I get an alert saying that the item has already been purchased and will be restored for free.
Why is this happening with a consumable in-app-purchase?
Here is my IAP code:
typealias RequestProductsCompletionHandler = ([SKProduct]?) -> Void
class IAPHelper: NSObject, SKProductsRequestDelegate{
private var productsRequest: SKProductsRequest?
private var completionHandler: RequestProductsCompletionHandler!
private let productIdentifiers: Set<String>
private var purchasedProductIdentifiers = Set<String>()
init(productIdentifiers: Set<String>){
self.productIdentifiers = productIdentifiers
super.init()
for identifier in productIdentifiers{
let productPurchased = NSUserDefaults.standardUserDefaults().boolForKey(identifier)
if productPurchased{
purchasedProductIdentifiers.insert(identifier)
}
}
}
func requestProducts(completionHandler: RequestProductsCompletionHandler){
self.completionHandler = completionHandler
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productsRequest?.delegate = self
productsRequest?.start()
}
// MARK: SKProductsRequestDelegate
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
productsRequest = nil
let skProducts = response.products as! [SKProduct]
completionHandler(skProducts)
completionHandler = nil
}
func request(request: SKRequest, didFailWithError error: NSError) {
productsRequest = nil
print("Error: \(error)\nDescription: \(error.description)")
completionHandler(nil)
completionHandler = nil
}
func buyProduct(product: SKProduct){
let payment = SKPayment.paymentWithProduct(product) as! SKPayment
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().addPayment(payment)
}
func productPurchased(productIdentifier: String) -> Bool{
return purchasedProductIdentifiers.contains(productIdentifier)
}
}
extension IAPHelper: SKPaymentTransactionObserver{
func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) {
for transaction in transactions as! [SKPaymentTransaction]{
switch transaction.transactionState{
case SKPaymentTransactionStatePurchased:
completeTransaction(transaction)
case SKPaymentTransactionStateFailed:
failedTransaction(transaction)
default:
break
}
}
}
func completeTransaction(transaction: SKPaymentTransaction){
provideContentForProductIdentifier(transaction.payment.productIdentifier)
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
}
func failedTransaction(transaction: SKPaymentTransaction){
if let errorCode = transaction.error?.code where errorCode != SKErrorPaymentCancelled{
print(transaction.error!.localizedDescription)
}
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
}
func provideContentForProductIdentifier(productIdentifier: String){
//Override in subclass
}
}