Hey guys I am trying to retrieve and display a cloud anchor from my IOS app and never receive a delegate callback from resolve cloud anchor here is my view controller :
class ShowBooViewController: UIViewController,GARSessionDelegate, ARSessionDelegate {
var garSession : GARSession? = nil
var arScene : SCNScene? = nil
#IBOutlet weak var arSceneView: ARSCNView!
#IBAction func showBoo(_ sender: UIButton) {
let ac = UIAlertController(title: "Enter answer", message: nil, preferredStyle: .alert)
ac.addTextField()
let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned ac] _ in
//let answer = ac.textFields![0]
// do something interesting with "answer" here
}
ac.addAction(submitAction)
present(ac, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
do {
try self.garSession = GARSession.init(apiKey: "RedactedCuzSuperSecret",bundleIdentifier: nil)
self.garSession?.delegate = self
do {
try self.garSession!.resolveCloudAnchor(withIdentifier: "bgfbgfbgf")
} catch {
print("Failed")
}
} catch {
print("Failed")
print(error)
}
}
func session(_ session: GARSession, didResolve anchor: GARAnchor) {
print("session")
}
func session(_ session: GARSession, didFailToResolve anchor: GARAnchor) {
print("Session")
}
func session(_ session: GARSession, didHostAnchor anchor: GARAnchor) {
print("Session")
}
func session(_ session: GARSession, didFailToHostAnchor anchor: GARAnchor) {
print("Session")
}
}
The api key was changed to not post here but I have the actual api key in view controller, when using Xcode inspector I see that the delegate is assigned to the view controller I just do not get the session callbacks.
Related
I am working on an open source application using Xcode 9.3.1 Swift 4.
There is a play button. When the user clicks on the play button the audio file downloads automatically before it starts playing. I want to add an alert message that alerts the user, shows the file size, and lets him accept or not to proceed with the download.
Here my audiobarview.xib code:
import GenericDataSources
import QueuePlayer
import UIKit
internal protocol AdvancedAudioOptionsViewControllerDelegate : AnyObject {
internal func advancedAudioOptionsViewController(_ controller: AdvancedAudioOptionsViewController, finishedWith options: AdvancedAudioOptions)
}
internal class AdvancedAudioOptionsViewController : UIViewController, UIGestureRecognizerDelegate {
weak internal var delegate: AdvancedAudioOptionsViewControllerDelegate?
#IBOutlet weak internal var tableView: UITableView!
#IBOutlet weak internal var contentView: UIView!
#IBOutlet weak internal var bottomConstraint: NSLayoutConstraint!
#IBOutlet weak internal var navigationBar: UINavigationBar!
lazy internal var playButton: UIButton { get set }
internal init(options: AdvancedAudioOptions)
required internal init?(coder aDecoder: NSCoder)
override internal func viewDidLoad()
override internal func viewDidAppear(_ animated: Bool)
override internal func viewDidLayoutSubviews()
#IBAction internal func playButtonTapped(_ sender: Any)
#IBAction internal func dismissView(_ sender: Any)
internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
}
extension UIView {
internal func round(corners: UIRectCorner, radius: CGFloat)
}
Here is the audiofilesdownloader.swift code:
import BatchDownloader
import PromiseKit
class AudioFilesDownloader {
let audioFileList: QariAudioFileListRetrieval
let downloader: DownloadManager
let ayahDownloader: AnyInteractor<AyahsAudioDownloadRequest, DownloadBatchResponse>
private var response: DownloadBatchResponse?
init(audioFileList: QariAudioFileListRetrieval,
downloader: DownloadManager,
ayahDownloader: AnyInteractor<AyahsAudioDownloadRequest, DownloadBatchResponse>) {
self.audioFileList = audioFileList
self.downloader = downloader
self.ayahDownloader = ayahDownloader
}
func cancel() {
response?.cancel()
response = nil
}
func needsToDownloadFiles(qari: Qari, range: VerseRange) -> Bool {
let files = filesForQari(qari, range: range)
return !files.filter { !FileManager.documentsURL.appendingPathComponent($0.destinationPath).isReachable }.isEmpty
}
func getCurrentDownloadResponse() -> Promise<DownloadBatchResponse?> {
if let response = response {
return Promise(value: response)
} else {
return downloader.getOnGoingDownloads().then { batches -> DownloadBatchResponse? in
let downloading = batches.first { $0.isAudio }
self.createRequestWithDownloads(downloading)
return self.response
}
}
}
func download(qari: Qari, range: VerseRange) -> Promise<DownloadBatchResponse?> {
return ayahDownloader
.execute(AyahsAudioDownloadRequest(range: range, qari: qari))
.then(on: .main) { responses -> DownloadBatchResponse? in
// wrap the requests
self.createRequestWithDownloads(responses)
return self.response
}
}
private func createRequestWithDownloads(_ batch: DownloadBatchResponse?) {
guard let batch = batch else { return }
response = batch
response?.promise.always { [weak self] in
self?.response = nil
}
}
func filesForQari(_ qari: Qari, range: VerseRange) -> [DownloadRequest] {
return audioFileList.get(for: qari, range: range).map {
DownloadRequest(url: $0.remote, resumePath: $0.local.stringByAppendingPath(Files.downloadResumeDataExtension), destinationPath: $0.local)
}
}
}
Assuming you have the filesize as a variable filesize
Swift 4:
let alert = UIAlertController(title: "Proceed with download?", message: "File size: \(filesize)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in
// Leave empty, dismisses the alert
}))
alert.addAction(UIAlertAction(title: "Download Song", style: .default, handler: {(alert: UIAlertAction!) in
// Code to download song
}))
self.present(alert, animated: true, completion: nil)
I've successfully parsed an result from a SOAP WebServices request I made, by sending in a userName and password.
But now I need to validate this login function and if true segue to a new view programmatically:
let menuPageView = (self.storyboard?.instantiateViewController(withIdentifier: "MenuCentral"))!
self.present(menuPageView, animated: true, completion: nil)
The problem is I don't know how or where to add such validation.
class LoginCentralViewController: UIViewController, SOAPServiceProtocol {
var chave = ChaveWebService().chave()
var soapService : SOAPService?
var resultadoLoginCentral : [LoginCentralModel]!
#IBOutlet weak var txtUsuarioOUTLET: UITextField!
#IBOutlet weak var txtSenhaOUTLET: UITextField!
#IBOutlet weak var btnAcessarOUTLET: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
soapService = SOAPService(delegate: self)
print(chave)
}
#IBAction func btnAcessarACTION(_ sender: Any) {
soapService?.loginCentral(userName: txtUsuarioOUTLET.text!, password: txtSenhaOUTLET.text!, methodName: nomeServico)
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func didSuccessRequest(results: XMLIndexer, requestName: String) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
switch requestName {
case nomeServico:
do{
resultadoLoginCentral = try LoginCentralModel.realizarLoginCentral(results: results)
} catch let error as XMLParseError{
print(error.description)
return
} catch {
print(error)
return
}
print("codigoCliente = ", resultadoLoginCentral[0].codigoCliente)
print("permissoes = " , resultadoLoginCentral[0].permissoes)
break
default:
break
}
}
func didFailRequest(err: String, requestName: String) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
switch requestName {
case nomeServico:
return
default:
break
}
}
func showAlert() {
let loginAlert = UIAlertController(title: "Central do Assinante", message: "Login/Senha inválidos", preferredStyle: .alert)
let acaoDefault = UIAlertAction(title: "OK", style: .destructive, handler: nil)
loginAlert.addAction(acaoDefault)
present(loginAlert, animated: true, completion: nil)
}
}
You can put your validation code here
do{
resultadoLoginCentral = try LoginCentralModel.realizarLoginCentral(results: results)
//Put here code
// we need to call this in main thread
DispatchQueue.main.sync {
if resultadoLoginCentral.codigoCliente.characters.count > 0 && resultadoLoginCentral.permissoes.characters.count > 0{{
// Login process
}else{
//Show Alert
}
}
}
Hope this helps
I'm having problems detecting when someone presses up or down volume button. For the moment I just play a file but I want to know when the user presses the button to show an alert when the volume changes. I'm developing in Swift and I'm using AVFoundation to create this player. For the moment I can't find something that works in Swift. I'm very new to this language.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var backgroundMusicPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
playBackgroundMusic("IronBacon.mp3")
}
func playBackgroundMusic(filename:String){
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
print(url)
guard let newUrl = url else{
print("couldn't find file: \(filename)")
return
}
do{
backgroundMusicPlayer = try AVAudioPlayer(contentsOfURL: newUrl)
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
}catch let error as NSError{
print(error.description)
}
}
#IBAction func playPauseAction(sender: UIButton) {
sender.selected = !sender.selected
if sender.selected {
backgroundMusicPlayer.play()
} else {
backgroundMusicPlayer.pause()
}
}
func ShowAlert(title: String, message: String, dismiss: String) {
let alertController = UIAlertController(title: title, message:
message, preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: dismiss, style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
func volumeUp(){
ShowAlert( "example", message: "example", dismiss: "close")
}
func volumeDown(){
ShowAlert( "example", message: "example", dismiss: "close")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This should do the trick.
class ViewController: UIViewController {
// MARK: Properties
let notificationCenter = NSNotificationCenter.defaultCenter()
// MARK: Lifecycle
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
notificationCenter.addObserver(self,
selector: #selector(systemVolumeDidChange),
name: "AVSystemController_SystemVolumeDidChangeNotification",
object: nil
)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
notificationCenter.removeObserver(self)
}
// MARK: AVSystemPlayer - Notifications
func systemVolumeDidChange(notification: NSNotification) {
print(notification.userInfo?["AVSystemController_AudioVolumeNotificationParameter"] as? Float)
}
}
For some reason, the accepted answer does not work. Here is how you can do it in latest iOS versions -
func addObserver() {
NotificationCenter.default.addObserver(self,
selector: #selector(systemVolumeDidChange),
name: Notification.Name("SystemVolumeDidChange"),
object: nil)
}
func systemVolumeDidChange(notification: NSNotification) {
Log.msg("New Volume = \(notification.userInfo?["Volume"] as? Float)")
}
There are a few more fields in user info that can determine the volume change reason etc.
I am working on an assignment for a job interview. I have finished most of the assignment. There's only a bug i can't figure out. I have been trying for three days now.
I had to make a client app for the Flickr API that allows users to search for photos using specific words. Display the results in a collection view with infinite scroll. And when a photo is selected it should show the details of the photo in a detail view.
The bug:
Everything is working if i stay in the collection view. I can search over and over again and the infinite scroll is also working.As soon as a specific index in the index path is hit. A new request is sent with the same search term. But if i select a photo and then navigate back to the collection view and try a new search nothing comes back and my error handeling returns an error. (the error is not a console error).Also when navigating back from detail to collection. I can still scroll until the index triggers a new request than it also throws an error.
I hope i am explaining it well. I am really getting desperate at the moment. I tried everything i could think of: the request url still works when i try it in the browser.
Please help! If you need more info just ask.
Collection view controller:
import UIKit
// Global variable for holding a search term.
var searchTerm: String?
// Global variable to hold an instance of Reachability.
var reachability: Reachability?
// Enum for changing the textfield placeholder text.
enum TextFieldPlaceHolderText: String {
case Search = "Search"
case Searching = "Searching..."
}
class PhotosViewController: UIViewController {
// MARK: - Outlets
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var searchTextField: UITextField!
// MARK: - Properties
let photoDataSource = PhotoDataSource()
let photoStore = PhotoStore()
// MARK: - View Setup
override func viewDidLoad() {
super.viewDidLoad()
// Sets the data source and delegate.
collectionView.dataSource = photoDataSource
collectionView.delegate = self
// Uses an image to add a pattern to the collection view background.
collectionView.backgroundColor = UIColor(patternImage: UIImage(named: "flickr.png")!)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Checks if the device is connected to the internet.
checkForReachability()
}
// MARK: showAlert
func showAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Cancel, handler: { (nil) in
self.dismissViewControllerAnimated(true, completion: nil)
})
alert.addAction(okAction)
self.presentViewController(alert, animated: true, completion: nil)
}
// MARK: - Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowPhoto" {
if let selectedIndexPath = collectionView.indexPathsForSelectedItems()?.first {
let flickrPhoto = photoDataSource.flickrPhotos[selectedIndexPath.row]
let destinationVC = segue.destinationViewController as! PhotoDetailViewController
destinationVC.flickrPhoto = flickrPhoto
destinationVC.photoStore = photoStore
}
}
}
// MARK: - checkForReachability
func checkForReachability() {
do {
reachability = try Reachability.reachabilityForInternetConnection()
} catch {
print("Unable to create Reachability")
return
}
reachability!.whenReachable = { reachability in
// This is called on a background thread, but UI updates must be on the main thread.
NSOperationQueue.mainQueue().addOperationWithBlock({
if reachability.isReachableViaWiFi() {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
})
}
reachability!.whenUnreachable = { reachability in
// This is called on a background thread, but UI updates must be on the main thread.
NSOperationQueue.mainQueue().addOperationWithBlock({
print("Not reachable")
self.showAlert("No Internet Connection", message: "Make sure your device is connected to the internet.")
})
}
do {
try reachability!.startNotifier()
} catch {
print("Unable to start notifier")
}
}
}
//MARK: - Extension UICollectionViewDelegate
extension PhotosViewController: UICollectionViewDelegate {
//MARK: - willDisplayCell
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
let flickrPhoto = photoDataSource.flickrPhotos[indexPath.row]
// Downloads the image data for a thumbnail.
photoStore.fetchImageForPhoto(flickrPhoto,thumbnail: true) { (result) -> Void in
// Calls the mainthread to update the UI.
NSOperationQueue.mainQueue().addOperationWithBlock() {
// The indexpath for the photo might have changed between the time the request started and finished, so find the most recent indeaxpath
let photoIndex = self.photoDataSource.flickrPhotos.indexOf(flickrPhoto)!
let photoIndexPath = NSIndexPath(forRow: photoIndex, inSection: 0)
// When the request finishes, only update the cell if it's still visible
if let cell = collectionView.cellForItemAtIndexPath(photoIndexPath) as? PhotoCollectionViewCell {
cell.updateWithImage(flickrPhoto.image)
}
}
}
}
}
//MARK: - Extension UITextFieldDelegate
extension PhotosViewController : UITextFieldDelegate {
func textFieldShouldReturn(textField: UITextField) -> Bool {
// Checks if the textfield is not empty.
if textField.text!.isEmpty {
self.showAlert("S😉rry", message: "No search term detected, please enter a search term.")
return false
}
else {
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
textField.addSubview(activityIndicator)
activityIndicator.frame = textField.bounds
activityIndicator.startAnimating()
textField.placeholder = TextFieldPlaceHolderText.Searching.rawValue
// Sets the text that the user typed as the value for the searchTerm property.
searchTerm = textField.text!
// Fetches the photos from flickr using the user's search term.
photoStore.fetchPhotosForSearchTerm() {
(photosResult) -> Void in
// Calls the mainthread to update the UI.
NSOperationQueue.mainQueue().addOperationWithBlock() {
switch photosResult {
case let .Success(photos):
// Checks if photos were found using the search term.
if photos.count == 0 {
self.showAlert("S😞rry", message: "No images found matching your search for: \(searchTerm!), please try again.")
}
activityIndicator.removeFromSuperview()
textField.placeholder = TextFieldPlaceHolderText.Search.rawValue
// Sets the result to the data source array.
self.photoDataSource.flickrPhotos = photos
print("Successfully found \(photos.count) recent photos.")
case let .Failure(error):
self.checkForReachability()
activityIndicator.removeFromSuperview()
textField.placeholder = TextFieldPlaceHolderText.Search.rawValue
self.photoDataSource.flickrPhotos.removeAll()
self.showAlert("", message: "Something went wrong, please try again.")
print("Error fetching photo's for search term: \(searchTerm!), error: \(error)")
}
self.collectionView.reloadSections(NSIndexSet(index: 0))
}
}
textField.text = nil
textField.resignFirstResponder()
self.collectionView?.backgroundColor = UIColor.whiteColor()
return true
}
}
}
The detail view controller:
import UIKit
import Social
class PhotoDetailViewController: UIViewController {
// MARK: - Outlets
#IBOutlet var photoTitleLabel: UILabel!
#IBOutlet var photoIDLabel: UILabel!
#IBOutlet var dateTakenLabel: UILabel!
#IBOutlet var imageView: UIImageView!
// MARK: Properties
var flickrPhoto: FlickrPhoto!
var photoStore: PhotoStore!
let formatter = FlickrAPI.dateFormatter
// MARK: - View Setup
override func viewDidLoad() {
super.viewDidLoad()
//Downloads the image data for large image
photoStore.fetchImageForPhoto(flickrPhoto, thumbnail: false) { (result) -> Void in
switch result {
case let .Success(image):
// Calls the mainthread to update the UI.
NSOperationQueue.mainQueue().addOperationWithBlock() {
self.imageView.image = image
}
case let .Failure(error):
print(" Error fetching detail image for photo: \(error)")
}
}
// Formats the date a shorte date that doesn't display the time
formatter.dateStyle = .MediumStyle
formatter.timeStyle = .NoStyle
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Checks if the device is connected to the internet.
checkForReachability()
// Configures the UI.
configureView()
}
// MARK: - checkForReachability
func checkForReachability() {
do {
reachability = try Reachability.reachabilityForInternetConnection()
} catch {
print("Unable to create Reachability")
return
}
reachability!.whenReachable = { reachability in
// this is called on a background thread, but UI updates must be on the main thread, like this:
NSOperationQueue.mainQueue().addOperationWithBlock({
if reachability.isReachableViaWiFi() {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
})
}
reachability!.whenUnreachable = { reachability in
// this is called on a background thread, but UI updates must be on the main thread, like this:
NSOperationQueue.mainQueue().addOperationWithBlock({
print("Not reachable")
self.showAlert("No Internet Connection", message: "Make sure your device is connected to the internet.")
})
}
do {
try reachability!.startNotifier()
} catch {
print("Unable to start notifier")
}
}
// MARK: - configureView
func configureView() {
photoTitleLabel.text = flickrPhoto.title ?? "No title available"
photoIDLabel.text = flickrPhoto.photoID ?? "ID unknown"
dateTakenLabel.text = formatter.stringFromDate(flickrPhoto.dateTaken) ?? " Date unknown"
}
// MARK: - showShareOptions
#IBAction func showShareOptions(sender: AnyObject) {
// Configure an action sheet to show the sharing options.
let actionSheet = UIAlertController(title: "Share this photo", message: "", preferredStyle: UIAlertControllerStyle.ActionSheet)
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in
// Check if sharing to Twitter is possible.
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) {
let twitterComposeVC = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
twitterComposeVC.addImage(self.imageView.image)
self.presentViewController(twitterComposeVC, animated: true, completion: nil)
}
else {
self.showAlert("Flickr Searcher", message: "You are not logged in to your Twitter account.")
}
}
// Configure a new action to share on Facebook.
let facebookPostAction = UIAlertAction(title: "Share on Facebook", style: UIAlertActionStyle.Default) { (action) -> Void in
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) {
let facebookComposeVC = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
facebookComposeVC.addImage(self.imageView.image)
self.presentViewController(facebookComposeVC, animated: true, completion: nil)
}
else {
self.showAlert("Flickr Searcher", message: "You are not logged in to your facebook account.")
}
}
// Configure a new action to show the UIActivityViewController
let moreAction = UIAlertAction(title: "More", style: UIAlertActionStyle.Default) { (action) -> Void in
let activityViewController = UIActivityViewController(activityItems: [self.imageView.image!], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
}
let dismissAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Destructive) { (action) -> Void in
}
actionSheet.addAction(tweetAction)
actionSheet.addAction(facebookPostAction)
actionSheet.addAction(moreAction)
actionSheet.addAction(dismissAction)
presentViewController(actionSheet, animated: true, completion: nil)
}
// MARK: showAlert
func showAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Cancel, handler: { (nil) in
self.dismissViewControllerAnimated(true, completion: nil)
})
alert.addAction(okAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
My data source:
import UIKit
class PhotoDataSource: NSObject, UICollectionViewDataSource {
//MARK: - Properties
// Array to store the Flickr Photos
var flickrPhotos = [FlickrPhoto]()
// An instance of photoStore.
var photoStore = PhotoStore()
// MARK: - numberOfItemsInSection
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return flickrPhotos.count
}
// MARK: - cellForItemAtIndexPath
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let identifier = "FlickrCell"
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(identifier, forIndexPath: indexPath) as! PhotoCollectionViewCell
let photo = flickrPhotos[indexPath.item]
cell.updateWithImage(photo.image)
print(indexPath.item)
// If you get close to the end of the collection, fetch more photo's.
if indexPath.item == flickrPhotos.count - 20 {
print("Detected the end of the collection")
// Fetch the next batch of photos.
photoStore.fetchPhotosForSearchTerm() {
(photosResult) -> Void in
// Calls the mainthread to update the UI.
NSOperationQueue.mainQueue().addOperationWithBlock() {
switch photosResult {
case let .Success(photos):
print("Successfully found \(photos.count) recent photos.")
self.flickrPhotos.appendContentsOf(photos)
case let .Failure(error):
self.flickrPhotos.removeAll()
print("Error fetching more photos for search term \(error)")
}
collectionView.reloadSections(NSIndexSet(index: 0))
}
}
}
return cell
}
}
This is the method that throws the error. But only when navigated to the detail view first. Staying in the collection view the method gets call over and over with no problem:
photoStore.fetchPhotosForSearchTerm() {
(photosResult) -> Void in
// Calls the mainthread to update the UI.
NSOperationQueue.mainQueue().addOperationWithBlock() {
switch photosResult {
case let .Success(photos):
print("Successfully found \(photos.count) recent photos.")
self.flickrPhotos.appendContentsOf(photos)
case let .Failure(error):
self.flickrPhotos.removeAll()
print("Error fetching more photos for search term \(error)")
}
collectionView.reloadSections(NSIndexSet(index: 0))
}
}
I have working barcode scanner codes and it have auto opening camera with viewDidAppear i want to change it with button actions open and close i try but i dont resolve it my codes under below. ( Also i added closeCamera and openCamera actions )Thanks for help.
#IBOutlet weak var cameraView: DesignableView!
override func viewDidAppear(animated: Bool){
super.viewDidAppear(animated)
self.setupCaptureSession()
}
//MARK: Session Startup
private func setupCaptureSession(){
self.captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
do {
let deviceInput = try AVCaptureDeviceInput(device: captureDevice) as AVCaptureDeviceInput
//Add the input feed to the session and start it
self.captureSession.addInput(deviceInput)
self.setupPreviewLayer({
self.captureSession.startRunning()
self.addMetaDataCaptureOutToSession()
})
} catch let setupError as NSError {
self.showError(setupError.localizedDescription)
}
}
private func setupPreviewLayer(completion:() -> ()){
self.captureLayer = AVCaptureVideoPreviewLayer(session: captureSession) as AVCaptureVideoPreviewLayer
if let capLayer = self.captureLayer {
capLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
capLayer.frame = self.cameraView.frame
self.view.layer.addSublayer(capLayer)
completion()
}
else {
self.showError("An error occured beginning video capture.")
}
}
//MARK: Metadata capture
func addMetaDataCaptureOutToSession() {
let metadata = AVCaptureMetadataOutput()
self.captureSession.addOutput(metadata)
metadata.metadataObjectTypes = metadata.availableMetadataObjectTypes
metadata.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
}
//MARK: Delegate Methods
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
for metaData in metadataObjects {
let decodedData:AVMetadataMachineReadableCodeObject = metaData as! AVMetadataMachineReadableCodeObject
self.pCodeTextField.text = decodedData.stringValue
//decodedData.type
}
}
//MARK: Utility Functions
func showError(error:String) {
let alertController = UIAlertController(title: "Error", message: error, preferredStyle: .Alert)
let dismiss:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler:{(alert:UIAlertAction) in
alertController.dismissViewControllerAnimated(true, completion: nil)
})
alertController.addAction(dismiss)
self.presentViewController(alertController, animated: true, completion: nil)
}
#IBAction func closeCamera(sender: AnyObject) {
// HERE I WANT CLOSE CAMERA WHEN CLICKED
}
#IBAction func openCamera(sender: AnyObject) {
// HERE I WANT OPEN CAMERA WHEN CLICKED
}
Thank you.