First program in Swift - HelloWorld - ios

I have some issue with my first code in Swift, when I'm running it, it seems fine, but it shows e.g. Hello Optional "(name)" instead of Hello (name).
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var helloLabel: UILabel!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var sayHelloButton: UIButton!
#IBAction func sayHelloAction(sender: AnyObject)
{
let name = nameTextField.text
if name!.isEmpty {
let alert = UIAlertController(title: "Error", message: "Please enter a name", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
} else {
helloLabel.text = "Hello \(name)!"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setupUI()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupUI() {
helloLabel.text = "Hello There!"
helloLabel.textColor = UIColor.blueColor()
helloLabel.textAlignment = NSTextAlignment.Center
nameTextField.placeholder = "Enter your name"
sayHelloButton.setTitle("Say Hello", forState: .Normal)
}
}
Can anyone help me, please?
Doms.

In Swift you have a type called Optional. This is used to express nullability. You need to do what is called unwraping the optional. I will discourage you from force unwrapping ! it will cause your app to crash. You can unwrap an optional value using the if let statement:
#IBAction func sayHelloAction(sender: AnyObject) {
if let name = nameTextField.text where !name.isEmpty {
helloLabel.text = "Hello \(name)"
} else {
let alert = UIAlertController(title: "Error", message: "Please enter a name", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}

I ran into this when I was just learning Swift myself, and it tends to pop out in all sorts of places. For instance, I couldn't understand why one of my tableview columns always said "0" instead of "1" or "2". It was in fact saying "O"ptional!
The simplest solution is to guard everything everywhere. That way the compiler knows you've checked that it's not nil, and "unwraps" the value for you. so instead of:
let name = nameTextField.text
just do a:
guard let name = nameTextField.text else { return }
Replace that return with something more appropriate. From that point on, name is the string and won't have the Optional(theThingYouReallyWanted) any more.
note: as I said at the start, this has a habit of showing up in weird places. If you bind Optionals into things like text fields or table columns, you'll see it when you don't expect it. I strongly suggest making getter/setter properties for all UI work, and using the guard to unwrap as above and instead of return hand back an empty string or something similar.

You get the Optional("") because the optional value is not unwrapped. You need to put a ! after the object and you won't get the Optional("") bit any more. I would show you the code but you haven't shown us the print() statement. I made some sample ones below that I think would replicate the problem, though I haven't tried them.
var value:String?
value = "Hello, World"
print("The Value Is \(value)") // Prints "The Value Is Optional(Hello, World)"
print("The Value Is \(value!)")// Prints "The Value Is Hello, World"

Related

Passing data back to a data model file using protocols and delegates

[SOLVED] As a beginner, this most likely isn't an optimal or clever solution, however it does what it needs to do. The data from the AddVocabViewController is passed back via this delegate and then inserts a new instance of Vocab into the array in the data model. Also the delegation in the prepare for segue function allowed the data to pass through.
class ViewController: UIViewController, passNewWordData{
func passDataBack(data: Vocab){
vocabBuilder.n1LevelVocab.insert(data, at: vocabBuilder.n1LevelVocab.startIndex)
self.dismiss(animated: true) {
let currentVocabNumber = vocabNumber
self.vocabBuilder.n1LevelVocab.swapAt(currentVocabNumber, self.vocabBuilder.n1LevelVocab.startIndex)
self.loadUIN1()
print(vocabNumber)
}
}
Original Question is as follows:
I have a class modal view controller that passes data back successfully but I want to insert this data type into an array.
My modal view controller is this:
import UIKit
protocol passNewWordData {
func passDataBack(data: Vocab)
}
//pass back the data using this protocol and calling it as a delegate
var vocabBuilder1 = VocabBuilder()
class AddVocabularyViewController: UIViewController {
#IBOutlet var modalView: UIView!
#IBOutlet weak var vocabTextField: UITextField!
#IBOutlet weak var hiraganaTextField: UITextField!
#IBOutlet weak var englishTranslationTextField: UITextField!
var delegate: passNewWordData?
//this is crucial! This is the link between both VCs.
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addNewWord(_ sender: UIButton) {
guard let vocabText = vocabTextField.text, vocabTextField.hasText else {
print("Error no data")
let ac = UIAlertController(title: "Missing Vocabulary Word!", message: "Please fill in the Vocabulary field", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .cancel))
present(ac, animated: true)
return
}
guard let hiraganaText = hiraganaTextField.text, hiraganaTextField.hasText else {
print("Error no hiragana entered")
let ac = UIAlertController(title: "Missing hiragana!", message: "Please fill in the Hiragana field", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .cancel))
present(ac, animated: true)
return
}
guard let englishTranslationText = englishTranslationTextField.text, englishTranslationTextField.hasText else {
let ac = UIAlertController(title: "Missing English Translation!", message: "Please fill in the English Translation field", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .cancel))
present(ac, animated: true)
print("Error no english translation entered.")
return
}
//better to have guard lets to handle the data so conditions are correct before passing the data..
let newWord = Vocab(vocabTitle: vocabText, vocabHiragana: hiraganaText, englishTranslation: englishTranslationText, noOfTimesSeen: 0)
delegate?.passDataBack(data: newWord)
print(newWord)
}
This prints out the data that's being sent back no problem but what I want to do is add this data to a data model file I made specifically to an array inside it.
struct VocabBuilder {
var n1LevelVocab = [Vocab(vocabTitle: "上達", vocabHiragana: "じょうたつ", englishTranslation: "Improvement", noOfTimesSeen: 0),
Vocab(vocabTitle: "乗り越える", vocabHiragana: "のりこえる", englishTranslation: "To Push Through", noOfTimesSeen: 0),
Vocab(vocabTitle: "耐久性", vocabHiragana: "たいきゅうせい", englishTranslation: "Durability", noOfTimesSeen: 0),]
Things I've tried:
I tried to make the extension to the the main view controller to receive the data but it won't append the data when I call the functions from the data model to add them.
extension ViewController: passNewWordData {
func passDataBack(data: Vocab) {
self.dismiss(animated: true)
self.vocabInfo.n1LevelVocab.append(data)
//vocabInfo is calling the VocabBuilder Struct.
//need to append this data to the newWord variable then send that back to the n1VocabArray in the dataModel.
print(data)
}
}
I tested out inside the data model appending a new Vocab type and it does append an extra item to the array there, but how do I get that data from my modal view controller all the way back to that struct? Would I need to create an extension to handle the data from the protocol in my data model itself? Most examples are just passing directly into the view controller.
Any help would be appreciated.

Checking for an empty string in Swift 2

I am trying to create a required field in Swift 2. Everytime I run this code I receive no errors, but I never receive an error message with the text field is empty. The segue is always performed. Any idea what I am doing wrong?
Thanks!
#IBOutlet weak var userName: UITextField!
#IBAction func userConfermation(sender: AnyObject) {
if userName.text!.isEmpty {
let alertController = UIAlertController(title: "Error",
message: "Incorrect Password", preferredStyle:UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss",
style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
} else {
performSegueWithIdentifier("final", sender: self)
}
return
}
Hi you can check the empty string by checking userName.text character count or userName.text == "" whenever is got empty it will give you error and segue will not perfrom
In Swift 2 you can use a guard statement and where !text.isEmpty to check if the text field has text in it or not.
guard let text = textfield.text where !text.isEmpty else {
// do something if it's empty
return
}
print(text) // do something if it's not empty
A good way to do that would be, To create an extension of String and check for isEmpty after trimming whitespace characters :
extension String {
var isBlank: Bool {
return trimmingCharacters(in: .whitespaces).isEmpty
}
}
After that you can check a string like this:
if userName.text!.isBlank {
//do stuff
}

UIAlertController utility class fails to call UITextField delegate or target but works in UIViewController

I encountered a strange issue and maybe it is only a lack of knowledge about Swift 3.0 / iOS 10 so hopefully you can guide me into the right direction or explain to me what I'm doing wrong.
HOW IT CURRENTLY WORKS
I am trying to create a UIAlertController with style .alert so I can get a user text input for my app. My requirements are that the text must not be empty and if there was a text there before, it must be different.
I can use the following code to achieve what I want:
//This function gets called by a UIAlertController of style .actionSheet
func renameDevice(action: UIAlertAction) {
//The AlertController
let alertController = UIAlertController(title: "Enter Name",
message: "Please enter the new name for this device.",
preferredStyle: .alert)
//The cancel button
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
//The confirm button. Make sure to deactivate on first start
let confirmAction = UIAlertAction(title: "Ok", style: .default, handler: { action in
self.renameDevice(newName: alertController.textFields?.first?.text)
})
//Configure the user input UITextField
alertController.addTextField { textField in
log.debug("Setting up AlertDialog target")
textField.placeholder = "Enter Name"
textField.text = self.device.getName()
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
}
//Disable the OK button so that the user first has to change the text
confirmAction.isEnabled = false
self.confirmAction = confirmAction
//Add the actions to the AlertController
alertController.addAction(cancelAction)
alertController.addAction(confirmAction)
present(alertController, animated: true, completion: nil)
}
var confirmAction: UIAlertAction?
func textFieldDidChange(_ textField: UITextField){
log.debug("IT CHAGNED!=!=!=!=!")
if let text = textField.text {
if !text.isEmpty && text != self.device.getName() {
confirmAction?.isEnabled = true
return
}
}
confirmAction?.isEnabled = false
}
//Finally this code gets executed if the OK button was pressed
func renameDevice(newName: String?){ ... }
HOW I WANT IT TO WORK
So far so good but I'm going to ask the user for a text input at various places so I want to use a utility class to handle all this stuff for me. The final call shall look like this:
func renameDevice(action: UIAlertAction) {
MyPopUp().presentTextDialog(title: "Enter Name",
message: "Please enter the new name for this device.",
placeholder: "New Name",
previousText: self.device.getName(),
confirmButton: "Rename",
cancelButton: "Cancel",
viewController: self){ input: String in
//do something with the input, e. g. call self.renameDevice(newName: input)
}
WHAT I CAME UP WITH
So I implemented everything in this little class:
class MyPopUp: NSObject {
var confirmAction: UIAlertAction!
var previousText: String?
var textField: UITextField?
func presentTextDialog(title: String, message: String?, placeholder: String?, previousText: String?, confirmButton: String, cancelButton: String, viewController: UIViewController, handler: ((String?) -> Swift.Void)? = nil) {
//The AlertController
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
//The cancel button
let cancelAction = UIAlertAction(title: cancelButton, style: .cancel)
//The confirm button. Make sure to deactivate on first start
confirmAction = UIAlertAction(title: confirmButton, style: .default, handler: { action in
handler?(alertController.textFields?.first?.text)
})
//Configure the user input UITextField
alertController.addTextField { textField in
log.debug("Setting up AlertDialog target")
self.textField = textField
}
//Set placeholder if necessary
if let placeholder = placeholder {
self.textField?.placeholder = placeholder
}
//Set original text if necessary
if let previousText = previousText {
self.textField?.text = previousText
}
//Set the target for our textfield
self.textField?.addTarget(self, action: #selector(textChanged), for: .editingChanged)
log.debug("It appears that our textfield \(self.textField) has targets: \(self.textField?.allTargets)")
//Store the original text for a later comparison with the new entered text
self.previousText = previousText
//Disable the OK button so that the user first has to change the text
confirmAction.isEnabled = false
//Add the actions to the AlertController
alertController.addAction(cancelAction)
alertController.addAction(confirmAction)
viewController.present(alertController, animated: true, completion: nil)
}
func textChanged() {
if let text = textField?.text {
if !text.isEmpty && text != previousText {
confirmAction.isEnabled = true
return
}
}
confirmAction.isEnabled = false
}
}
THE PROBLEM
My problem is that no matter where I try to set the target for the UITextField of the UIAlertController, it never executes my target. I tried setting the TextFields delegate in alertController.addTextField{} as well as setting the target there. The issue which confuses me the most is that setting the placeholder and original text works just fine but delegate or target functions are never called. Why does the same code works when executed in a UIViewController but does not work when executed in a utility class?
THE SOLUTION (UPDATE)
Apparently I made a mistake. In my viewcontroller, I create an instance of MyPopUp and call the present() function on it.
MyPopUp().presentTextDialog(title: "Enter Name",
message: "Please enter the new name for this device.",
placeholder: "New Name",
previousText: self.device.getName(),
confirmButton: "Rename",
cancelButton: "Cancel",
viewController: self)
In the presentTextDialog() I thought setting the current instance of MyPopUp as the delegate/target would be enough but it seems that the MyPopUp instance is released immediately and therefore never called. My very simple workaround is to create the MyPopUp instance in an instance variable and call the present method whenever I need to.
let popup = MyPopUp()
func renameDevice(action: UIAlertAction) {
popup.presentTextDialog(...){ userinput in
renameDevice(newName: userinput)
}
}
Okay so here's exactly what I did wrong.
I created a utility class which I had to instantiate
The class itself was basically empty and it's only purpose was to be the target or delegate of the UITextField
I instantiated the class and immediately called the presentation function without keeping a reference around
By not keeping a reference to my instance, the object must have gotten released immediately after presenting the UIAlertController in my viewcontroller.
Solution: Just keep a reference around in your viewcontroller. Of course a local variable won't do. I store the reference in an instance variable of my viewcontroller but this doesn't feel very "swifty". I'm still a beginner in swift and maybe my mind is "damaged" by other languages (java, c#). I will probably start by making my utility class a singleton or creating an extension for UIViewController to present the alert. If you have other good ideas feel free to teach them to me :)
Instead of presenting dialogue in NSObject class. You must use delegates and protocol to present an alert. Replace your code with this. In View Controller we have a function named renameDevice. You can present alert here.
MyPopUp.swift
import UIKit
class MyPopUp: NSObject {
var confirmAction: UIAlertAction!
var previousText: String?
var textField: UITextField?
var delegate : MyPopUpDelegate!
func textChanged() {
if let text = textField?.text {
if !text.isEmpty && text != previousText {
confirmAction.isEnabled = true
return
}
}
confirmAction.isEnabled = false
}
}
protocol MyPopUpDelegate {
func renameDevice(action: UIAlertAction)
}
ViewController.swift
import UIKit
class ViewController: UIViewController,MyPopUpDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// 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 renameDevice(action: UIAlertAction) {
// Add dialogue that you wnat to create.
}
}
In your MyPopUp class first you need to conform to UITextFieldDelegate method like this
class MyPopUp:NSObject,UITextFieldDelegate {
then while adding your UITextField to alert you need to set delegate to that UITextField like this
alertController.addTextField { textField in
log.debug("Setting up AlertDialog target")
textField.delegate = self
self.textField = textField
}
then you need to implement UITextField Delegate method to get the change in your UITextField like this
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
This will solve your problem.Also check this

UIAlertController Not Within The Window Hierarchy

First of all please do not mark duplicate on this question Ive done my research on this topic, and not only have the most recent answers been from over a year ago, but they have also been in C#. Mine also differs from those because I am trying to present my UIView from what I assume to be a child of a child view. But I'm not 100% sure about this. So, here is what my code dump looks like after the suggestions.
import UIKit
import Firebase
class LoginViewController: UIViewController, UITextFieldDelegate{
#IBOutlet weak var usernameTxt: UITextField!
#IBOutlet weak var emailTxt: UITextField!
#IBOutlet weak var passwordTxt: UITextField!
#IBOutlet weak var confirmPassTxt: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func nextScreen(sender: UIButton) {
if(emailTxt.text == "" || passwordTxt.text == "" || confirmPassTxt.text == "" || usernameTxt.text == ""){
let alertController = UIAlertController(title: "Wait!", message: "You didn't fill out the required fields, please do so and try again. ", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}else{
if(validateEmail(emailTxt.text!)){
emailCheck(emailTxt.text!){isValid in if isValid{self.secondRound({ (goodMail, goodPassL, goodPassTxt, nameGood) in
if (goodMail && goodPassL && goodPassTxt && !nameGood){
print("good")
}else{
self.showAlert("Else", description: "Got it?") }
})}else{let alertController=UIAlertController(title: "Whoops!", message: "That email address has already been taken, please try another one", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
alertController.parentViewController
self.presentViewController(alertController, animated: true, completion: nil)
}}
}else{
let alertController = UIAlertController(title: "Whoops!", message: "That doesnt appear to be a valid email address, please check your information and try again!", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
alertController.parentViewController
presentViewController(alertController, animated: true, completion: nil)
}
}
}
func showAlert(title: String, description: String){
let alertController: UIAlertController = UIAlertController(title: title, message: description, preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
self.presentViewController(alertController, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestinationVC : Login2VC = segue.destinationViewController as! Login2VC
DestinationVC.prepareEmail = emailTxt.text!
DestinationVC.preparePass = passwordTxt.text!
}
func validateEmail(canidate: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
return NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluateWithObject(canidate)
}
func nameFilter(input : String)-> Bool{
var profanity : Bool = true
let dataRef = FIRDatabase.database().reference()
dataRef.child("Profanity").observeSingleEventOfType(.Value) { (snap: FIRDataSnapshot) in
if(snap.exists()){
if(snap.value! as! NSArray).containsObject(input){
print("our ears!")
profanity = true
}else{
profanity = false
}
}
}
return profanity
}
func emailCheck(input: String, callback: (isValid: Bool) -> Void) {
FIRAuth.auth()?.signInWithEmail(input, password: " ") { (user, error) in
var canRegister = false
if error != nil {
if (error?.code == 17009) {
canRegister = false
} else if(error?.code == 17011) {
//email doesn't exist
canRegister = true
}
}
callback(isValid: canRegister)
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func secondRound(callback:(goodMail:Bool, goodPassL:Bool, goodPassTxt:Bool, nameGood:Bool)->Void){
let availableEmail : Bool = true
var passwordMatch : Bool = false
var passwordLength : Bool = false
var profanity : Bool = false
if(passwordTxt.text!==confirmPassTxt.text!){passwordMatch=true}else{passwordMatch=false}
if(passwordTxt.text!.characters.count>=6&&confirmPassTxt.text!.characters.count>=6){passwordLength=true}else{passwordLength=false}
if(nameFilter(usernameTxt.text!)){profanity=true}else{profanity=false}
callback(goodMail: availableEmail, goodPassL: passwordLength, goodPassTxt: passwordMatch, nameGood: profanity)
}
}
Essentially, what I am trying to do is:
Check to see if the inputted text is formatted as an email correctly
Check to see if the name is available
Check if the username contains profanity (pulled as a json from firebase)
Check to see if the passwords match
Check too see if the passwords are at least 6 characters in length
Each false result would have its own UIAlertView that results from it, but whenever I try to add these views they do not show up, and the app returns with this error.
Note, the false event does intact appear in the first condition only. Other than that, nothing happens.
This is the error I have been getting, and while it seems pretty straight forward I cannot figure out hoe to fix it, nor find any recent information online on how to accomplish this task.
> Warning: Attempt to present <UIAlertController: 0x7fb513fb8bc0> on
> <myApp.LoginViewController: 0x7fb513c6e0a0> whose view is not in the
> window hierarchy!
The logical answer to this would be:
Hey, why don't you just add the window to the hierarchy and be done?
Well, to that question I have a question, if the window is not apart of the hierarchy, then why is the view itself even displaying. Furthermore, why would the first set of UIAlerts be displaying, but as soon as I get into a nested if they cease? Any ideas on how to fix this terrible error?
Thanks all

how to show UIAlertController in a custom UITableViewCell in button click using swift code?

i want to show UIAlertController in a custom UITableViewCell in a button click. but i can't find any way for this. please see the below code that i have try.
this code give error in UITableViewCel, that is shown in above picture.
please help me.the whole class code is below:
class CustomCellDeerCalls: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBOutlet weak var playButton: UIButton!
#IBOutlet weak var detialsInfoButton: UIButton!
#IBOutlet weak var DeerCallNameLabel: UILabel!
var arrayOfDetialsInfoDeerCalls: [String]=["This sound is a doe's way of locating other deer of her family group . This call can be used all year long.",
"Grunts are a doe's way of saying come here , also to call her fawns at feeding time . It is critical to keep the call soft as a loud grunt is too aggressive of a call.",
"A buck grunt is a deeper pitch than a doe grunt , it means the same thing . The older the buck the deeper the tone. ",
"As the buck chases the doe as the rut approaches he is frustrated, and makes a series of soft grunts while trailing her. It's the bucks way of asking her to stop so he can be breed with her.",
"This sound's a lot like a calf bawl , but it is a series of buck bleats. This signals the bucks desire for company.",
"This is a non aggressive and social behaviour that all bucks do after shedding their velvet . This is when the bucks learn who can whip the other . This process does not prevent serious fights later on during the rut.",
"This is the sound that a buck makes during the courtship when the doe stops running , but won't let the buck breed her. It's a non aggressive and frustration call by him.",
"This is the sound that a Doe makes to signal that her breeding time is near.",
"This is the sound that a Doe makes to signal that she ready to breed RIGHT NOW.",
"Deer make this sound to intimidate other deer and prevent fights. This call is often made by a rut- crazed buck when confronted with a rival. This sound can send smaller buck running from the area.",
"Another rut crazed Bucks sound to intimidate other deer and prevent fights when confronted with a rival. This sound can also send smaller buck running from the area.",
"This is a short aggressive rattling sequence to possibly lure in less aggressive, but curious buck, as well as the local dominant whitetail buck of the area. To make this sound like a real fight sniffs, wheezes and grunts have also been thrown in for added effect."]
var arrayOfDeerSoundsCall: [String]=["CONTACT","doegrunt","bkgrunt","tend","bawl","spar","rage","estrusb","bellow","sniff","wheeze","rattle"]
// var arrayOfCallsName: [String]=[""]
#IBAction func clickDetialsInfoButton(sender: AnyObject) {
var alert = UIAlertController(title: "dddddd", message: arrayOfDetialsInfoDeerCalls[sender.tag], preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
//sender.sup
//
}
var audioPlayer = AVAudioPlayer()
#IBAction func clickplayButton(sender: AnyObject) {
println(sender.tag)
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(arrayOfDeerSoundsCall[sender.tag], ofType: "wav")!)
println(alertSound)
// Removed deprecated use of AVAudioSessionDelegate protocol
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCell(callName: String){
self.DeerCallNameLabel.text=callName
}
}
i found a solution. following are code for above question.
write the following code for button in viewcontroller where table view are present.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let deerNameCell: CustomCellDeerCalls = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomCellDeerCalls
let deercallcell=arrayOfCallsName[indexPath.row]
deerNameCell.DeerCallNameLabel.text=deercallcell.callName
deerNameCell.playButton.tag=indexPath.row
deerNameCell.detialsInfoButton.tag=indexPath.row
deerNameCell.detialsInfoButton.addTarget(self, action: "showAlert:", forControlEvents:UIControlEvents.TouchUpInside)
return deerNameCell
}
and the funtion for alert in the same view controller:
func showAlert(sender:UIButton!)
{
println(sender.tag)
let deercallcell=arrayOfCallsName[sender.tag]
var alert = UIAlertController(title: deercallcell.callName, message: arrayOfDetialsInfoDeerCalls[sender.tag], preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
You are trying to call presentViewController on a UITableViewCell but this method is a member of a UIViewController instead.
Here is my suggestion:
1) Create a CustomCellDeerCallsDelegate protocol, ie.:
protocol CustomCellDeerCallsDelegate {
func showAlert(title:String, message:String);
}
2) Add a weak property to your custom cell:
var delegate:CustomCellDeerCallsDelegate?
3) In your clickDetialsInfoButton function call a method on a delegate:
self.delegate?.showAlert("DDDDD", message: arrayOfDetialsInfoDeerCalls[sender.tag])
4) Add a protocol implementation to a ViewController that hosts the table view that displays the cell.
5) In a protocol implementation of showAlert function - show the alert:
func showAlert(title:String, message:String){
var alert = UIAlertController(title: "dddddd", message: arrayOfDetialsInfoDeerCalls[sender.tag], preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}

Resources