I am learning how to create a barcode scanner and would like to add highlighting (the yellow square that goes around the numbers when the camera recognizes it)
I believe I should use isHighlightingEnabled: true
But I am not sure what line to put it on in my code. Where should I be placing it and do I need to add anything to make it work?
import UIKit
import Vision
import AVFoundation
import SafariServices
#objc class CMWSTVisionReader: UIViewController {
// MARK: - Private Variables
var captureSession = AVCaptureSession()
#IBOutlet weak var cameraView: UIView!
#IBOutlet weak var barcodeResult: UILabel!
// TODO: Make VNDetectBarcodesRequest variable
lazy var detectBarcodeRequest = VNDetectBarcodesRequest { request, error in
guard error == nil else {
// self.showAlert(
// withTitle: "Barcode error",
// message: error?.localizedDescription ?? "error")
return
}
self.processClassification(request)
}
// MARK: - Override Functions
override func viewDidLoad() {
super.viewDidLoad()
checkPermissions()
setupCameraLiveView()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// TODO: Stop Session
captureSession.stopRunning()
}
}
extension CMWSTVisionReader {
// MARK: - Camera
private func checkPermissions() {
// TODO: Checking permissions
switch AVCaptureDevice.authorizationStatus(for: .video) {
// 1
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { [self] granted in
if !granted {
showPermissionsAlert()
}
}
// 2
case .denied, .restricted:
showPermissionsAlert()
// 3
default:
return
}
}
private func setupCameraLiveView() {
// TODO: Setup captureSession
captureSession.sessionPreset = .hd1280x720
// TODO: Add input
// 1
let videoDevice = AVCaptureDevice
.default(.builtInWideAngleCamera, for: .video, position: .back)
// 2
guard
let device = videoDevice,
let videoDeviceInput = try? AVCaptureDeviceInput(device: device),
captureSession.canAddInput(videoDeviceInput)
else {
// 3
showAlert(
withTitle: "Cannot Find Camera",
message: "There seems to be a problem with the camera on your device.")
return
}
// 4
captureSession.addInput(videoDeviceInput)
// TODO: Add output
let captureOutput = AVCaptureVideoDataOutput()
// TODO: Set video sample rate
captureOutput.videoSettings =
[kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
captureOutput.setSampleBufferDelegate(
self,
queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default))
captureSession.addOutput(captureOutput)
configurePreviewLayer()
// TODO: Run session
captureSession.startRunning()
}
// MARK: - Vision
func processClassification(_ request: VNRequest) {
// TODO: Main logic
// 1
guard let barcodes = request.results else { return }
DispatchQueue.main.async { [self] in
if captureSession.isRunning {
view.layer.sublayers?.removeSubrange(1...)
// 2
for barcode in barcodes {
guard
// TODO: Check for QR Code symbology and confidence score
let potentialQRCode = barcode as? VNBarcodeObservation,
potentialQRCode.confidence > 0.9
else { return }
// 3
observationHandler(payload: potentialQRCode.payloadStringValue)
}
}
}
}
// MARK: - Handler
func observationHandler(payload: String?) {
// TODO: Open it in Safari
// 1
barcodeResult.text = payload
// guard
// let payloadString = payload,
// let url = URL(string: payloadString),
// ["http", "https"].contains(url.scheme?.lowercased())
// else { return }
//
// // 2
// let config = SFSafariViewController.Configuration()
// config.entersReaderIfAvailable = true
//
// // 3
// let safariVC = SFSafariViewController(url: url, configuration: config)
// safariVC.delegate = self
// present(safariVC, animated: true)
}
}
// MARK: - AVCaptureDelegation
extension CMWSTVisionReader: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// TODO: Live Vision
// 1
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
// 2
let imageRequestHandler = VNImageRequestHandler(
cvPixelBuffer: pixelBuffer,
orientation: .right)
// 3
do {
try imageRequestHandler.perform([detectBarcodeRequest])
} catch {
print(error)
}
}
}
// MARK: - Helper
extension CMWSTVisionReader {
private func configurePreviewLayer() {
let cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer.videoGravity = .resizeAspectFill
cameraPreviewLayer.connection?.videoOrientation = .portrait
cameraPreviewLayer.frame = cameraView.frame
cameraView.layer.insertSublayer(cameraPreviewLayer, at: 0)
}
private func showAlert(withTitle title: String, message: String) {
DispatchQueue.main.async {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true)
}
}
private func showPermissionsAlert() {
showAlert(
withTitle: "Camera Permissions",
message: "Please open Settings and grant permission for this app to use your camera.")
}
}
// MARK: - SafariViewControllerDelegate
extension CMWSTVisionReader: SFSafariViewControllerDelegate {
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
captureSession.startRunning()
}
}
Related
I want my swift code to call the playSound and play the sound based for the duration of each item in array playamount. So I want the user to play the sound for the first time for 10 seconds then play the sound starting at the beginning for 20 and then the same thing for 30 seconds. So the sound always starts at the beginning each time it is called.
import UIKit; import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer?
func playSound() {
let url = Bundle.mainBundle().URLForResource("rock", withExtension: "mp3")!
do {
player = try AVAudioPlayer(contentsOfURL: url)
guard let player = player else { return }
player.prepareToPlay()
player.play()
} catch let error as NSError {
print(error.description)
}
}
var playAmount : [Int] = [10,20,30]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
class ViewController: UIViewController {
var player: AVAudioPlayer?
var currentIndex: Int = 0
func runMusicBox() {
guard !playAmount.isEmpty else { return }
currentIndex = 0
newTimerForIndex(index: 0)
}
func newTimerForIndex(index: Int) {
player?.prepareToPlay()
player?.play()
Timer.scheduledTimer(withTimeInterval: Double(playAmount[index]), repeats: false) { timer in
self.player?.stop()
if self.currentIndex + 1 < self.playAmount.count {
self.currentIndex += 1
self.newTimerForIndex(index: self.currentIndex)
} else {
self.player?.stop()
}
}
}
func playSound() {
let url = Bundle.mainBundle().URLForResource("rock", withExtension: "mp3")!
do {
player = try AVAudioPlayer(contentsOfURL: url)
guard let player = player else { return }
runMusicBox()
} catch let error as NSError {
print(error.description)
}
}
var playAmount : [Int] = [10,20,30]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Hi, can you try this code. Here I have a timer, and when one stops, then we check if we have another element in the array and will run a new timer. The Timer is working, but i didn;t check the player. if it works as expected - it should work for you
If a person presses the button 10 times, then they will hear 10 different lists of songs being played continuously. I want it to be that if a person presses 10 times, they will only be listening to one list of songs. I'm basically trying to create a reset button.
var myQueuePlayer: AVQueuePlayer?
var avItems: [AVPlayerItem] = []
func audio () {
var items: [String] = ["one", "two", "three", "four", "five"]
items.shuffle()
for clip in items {
guard let url = Bundle.main.url(forResource: clip, withExtension: ".mp3") else {
// mp3 file not found in bundle - so crash!
fatalError("Could not load \(clip).mp3")
}
avItems.append(AVPlayerItem(url: url))
//button.isHidden = true
}
}
#IBAction func didTapButton() {
audio()
if myQueuePlayer == nil {
// instantiate the AVQueuePlayer with all avItems
myQueuePlayer = AVQueuePlayer(items: avItems)
} else {
// stop the player and remove all avItems
myQueuePlayer?.removeAllItems()
// add all avItems back to the player
avItems.forEach {
myQueuePlayer?.insert($0, after: nil)
}
}
// seek to .zero (in case we added items back in)
myQueuePlayer?.seek(to: .zero)
// start playing
myQueuePlayer?.play()
}
Here is a very simple example.
This assumes 5 .mp3 files in your bundle, and 4 buttons:
Play / Restart
Pause
Resume
Shuffle and Play
connected to the #IBAction funcs:
class TestAVQueuViewController: UIViewController {
var myQueuePlayer: AVQueuePlayer?
var avItemsArray: [AVPlayerItem] = []
override func viewDidLoad() {
super.viewDidLoad()
// assuming I have 5 .mp3 files in the bundle, named:
let mySongs: [String] = [
"clip1", "clip2", "clip3", "clip4", "clip5",
]
// build the array of URLs for the song files
for clip in mySongs {
if let url = Bundle.main.url(forResource: clip, withExtension: ".mp3") {
avItemsArray.append(AVPlayerItem(url: url))
} else {
print("Could not get URL for \(clip).mp3")
}
}
if avItemsArray.count == 0 {
fatalError("Failed to get URL for ANY songs!")
}
}
func playQueue() -> Void {
// if first time
if myQueuePlayer == nil {
// instantiate the AVQueuePlayer
myQueuePlayer = AVQueuePlayer()
}
guard let player = myQueuePlayer else {
// I suppose it's possible that AVQueuePlayer() failed to instantiate
// so print a message to debug console and return
print("AVQueuePlayer failed to instantiate!")
return
}
// this will make sure the player is stopped and remove any remaining avItems
player.removeAllItems()
// every time this is called,
// loop through and reset the time on each avItem
for item in avItemsArray {
item.seek(to: .zero, completionHandler: nil)
}
// add avItems to the player
avItemsArray.forEach {
player.insert($0, after: nil)
}
// start playing
player.play()
}
#IBAction func playRestartTapped(_ sender: Any) {
playQueue()
}
#IBAction func pauseTapped(_ sender: Any) {
guard let player = myQueuePlayer, player.items().count > 0 else {
return
}
player.pause()
}
#IBAction func resumeTapped(_ sender: Any) {
guard let player = myQueuePlayer, player.items().count > 0 else {
return
}
player.play()
}
#IBAction func restartShuffledTapped(_ sender: Any) {
// shuffle the items
avItemsArray.shuffle()
playQueue()
}
}
I've been looking around on stackoverflow for a solution but I haven't yet successfully implemented it. If someone can give me some tips on where the problem lies, thank you so much. Here is what I have so far
Here is location class
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
Method to display all annotations.
func displayAllEventsPins() {
for event in events {
let address = event.location
geocoder.geocodeAddressString(address!, completionHandler: { (placemarks: [CLPlacemark]?, error: Error?) -> Void in
if let placemark = placemarks?.first {
let eventlat = placemark.location?.coordinate.latitude
let eventlong = placemark.location?.coordinate.longitude
let annotation = MKPointAnnotation()
annotation.title = event.name
annotation.coordinate = CLLocationCoordinate2D(latitude: eventlat!, longitude: eventlong!)
self.locations.append(Location(title: annotation.title!, coordinate: annotation.coordinate))
for location in self.locations {
let pin = MKPointAnnotation()
pin.title = location.title
pin.coordinate = location.coordinate
self.mapView.addAnnotation(pin)
}
}
})
}
}
Edited: The problem here is that annotations doesnt show up on mapview. I can only see the currentlocation pin and nothing else.
Edited: This is the call i used to drop user current location pin.
extension Search : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//MARK: remove previous current pin for user location
mapView.removeAnnotation(newPin)
let location = locations.last! as CLLocation
let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
self.currentLocation = location
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.03, 0.03))
mapView.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
mapView.addAnnotation(newPin)
}
}
Here is the code in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
//MARK: Request Current Location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
locationManager.requestLocation()
displayAllEventsPins()
}
This should work for you.
By the way, looping through your locations whilst in the events loop is just going to add duplicates of the same pin, which will be very bad on memory and it's not a good thing to do.
import UIKit
import MapKit
import Firebase
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
var events = Array<Event>()
var locations = Array<Location>()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// This closure gets called once for every event in your database
getEvents { (event, pin) in
self.tableView.reloadData()
if event != nil && pin != nil {
print(event!)
self.locations.append(pin!)
self.events.append(event!)
} else {
print("Failed to get event.")
}
}
}
func getEvents(results: #escaping (_ event: Event?, _ pin:Location?)->()) {
let ref = FIRDatabase.database().reference().child("Events")
ref.observe(.childAdded, with: { (snapshot) in
guard let value = snapshot.value as? Dictionary<String,String> else { return }
guard let name = value["eventName"],
let location = value["location"],
let attending = value["attendance"],
let dateTime = value["dateTime"],
let addedByUser = value["addedByUser"] else { return }
self.getEventPlacemark(address: location, results: { (placemark) in
if let placemark = placemark {
let pin = Location(title: name, coordinate: placemark.coordinate)
var distance: Double = -1 // If user location is not avalible, this will stay at -1
if let currentLocation = self.locationManager.location?.coordinate {
distance = pin.coordinate.distance(to: currentLocation)
}
let event = Event(id: snapshot.key, name: name, location: location, dateTime: dateTime, addedByUser: addedByUser, attending: attending, distance: distance)
results(event, pin)
return
}
})
})
}
func getEventPlacemark(address:String, results: #escaping (_ placemark: MKPlacemark?)->()){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
if let error = error {
print(error.localizedDescription)
results(nil)
}
if let placemark = placemarks?.first {
results(MKPlacemark(placemark: placemark))
}
}
}
func displayAllEvents(){
self.map.addAnnotations(self.locations)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let userLocation = annotation as? MKUserLocation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "userLocationPin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: userLocation, reuseIdentifier: "userLocationPin")
view.pinTintColor = .purple
view.canShowCallout = true
return view
}
if let pin = annotation as? MKPointAnnotation {
let view = (mapView.dequeueReusableAnnotationView(withIdentifier: "pin") as? MKPinAnnotationView) ?? MKPinAnnotationView(annotation: pin, reuseIdentifier: "pin")
view.pinTintColor = .red
view.canShowCallout = true
return view
}
return nil
}
}
class Location: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
}
struct Event {
var name: String
var location: String
}
extension CLLocationCoordinate2D {
func distance(to: CLLocationCoordinate2D) -> CLLocationDistance {
return MKMetersBetweenMapPoints(MKMapPointForCoordinate(self), MKMapPointForCoordinate(to))
}
}
If you are going to implement my code above, you'll need to remove your code from
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
because you don't need to add the pin manually anymore.
Can you try putting this in your view did load function and not have anything else run. This should put a pin to the west of Africa.
Something to notice, if the coordinate is
CLLocationCoordinate2D(latitude: 0, longitude: 0), the pin appears
right down at Antartica on the date line, which is the bottom right of
the map. So if for some reason your coordinate is the default 0,0,
your pins might by sitting there.
let pin = MKPointAnnotation()
pin.title = "Null Island"
pin.coordinate = CLLocationCoordinate2DMake(0.000001, 0.000001)
self.map.addAnnotation(pin)
This could possibly be where your pins are.
I have 2 arrays
var messages = [Message]()
var screenMessages = [screenMessage]()
I have the messages array items in a NSTableView.. when I press an IBOutlet I would like to pass the items in that row to the screenMessages array to present in another NSTableView.
My NSTableView starts like so..
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
I've tried a number of ways of appending the screenMessages with the messages[row] but I can't put my finger on it. If anyone could demonstrate or point me in the right direction that would be brilliant.
Thank you.
Added more detail:
Screen one looks like so and when pressing the add button it should then pass that data from that row into screen twos tableview..
Screen two:
My View for screen one is as:
import Firebase
import Cocoa
var messages = [Message]()
var screenMessages = [screenMessage]()
class secondVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var screenRefreshBtn: NSButton!
#IBOutlet weak var refreshButton: NSButton!
var senderImageUrl: String!
var ref: Firebase!
var messagesRef: Firebase!
func setupFirebase() {
messagesRef = Firebase(url: "https://url.firebaseio.com/screenmessages")
messagesRef.queryLimitedToLast(25).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in
let text = snapshot.value["text"] as? String
let sender = snapshot.value["senderName"] as? String
let imageUrl = snapshot.value["profileImageURL"] as? String
let MediaType = snapshot.value["MediaType"] as! String
let fileUrl = snapshot.value["fileUrl"] as? String
let message = Message(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
messages.append(message)
let screenmessage = screenMessage(text: text, sender: sender, imageUrl: imageUrl, MediaType: MediaType, fileUrl: fileUrl)
screenMessages.append(screenmessage)
switch MediaType{
case "TEXT":
print("text message")
case "PHOTO":
print("photo message")
default:
print("default")
}
self.tableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
setupFirebase()
}
// MARK: - Table View
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return messages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell", owner: self) as? secondviewTableCell
let mess = messages[row]
if mess.text() == nil {
result?.textField?.alphaValue = 0
result!.sendertextView.stringValue = mess.sender()
let url = NSURL(string: mess.fileUrl()!)!
// Download task:
// - sharedSession = global NSURLCache, NSHTTPCookieStorage and NSURLCredentialStorage objects.
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
// if responseData is not null...
if let data = responseData{
// execute in UI thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
task.resume()
} else {
result!.textField!.stringValue = mess.text()!
result!.sendertextView.stringValue = mess.sender()
}
return result
}
#IBAction func addtablerow(object: NSButton) {
let row = tableView.rowForView( object as NSView )
if ( row > -1 ) {
}
}
And my second screen is:
import Cocoa
class screenVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
var addedObserver = false
#IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
refreshObs()
clearObs()
self.tableView.backgroundColor = NSColor.clearColor()
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
} else {
addedObserver = true
self.addObserver(self, forKeyPath: "view.window", options: [.New, .Initial], context: nil)
}
}
func refreshList(notification: NSNotification){
self.tableView.alphaValue = 0
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
animateViewRefresh()
tableView.scrollToEndOfDocument(self)
}
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return screenMessages.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result = tableView.makeViewWithIdentifier("cell2", owner: self) as? screenviewTableCell
let mess = screenMessages[row]
result?.senderLabel.stringValue = mess.sender()
if mess.text() != nil {
result?.messageTextView.stringValue = mess.text()!
let url = NSURL(string: mess.imageUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
} else {
result?.messageTextView.alphaValue = 0
let mess = screenMessages[row]
let url = NSURL(string: mess.fileUrl()!)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let photo = NSImage(data: data)!
result?.mediaPhoto.image = photo
})
}
}
let url2 = NSURL(string: mess.imageUrl()!)!
let task2 = NSURLSession.sharedSession().dataTaskWithURL(url2) { (responseData, responseUrl, error) -> Void in
if let data = responseData{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
result?.avatarImage.image = NSImage(data: data)
})
}}
task.resume()
task2.resume()
}
return result
}
// MARK : Animate
func animateView(notification: NSNotification){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 2
self.tableView.animator().alphaValue = 0
screenMessages.removeAll()
}, completionHandler: { () -> Void in
})}
func animateViewRefresh(){
NSAnimationContext.runAnimationGroup({ (context) in
context.duration = 4
self.tableView.animator().alphaValue = 1
}, completionHandler: { () -> Void in
})}
func refreshObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.refreshList(_:)), name:"refreshMyTableView", object: nil)
}
func clearObs(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(screenVC.animateView(_:)), name:"clearMyTableView", object: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let window = self.view.window {
// custom window here
window.level = Int(CGWindowLevelForKey(.FloatingWindowLevelKey))
window.titlebarAppearsTransparent = true
window.movableByWindowBackground = true
window.opaque = true
window.backgroundColor = NSColor.clearColor()
}
}
deinit {
if addedObserver {
self.removeObserver(self, forKeyPath: "view.window")
}
}
}
I have tried a number of things such as 'screenMessages += messages(row)' and appending to add that row to the screenMessages array but I've had no luck.
Am I going about this in the right way or is there a better way of doing so?
Thank you.
To append an element from one array to another array just write
let index = index of element you need
let message = messages[index]
screenMessages.append(message)
If message is not the same type as the contents of the screenMessages array you will need to convert it, I would need more details of the types to help with that.
If you are having trouble passing the data to another ViewController I would need more information on the current architecture to give good advice, but for example you might define a protocol MessageDelegate that one of the controllers implements and the other has as a property.
update
If you update your data array for a table and want the new information to appear remember to call reloadData on the UITableView
I'm new to Swift.
I have the following classes used to map a GET JSON response.
class BasketballTeamResponse: Mappable {
var name: String?
var alias: String?
var market: String?
var founded: Int?
var players: [Players]?
required init?(_ map: Map){ }
func mapping(map: Map) {
name <- map["name"]
alias <- map["alias"]
market <- map["market"]
founded <- map["founded"]
players <- map["players"]
}
}
class Players: Mappable {
var full_name: String?
var jersey_number: String?
var position: String?
init(full_name: String, jersey_number: String, position: String) {
self.full_name = full_name
self.jersey_number = jersey_number
self.position = position
}
required init?(_ map: Map) { }
func mapping (map: Map) {
full_name <- map["full_name"]
jersey_number <- map["jersey_number"]
position <- map["position"]
}
}
Let's say I have a ViewController and I want to populate finalRoster with an array of objects of Players. I've tried the appending with self and finalRoster is still empty and I want to use this later on to display them in a tableview. I even tried setting the return type to -> [Players]
class ViewController: UIViewController {
var finalRoster = [Players]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
getBasketBallTeamPlayers()
}
private func getBasketBallTeamPlayers() {
let URL = "http://api.sportradar.us/nba-t3/teams/583ec825-fb46-11e1-82cb-f4ce4684ea4c/profile.json?api_key=xxxxxxxxxxxxxxxxxxxxxxxx"
//var pool = [Players]()
Alamofire.request(.GET, URL, parameters: nil)
.validate()
.responseObject { (response: Response<BasketBallTeamResponse, NSError>) in
let gswResponse = response.result.value
if let roster = gswResponse?.players {
for players in roster {
print(players.full_name!)
print(players.jersey_number!)
print(players.position!)
let add = Players(full_name: players.full_name!, jersey_number: players.jersey_number!, position: players.position!)
self.finalRoster.append(add)
}
}
}
}
How can I pass the array of objects from getBasketBallTeamPlayers() to finalRoster? Thanks
As jtbandes have comment it's better to call the class Player instead of Players.
typealias apiSuccess = (result: Player?) -> Void
typealias apiFailure = (error: NSDictionary?) -> Void
class ViewController: UIViewController {
var finalRoster = [Player]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myApiSuccess: apiSuccess = {(result: Player?) -> Void in
print ("Api Success : result is:\n \(result)")
// Here you can make whatever you want with result
self.finalRoster.append(result!)
}
let myApiFailure: apiFailure = {(error: NSDictionary?) -> Void in
print ("Api Failure : error is:\n \(error)")
// Here you can check the errors with error dictionary looking for http error type or http status code
}
getBasketBallTeamPlayers(success: myApiSuccess, failure: myApiFailure)
}
private func getBasketBallTeamPlayers(success successBlock :apiSuccess,
failure failureBlock :apiFailure) {
let URL = "http://api.sportradar.us/nba-t3/teams/583ec825-fb46-11e1-82cb-f4ce4684ea4c/profile.json?api_key=xxxxxxxxxxxxxxxxxxxxxxxx"
//var pool = [Players]()
Alamofire.request(.GET, URL, parameters: nil)
.validate()
.responseObject { (response: Response<BasketBallTeamResponse, NSError>) in
if response.result.isSuccess {
let gswResponse = response.result.value
if let roster = gswResponse?.players {
for players in roster {
print(players.full_name!)
print(players.jersey_number!)
print(players.position!)
let add = Players(full_name: players.full_name!, jersey_number: players.jersey_number!, position: players.position!)
successBlock(result: add)
}
} else {
print("I have some kind of error in my data")
}
} else {
let httpError: NSError = response.result.error!
let statusCode = httpError.code
let error:NSDictionary = ["error" : httpError,"statusCode" : statusCode]
failureBlock(error: error)
}
}
}
}