Cannot list recorded files to a TableView - ios

I am in some desperate need of assistance, since my head is really sore from beating it against the wall.
I have one view controller where I am recording audio with my microphone and saving it to the apps document directory. This is working well and I can see the files if I navigate to that folder in the simulator.
My problem is that I have a TableView with its own TableViewController where I want to list the contents of that document directory that contains my recordings. I created the TableView and it is reading and populating the table based on a basic array. My problem is that I am failing to convert it over to read the Document Directory contents instead.
I have future goals for this table to also allow me play, delete, or rename the file from within this TableView via swiping the particular cell.
I have been working on this issue for about 5 days now and I am certain I am overlooking something very simple to you all.
I am using Xcode 7.3.1 with Swift 2.
Thanks in advance and I can't wait until I get to a point where I can contribute.
ViewControllerRecorder.swift
(This is where I record and save the audio to the Document Directory, which is working.)
import UIKit
import AVFoundation
import PermissionScope
class ViewControllerRecorder: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
#IBOutlet weak var stopButton: UIButton!
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var playButton: UIButton!
#IBOutlet weak var audioDuration: UISlider!
var audioRecorder:AVAudioRecorder?
var audioPlayer:AVAudioPlayer?
let pscope = PermissionScope()
override func viewDidLoad() {
super.viewDidLoad()
audioDuration.value = 0.0
// Set up permissions
pscope.addPermission(MicrophonePermission(),
message: "Inorder to use this app, you need to grant the microphone permission")
// Show dialog with callbacks
pscope.show({ finished, results in
print("got results \(results)")
}, cancelled: { (results) -> Void in
print("thing was cancelled")
})
// Disable Stop/Play button when application launches
stopButton.enabled = false
playButton.enabled = false
// Get the document directory. If fails, just skip the rest of the code
guard let directoryURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first else {
let alertMessage = UIAlertController(title: "Error", message: "Failed to get the document directory for recording the audio. Please try again later.", preferredStyle: .Alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alertMessage, animated: true, completion: nil)
return
}
// Set the default audio file
let audioFileURL = directoryURL.URLByAppendingPathComponent("PWAC_" + NSUUID().UUIDString + ".m4a")
// Setup audio session
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)
// Define the recorder setting
let recorderSetting: [String: AnyObject] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 32000.0,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.Medium.rawValue
]
// Initiate and prepare the recorder
audioRecorder = try AVAudioRecorder(URL: audioFileURL, settings: recorderSetting)
audioRecorder?.delegate = self
audioRecorder?.meteringEnabled = true
audioRecorder?.prepareToRecord()
} catch {
print(error)
}
}
func updateaudioDuration(){
audioDuration.value = Float(audioPlayer!.currentTime)
}
#IBAction func sliderAction(sender: AnyObject) {
audioPlayer!.currentTime = NSTimeInterval(audioDuration.value)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func play(sender: AnyObject) {
if let recorder = audioRecorder {
if !recorder.recording {
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: recorder.url)
audioDuration.maximumValue = Float(audioPlayer!.duration)
_ = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: #selector(ViewControllerRecorder.updateaudioDuration), userInfo: nil, repeats: true)
audioPlayer?.delegate = self
audioPlayer?.play()
playButton.setImage(UIImage(named: "playing"), forState: UIControlState.Selected)
playButton.selected = true
} catch {
print(error)
}
}
}
}
#IBAction func stop(sender: AnyObject) {
recordButton.setImage(UIImage(named: "record"), forState: UIControlState.Normal)
recordButton.selected = false
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
stopButton.enabled = false
playButton.enabled = true
audioRecorder?.stop()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
} catch {
print(error)
}
}
#IBAction func record(sender: AnyObject) {
// Stop the audio player before recording
if let player = audioPlayer {
if player.playing {
player.stop()
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
}
}
if let recorder = audioRecorder {
if !recorder.recording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
// Start recording
recorder.record()
recordButton.setImage(UIImage(named: "recording"), forState: UIControlState.Selected)
recordButton.selected = true
} catch {
print(error)
}
} else {
// Pause recording
recorder.pause()
recordButton.setImage(UIImage(named: "pause"), forState: UIControlState.Normal)
recordButton.selected = false
}
}
stopButton.enabled = true
playButton.enabled = false
}
// MARK: - AVAudioRecorderDelegate Methods
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
if flag {
// iOS8 and later
let alert = UIAlertController(title: "Recorder",
message: "Finished Recording",
preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Keep", style: .Default, handler: {action in
print("keep was tapped")
}))
alert.addAction(UIAlertAction(title: "Delete", style: .Default, handler: {action in
print("delete was tapped")
self.audioRecorder!.deleteRecording()
}))
self.presentViewController(alert, animated:true, completion:nil)
// let alertMessage = UIAlertController(title: "Finish Recording", message: "Successfully recorded the audio!", preferredStyle: .Alert)
// alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
// presentViewController(alertMessage, animated: true, completion: nil)
print("Audio has finished recording")
print(recorder.url)
}
}
// MARK: - AVAudioPlayerDelegate Methods
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
playButton.setImage(UIImage(named: "play"), forState: UIControlState.Normal)
playButton.selected = false
let alertMessage = UIAlertController(title: "Finish Playing", message: "Finish playing the recording!", preferredStyle: .Alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alertMessage, animated: true, completion: nil)
print("Audio has finished playing")
print(player.url)
}
}
ViewControllerFileManager.swift
(This is the view controller that I want to display the contents of the document directory to a TableView.)
UPDATED 2016/07/27
import UIKit
class ViewControllerFileManager: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayRecordings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let fileManager = NSFileManager.defaultManager()
let dirPath = NSBundle.mainBundle().resourcePath!
let items = try! fileManager.contentsOfDirectoryAtPath(dirPath)
for item in items {
if item.hasSuffix("m4a") {
arrayRecordings.append(item)
}
print("Found \(item)")
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return arrayRecordings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = arrayRecordings[indexPath.row]
return cell
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}

If you are populating the array in viewDidLoad, you need to call reloadData of tableView for it to refresh.
override func viewDidLoad()
{
super.viewDidLoad()
// populate recordingFileNames here
// refresh your table
reloadTableViewContent()
}
func reloadTableViewContent()
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
self.tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
})
}

Here is the code that I got working to populate a TableView with the contents of my apps Document Folder
import UIKit
class ViewControllerFileManager: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayRecordings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// MARK: Read Document Directory and populate Array
// Get the document directory url:
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
do {
// Get the directory contents urls (including subfolders urls):
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL( documentsUrl, includingPropertiesForKeys: nil, options: [])
print(directoryContents)
// Filter directory contents:
let audioFiles = directoryContents.filter{ $0.pathExtension == "m4a" }
print("m4a urls:",audioFiles)
// Get the File Names:
let audioFileNames = audioFiles.flatMap({$0.URLByDeletingPathExtension?.lastPathComponent})
print("m4a list:", audioFileNames)
for audioFileName in audioFileNames {
arrayRecordings.append(audioFileName)
print("Found \(audioFileName)")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
// MARK: TableView Functions
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return arrayRecordings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = arrayRecordings[indexPath.row]
return cell
}
// MARK: Standard Functions
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}

Related

provideAPIKey: should be called at most once (Swift)

I'm using Google maps and places API and i'm trying to load nearby places in a tableView but everytime i come in this class
import UIKit
import MapKit
import CoreLocation
import GoogleMaps
import GooglePlaces
import Social
import AVFoundation
private let resueIdentifier = "MyTableViewCell"
extension UIViewController {
func present(viewController : UIViewController, completion : (() -> ())? = nil ){
if let presented = self.presentedViewController {
presented.dismiss(animated: true, completion: {
self.present(viewController, animated: true, completion: completion)
})
} else {
self.present(viewController, animated: true, completion: completion)
}
}
}
class CourseClass2: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
struct User {
var name: String
var images: UIImage
var type: String
}
var previuosViewTappedButtonsArray = [String]()
var locationManager:CLLocationManager?
let minimumSpacing : CGFloat = 15 //CGFloat(MAXFLOAT)
let cellWidth: CGFloat = 250
let radius = 5000 // 5km
var category : QCategoryy?
var currentLocation : CLLocationCoordinate2D?
var places: [QPlace] = []
var isLoading = false
var response : QNearbyPlacesResponse?
var rows = 0
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = category?.name
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
determineMyCurrentLocation()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
rows = 0
insertRowsMode3()
tableView.reloadData()
category?.markView()
}
#IBAction func refreshTapped(_ sender: Any) {
rows = 0
insertRowsMode3()
tableView.reloadData()
}
func canLoadMore() -> Bool {
if isLoading {
return false
}
if let response = self.response {
if (!response.canLoadMore()) {
return false
}
}
return true
}
func loadPlaces(_ force:Bool) {
if !force {
if !canLoadMore() {
return
}
}
print("load more")
isLoading = true
NearbyPlaces.getNearbyPlaces(by: category?.name ?? "food", coordinates: currentLocation!, radius: radius, token: self.response?.nextPageToken, completion: didReceiveResponse)
}
func didReceiveResponse(response:QNearbyPlacesResponse?, error : Error?) -> Void {
if let error = error {
let alertController = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let actionDismiss = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
let actionRetry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
})
alertController.addAction(actionRetry)
alertController.addAction(actionDismiss)
DispatchQueue.main.async {
self.present(viewController: alertController)
}
}
if let response = response {
self.response = response
if response.status == "OK" {
if let placesDownloaded = response.places {
places.append(contentsOf: placesDownloaded)
}
self.tableView?.reloadData()
} else {
let alert = UIAlertController.init(title: "Error", message: response.status, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction.init(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
}))
self.present(viewController: alert)
}
isLoading = false
}
else {
print("response is nil")
}
}
func insertRowsMode2() {
tableView.beginUpdates()
for i in 0..<places.count {
insertRowMode2(ind: i, usr: places[i])
}
tableView.endUpdates()
}
func insertRowMode2(ind:Int,usr:QPlace) {
tableView.beginUpdates()
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
tableView.endUpdates()
}
func insertRowsMode3() {
tableView.beginUpdates()
rows = 0
insertRowMode3(ind: 0)
tableView.endUpdates()
}
func insertRowMode3(ind:Int) {
tableView.beginUpdates()
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
guard ind < places.count-1 else { return }
DispatchQueue.main.asyncAfter(deadline: .now()+0.20) {
self.insertRowMode3(ind: ind+1)
}
tableView.endUpdates()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places.count /* rows */
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
let place = places[indexPath.row]
cell.update(place: place)
if indexPath.row == places.count - 1 {
loadPlaces(false)
}
/* let user = users[indexPath.row]
cell.selectionStyle = .none
cell.myImage.image = user.images
cell.myLabel.text = user.name
cell.myTypeLabel.text = user.type */
return (cell)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
UIView.animate(withDuration: 0.2, animations: {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
})
performSegue(withIdentifier: "goToLast" , sender: users[indexPath.row])
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
places.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
func didReceiveUserLocation(_ userLocation:CLLocation) {
currentLocation = userLocation.coordinate
loadPlaces(true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToLast" && sender is IndexPath {
let dvc = segue.destination as! FinalClass
dvc.index = (sender as! IndexPath).row
dvc.places = places
dvc.userLocation = currentLocation
/* guard let vc = segue.destination as? FinalClass else { return }
let guest = segue.destination as! FinalClass
if let user = sender as? User {
*/
}
}
#IBAction func IndTapped(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func socialShare(_ sender: Any) {
//Alert
let alert = UIAlertController(title: "Share", message: "First share!", preferredStyle: .actionSheet)
//First action
let actionOne = UIAlertAction(title: "Share on Facebook", style: .default) { (action) in
//Checking if user is connected to Facebook
if SLComposeViewController.isAvailable(forServiceType: SLServiceTypeFacebook)
{
let post = SLComposeViewController(forServiceType: SLServiceTypeFacebook)!
post.setInitialText("First")
post.add(UIImage(named: "uround logo.png"))
self.present(post, animated: true, completion: nil)
} else {self.showAlert(service: "Facebook")}
}
let actionThree = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
//Add action to action sheet
alert.addAction(actionOne)
alert.addAction(actionThree)
//Present alert
self.present(alert, animated: true, completion: nil)
}
func showAlert(service:String)
{
let alert = UIAlertController(title: "Error", message: "You are not connected to \(service)", preferredStyle: .alert)
let action = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
extension CourseClass2: CLLocationManagerDelegate {
func determineMyCurrentLocation() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
didReceiveUserLocation(userLocation)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
errorGettingCurrentLocation(error.localizedDescription)
}
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager?.startUpdatingLocation()
//locationManager.startUpdatingHeading()
} else if status == .denied || status == .restricted {
errorGettingCurrentLocation("Location access denied")
}
}
func errorGettingCurrentLocation(_ errorMessage:String) {
let alert = UIAlertController.init(title: "Error", message: errorMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
}
i get the message "error - response status" from this function
func didReceiveResponse(response:QNearbyPlacesResponse?, error : Error?) -> Void {
if let error = error {
let alertController = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let actionDismiss = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
let actionRetry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
})
alertController.addAction(actionRetry)
alertController.addAction(actionDismiss)
DispatchQueue.main.async {
self.present(viewController: alertController)
}
}
if let response = response {
self.response = response
if response.status == "OK" {
if let placesDownloaded = response.places {
places.append(contentsOf: placesDownloaded)
}
self.tableView?.reloadData()
} else {
let alert = UIAlertController.init(title: "Error", message: response.status, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction.init(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
}))
self.present(viewController: alert)
}
isLoading = false
}
else {
print("response is nil")
}
}
so looking in the console i saw this error "((null)) was false: provideAPIKey: should be called at most once" which is perhaps the cause of the problem (even if I'm not sure), i followed the google documentation guide to get the API key for the project, here is my appDelegate where there are my keys (i changed for now the numbers of the key with "My Api key")
import UIKit
import Firebase
import CoreLocation
import GoogleMaps
import GooglePlaces
import FBSDKCoreKit
import GoogleSignIn
import FBSDKShareKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
static let googleMapsApiKey = "MY API Key"
static let googlePlacesAPIKey = "MY API Key"
var window: UIWindow?
var locationManager: CLLocationManager?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
if GMSServices.provideAPIKey("MY API Key") {
print("good provided keys correctly")
}
else {
print("key didn't provided")
}
return true
}
someone can tell if the problem is a wrong use of the api key or if the keys are wrong or maybe the problem is another ?
Look at what you are doing here:
// once
GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
// twice!
if GMSServices.provideAPIKey("MY API Key") {
You are calling provideAPIKey twice!
I know you want to check whether the API key is provided correctly, but the correct way to do this is not to call the method twice. Instead, you should store the return value and check the return value:
// put the return value in "success"
let success = GMSServices.provideAPIKey(AppDelegate.googleMapsApiKey)
GMSPlacesClient.provideAPIKey(AppDelegate.googlePlacesAPIKey)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
IQKeyboardManager.sharedManager().enable = true
IQKeyboardManager.sharedManager().enableAutoToolbar = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
// check "success"
if success {

Parsing JSON Tableview Information as Separate Strings

I am currently trying to use information in Tableview cells that I have populated with JSON to execute various operations but I am unable to call the specific information due to the fact that it isn't in individual strings. Is there any way to take the group of data I have pulled into each tableview cell and turn it into a series of individual strings? Here is what I currently have:
import UIKit
import GoogleMobileAds
class OngoingViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var userUsernameLabel: UILabel!
#IBOutlet weak var bannerView: GADBannerView!
#IBOutlet weak var ongoingTable: UITableView!
var list:[MyStruct] = [MyStruct]()
struct MyStruct
{
var user1 = ""
var user2 = ""
var wager = ""
var amount = ""
init(_ user1:String, _ user2:String, _ wager:String, _ amount:String)
{
self.user1 = user1
self.user2 = user2
self.wager = wager
self.amount = amount
}
}
override func viewDidLoad() {
super.viewDidLoad()
let username = UserDefaults.standard.string(forKey: "userUsername")!
userUsernameLabel.text = username
/// The banner view.
print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
ongoingTable.dataSource = self
ongoingTable.delegate = self
get_data("http://cgi.soic.indiana.edu/~team10/ongoingWagers.php")
}
func get_data(_ link:String)
{
let url:URL = URL(string: link)!
var request = URLRequest(url:url);
request.httpMethod = "POST";
let postString = "a=\(userUsernameLabel.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.extract_data(data)
}
task.resume()
}
func extract_data(_ data:Data?)
{
let json:Any?
if(data == nil)
{
return
}
do{
json = try JSONSerialization.jsonObject(with: data!, options: [])
}
catch
{
return
}
guard let data_array = json as? NSArray else
{
return
}
for i in 0 ..< data_array.count
{
if let data_object = data_array[i] as? NSDictionary
{
if let data_user1 = data_object["id"] as? String,
let data_user2 = data_object["id2"] as? String,
let data_wager = data_object["wager"] as? String,
let data_amount = data_object["amount"] as? String
{
list.append(MyStruct(data_user1, data_user2, data_wager, data_amount))
}
}
}
refresh_now()
}
func refresh_now()
{
DispatchQueue.main.async(
execute:
{
self.ongoingTable.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.ongoingTable.dequeueReusableCell(withIdentifier: "owcell", for: indexPath) as! OngoingTableViewCell
cell.infoLabel.text = list[indexPath.row].user1 + " " + list[indexPath.row].user2 + " " + list[indexPath.row].wager + " " + list[indexPath.row].amount
cell.user1Button.tag = indexPath.row
cell.user1Button.addTarget(self, action: #selector(OngoingViewController.user1Action), for: .touchUpInside)
cell.user2Button.tag = indexPath.row
cell.user2Button.addTarget(self, action: #selector(OngoingViewController.user2Action), for: .touchUpInside)
return cell
}
#IBAction func user1Action(sender: UIButton) {
let user1Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user1Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user1ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user1ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user1ConfirmationAlert, animated: true, completion: nil)
}))
user1Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user1Alert, animated: true, completion: nil)
}
#IBAction func user2Action(sender: UIButton) {
let user2Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user2Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user2ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user2ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user2ConfirmationAlert, animated: true, completion: nil)
}))
user2Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user2Alert, animated: true, completion: nil)
}
}
Here is the OngoingTableViewCell subclass:
import UIKit
class OngoingTableViewCell: UITableViewCell {
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var user1Button: UIButton!
#IBOutlet weak var user2Button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
You have an array of MyStruct structures, that contain entries for user1, user1, wager, and amount. That's good.
You're using tags on the buttons as a way of figuring out the selected cell, which is not ideal. Instead I would suggest using the sender parameter to figure out the indexPath of the cell that contains the button. See the bottom of my answer for the details of a better way to do it.
In any case, once you have a row number, you can easily get to the data for that wager by indexing into your array:
#IBAction func user1Action(sender: UIButton) {
selectedRow = sender.tag
//or, using my function:
selectedRow = tableView.indexPathForView(sender)
//Get the wager for the button the user tapped on.
let thisWager = list[selectedRow]
}
If you want to take action on the wager once the user taps a button in your UIAlertController, don't use a nil handler on the your second alert controller. Instead, pass in a closure that uses the selectedRow parameter from the code above to index into the list of wagers, or even use the thisWager local variable I show in my code.
Getting the indexPath of the button the user taps on:
I created a simple extension to UITableView that lets you pass in a UIView (like the sender from a button action) and get back the indexPath that contains that view.
That extension is dirt-simple. Here's how it looks:
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
And you can call that function from your button's actions:
#IBAction func buttonTapped(_ button: UIButton) {
if let indexPath = self.tableView.indexPathForView(button) {
print("Button tapped at indexPath \(indexPath)")
}
else {
print("Button indexPath not found")
}
}
The whole project can be found on Github at this link: TableViewExtension

Unable to display table view on Swift 3

I’m currently trying to load out my tableview using these codes, however I get a thread breakpoint at return listitem.count. Any help to solve this problem would be great.
The following below are my codes:
import UIKit
import CoreData
class ViewInventoryTableController: UITableViewController{
var listItems = [NSManagedObject]()
override func viewDidLoad(){
super.viewDidLoad()
//Do any additional setup after loading the view, typically from a nib.
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.add, target: self, action: #selector(ViewInventoryTableController.addItem))
}
func addItem(){
let alertMessage = "Please key in the activation code"
let alertController = UIAlertController(title: "Add Item", message: alertMessage as String, preferredStyle: .alert)
//Add the textfield
var activationCodeTextField1: UITextField?
alertController.addTextField { (textField) -> Void in
activationCodeTextField1 = textField
activationCodeTextField1?.placeholder = "123456789"
}
// Create Cancel button
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action:UIAlertAction!) in
print("Cancel button tapped")
}
alertController.addAction(cancelAction)
// Create ConfirmAction
let confirmAction = UIAlertAction(title: "Confirm", style: UIAlertActionStyle.default, handler: ({
(_) in
if let field = alertController.textFields![0] as? UITextField{
self.saveItem(itemToSave: field.text!)
self.tableView.reloadData()
}
}
))
alertController.addAction(confirmAction)
// Present Dialog message
OperationQueue.main.addOperation {
self.present(alertController, animated: true){}
}
print("Activation Code = \(activationCodeTextField1?.text)")
}
//function save item
func saveItem(itemToSave: String){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "ListEntity", in: managedContext)
let item = NSManagedObject(entity: entity!, insertInto: managedContext)
item.setValue(itemToSave, forKey: "item")
do {
try managedContext.save()
listItems.append(item)
}
catch {
print("error")
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.right)
managedContext.delete(listItems[indexPath.row])
listItems.remove(at: indexPath.row)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of any resources that can be recreated
}
override func tableView (_ tableView: UITableView , numberOfRowsInSection section: Int) -> Int {
return listItems.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! as UITableViewCell
let item = listItems[indexPath.row]
cell.textLabel?.text = item.value(forKey: "item") as? String
return cell
}
}

How to record game scene in spritekit

I have a project with SpriteKit. I have seen the video of WWDC15 for ReplayKit.
I added ReplayKit to my project and i want record my GameScene and share it in Facebook , save in camera roll more...and more.
anything not working now but i added the functions and i organized all.
thanks!
Start Record
func startScreenRecording() {
// Do nothing if screen recording hasn't been enabled.
let sharedRecorder = RPScreenRecorder.sharedRecorder()
// Register as the recorder's delegate to handle errors.
sharedRecorder.delegate = self
sharedRecorder.startRecordingWithMicrophoneEnabled(true) { error in
if let error = error {
self.showScreenRecordingAlert(error.localizedDescription)
}
}
}
Stop Record
func stopScreenRecordingWithHandler(handler:(() -> Void)) {
let sharedRecorder = RPScreenRecorder.sharedRecorder()
sharedRecorder.stopRecordingWithHandler { (previewViewController: RPPreviewViewController?, error: NSError?) in
if let error = error {
// If an error has occurred, display an alert to the user.
self.showScreenRecordingAlert(error.localizedDescription)
return
}
if let previewViewController = previewViewController {
// Set delegate to handle view controller dismissal.
previewViewController.previewControllerDelegate = self
/*
Keep a reference to the `previewViewController` to
present when the user presses on preview button.
*/
self.presentViewController(previewViewController, animated: true, completion: nil)
}
handler()
}
}
Other Functions of ReplayKit
func showScreenRecordingAlert(message: String) {
// Pause the scene and un-pause after the alert returns.
GameScene().paused = true
// Show an alert notifying the user that there was an issue with starting or stopping the recorder.
let alertController = UIAlertController(title: "ReplayKit Error", message: message, preferredStyle: .Alert)
let alertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { _ in
GameScene().paused = false
}
alertController.addAction(alertAction)
/*
`ReplayKit` event handlers may be called on a background queue. Ensure
this alert is presented on the main queue.
*/
dispatch_async(dispatch_get_main_queue()) {
self.view?.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
}
}
func discardRecording() {
// When we no longer need the `previewViewController`, tell `ReplayKit` to discard the recording and nil out our reference
RPScreenRecorder.sharedRecorder().discardRecordingWithHandler {
self.previewViewController = nil
}
}
// MARK: RPScreenRecorderDelegate
func screenRecorder(screenRecorder: RPScreenRecorder, didStopRecordingWithError error: NSError, previewViewController: RPPreviewViewController?) {
// Display the error the user to alert them that the recording failed.
showScreenRecordingAlert(error.localizedDescription)
/// Hold onto a reference of the `previewViewController` if not nil.
if previewViewController != nil {
self.previewViewController = previewViewController
}
}
// MARK: RPPreviewViewControllerDelegate
func previewControllerDidFinish(previewController: RPPreviewViewController) {
previewViewController?.dismissViewControllerAnimated(true, completion: nil)
}
Game Scene
import SpriteKit
import ReplayKit
class GameScene: SKScene , SKPhysicsContactDelegate{
func addRecordButton() {
RecordButton = SKSpriteNode(imageNamed:"Record-Off.png")
RecordButton.name = "RecordButton"
RecordButton.position = CGPoint(x: self.size.width/2 + 185, y: self.size.height/2 + 285)
RecordButton.size = CGSizeMake(32,32)
addChild(RecordButton)
}
func Record() {
let recorder = RPScreenRecorder.sharedRecorder()
if recorder.available{
RecordButton.texture = SKTexture(imageNamed: "Record-On.png")
print("Record")
} else {
RecordButton.texture = SKTexture(imageNamed: "Record-Off.png")
print("Stop Record")
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if {
if (RecordButton.containsPoint(location)){
Record()
}
}
}
class ViewController: UIViewController, RPScreenRecorderDelegate, RPPreviewViewControllerDelegate {
#IBOutlet weak var startRecordingButton: UIButton!
#IBOutlet weak var stopRecordingButton: UIButton!
#IBOutlet weak var activityView: UIActivityIndicatorView!
private let recorder = RPScreenRecorder.sharedRecorder()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if SIMULATOR {
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(self.showSimulatorWarning), userInfo: nil, repeats: false)
return
}
}
override func viewDidLoad() {
super.viewDidLoad()
recorder.delegate = self
activityView.hidden = true
buttonEnabledControl(recorder.recording)
}
#IBAction func startRecordingAction(sender: AnyObject) {
activityView.hidden = false
// start recording
recorder.startRecordingWithMicrophoneEnabled(true) { [unowned self] (error) in
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.activityView.hidden = true
}
if let error = error {
print("Failed start recording: \(error.localizedDescription)")
return
}
print("Start recording")
self.buttonEnabledControl(true)
}
}
#IBAction func stopRecordingAction(sender: AnyObject) {
activityView.hidden = false
//end recording
recorder.stopRecordingWithHandler({ [unowned self] (previewViewController, error) in
dispatch_async(dispatch_get_main_queue()) {
self.activityView.hidden = true
}
self.buttonEnabledControl(false)
if let error = error {
print("Failed stop recording: \(error.localizedDescription)")
return
}
print("Stop recording")
previewViewController?.previewControllerDelegate = self
dispatch_async(dispatch_get_main_queue()) { [unowned self] in
// show preview vindow
self.presentViewController(previewViewController!, animated: true, completion: nil)
}
})
}
//MARK: - Helper
//control the enabled each button
private func buttonEnabledControl(isRecording: Bool) {
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
let enabledColor = UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0)
let disabledColor = UIColor.lightGrayColor()
if !self.recorder.available {
self.startRecordingButton.enabled = false
self.startRecordingButton.backgroundColor = disabledColor
self.stopRecordingButton.enabled = false
self.stopRecordingButton.backgroundColor = disabledColor
return
}
self.startRecordingButton.enabled = !isRecording
self.startRecordingButton.backgroundColor = isRecording ? disabledColor : enabledColor
self.stopRecordingButton.enabled = isRecording
self.stopRecordingButton.backgroundColor = isRecording ? enabledColor : disabledColor
}
}
func showSimulatorWarning() {
let actionOK = UIAlertAction(title: "OK", style: .Default, handler: nil)
// let actionCancel = UIAlertAction(title: "cancel", style: .Cancel, handler: nil)
let alert = UIAlertController(title: "ReplayKit不支持模拟器", message: "请使用真机运行这个Demo工程", preferredStyle: .Alert)
alert.addAction(actionOK)
// alert.addAction(actionCancel)
self.presentViewController(alert, animated: true, completion: nil)
}
func showSystemVersionWarning() {
let actionOK = UIAlertAction(title: "OK", style: .Default, handler: nil)
let alert = UIAlertController(title: nil, message: "系统版本需要是iOS9.0及以上才支持ReplayKit", preferredStyle: .Alert)
alert.addAction(actionOK)
self.presentViewController(alert, animated: true, completion: nil)
}
// MARK: - RPScreenRecorderDelegate
// called after stopping the recording
func screenRecorder(screenRecorder: RPScreenRecorder, didStopRecordingWithError error: NSError, previewViewController: RPPreviewViewController?) {
print("Stop Recording ...\n");
}
// called when the recorder availability has changed
func screenRecorderDidChangeAvailability(screenRecorder: RPScreenRecorder) {
let availability = screenRecorder.available
print("Availability: \(availability)\n");
}
// MARK: - RPPreviewViewControllerDelegate
// called when preview is finished
func previewControllerDidFinish(previewController: RPPreviewViewController) {
print("Preview finish");
dispatch_async(dispatch_get_main_queue()) {
[unowned previewController] in
// close preview window
previewController.dismissViewControllerAnimated(true, completion: nil)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Self.tableView.reloadData not working if there is no user tap or View change

I am having an issue; I have the following code that get execute in a IBAction and as you will see I have the code to execute reloadData of the tableView. The issue is if I don't touch the screen (like a tap or change of the view) no data is displayed in the tableView but as soon as I touch the screen or move the cells (like just move them up and down) then the data appears.
The following image is the code that imports the contacts, save them in core data and loads them into an Array and execute reload data.
Here is the complete code of the ViewController where this issue is happening.
import UIKit
import CoreData
import AddressBook
class ContactsViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableviewContacts: UITableView!
//Public property that represent an array of the contacts added or copied by the user using the application
var contacts: [Contact] = []
//Public property that represent the context required to save the data in the persistance storage.
var context: NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func viewWillAppear(animated: Bool) {
loadContacts()
tableviewContacts.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:cellContact = tableView.dequeueReusableCellWithIdentifier("cellContact", forIndexPath: indexPath) as! cellContact
let contact = contacts[indexPath.row]
cell.labelContact.text = contact.name + " " + contact.surname
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
var contact = contacts[indexPath.row]
var error: NSError?
var handler: HACoreDataHandler = HACoreDataHandler()
handler.context!.deleteObject(contact)
handler.context!.save(&error)
if(error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
contacts.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
#IBAction func importContacts(sender: AnyObject) {
let status = ABAddressBookGetAuthorizationStatus()
if status == .Denied || status == .Restricted {
// user previously denied, to tell them to fix that in settings
let alert = UIAlertController(title: "Warning", message: "We need your permission to import your contacts to giftlog.", preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
return
}
// open it
var error: Unmanaged<CFError>?
let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue()
if addressBook == nil {
println(error?.takeRetainedValue())
return
}
ABAddressBookRequestAccessWithCompletion(addressBook) {
granted, error in
if !granted {
// warn the user that because they just denied permission, this functionality won't work
// also let them know that they have to fix this in settings
let alert = UIAlertController(title: "Warning", message: "Please grant access to your contact first by granting the acess to Giftlog in the privacy phone setting ", preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
return
}
if let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray {
var handler: HACoreDataHandler = HACoreDataHandler()
var error: NSError?
for person:ABRecordRef in people{
if (ABRecordCopyValue(person, kABPersonFirstNameProperty) != nil){
var contact = NSEntityDescription.insertNewObjectForEntityForName("Contact", inManagedObjectContext: handler.context!) as! Contact
contact.name = (ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as? String)!
contact.surname = (ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as? String)!
var phones : ABMultiValueRef = ABRecordCopyValue(person,kABPersonPhoneProperty).takeUnretainedValue() as ABMultiValueRef
if (ABMultiValueGetCount(phones)>0){
let phoneUnmaganed = ABMultiValueCopyValueAtIndex(phones, 0)
contact.phone = phoneUnmaganed.takeUnretainedValue() as! String
}
let emails: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
if (ABMultiValueGetCount(emails)>0){
let index = 0 as CFIndex
let emailAddress = ABMultiValueCopyValueAtIndex(emails, index).takeRetainedValue() as! String
contact.email = emailAddress
}
handler.context!.save(&error)
if (error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
} else {
self.contacts.append(contact)
self.tableviewContacts.reloadData()
} // else
} //if (ABRecordCopyValue(person, kABPersonFirstNameProperty) != nil)
} //for person:ABRecordRef in people
} // if let people
} // ABAddressBookRequestAccessWithCompletion
}
func loadContacts(){
var request = NSFetchRequest(entityName: "Contact")
let handler = HACoreDataHandler()
var error: NSError?
contacts = handler.context!.executeFetchRequest(request, error: &error) as! [Contact]
if(error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
}
This image is the code that sets the label of each cell of the tableView.
Finally this is the image from the storyboard file of the view and the prototype cell
Any suggestions will be appreciated.
Thanks in advance.

Resources