I don't know why I can't access the text from the UITextField.
Here is my code:
import UIKit
import Firebase
import FirebaseAuth
class MessagesVC: UIViewController {
#IBOutlet weak var emailTextInput: UITextField! //Email Text Input
#IBOutlet weak var passwordTextInput: UITextField! //Password Text Input
var emailText: emailTextInput.text; //I get the error 'Use of undeclared type emailTextInput here.'
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func login(_ sender: Any) {
} //Login
#IBAction func signUp(_ sender: Any) {
Auth.auth().createUser(withEmail: , password: ) { (user, error) in
} //Authentication Create User
} //Sign Up
} //Class
This is the editor error I get:
Because you are declaring variable with value of textfield. You can assign textfield value to that string variable.
you can write it like,
First declare it with,
var emailText = ""
Then you can assign its value inside viewDidLoad like below,
self.emailText = self.emailTextInput.text!
Related
I have made a custom UIViewController called ViewControllerA and want to be able to use it so I made a UIViewControllerRepresentable called ViewControllerARepresentable as shown below, the problem though is that when I call ViewControllerARepresentable in my SwiftUI view and pass a value for stringToUpdateTextView, the ViewControllerA says the htmlTextView(UITextView) in ViewControllerA is nil and I'm not sure why.
ViewControllerARepresentable(stringToUpdateTextView: "<html>Send some Html Text as string here</html>")
ViewControllerARepresentable
public struct ViewControllerARepresentable: UIViewControllerRepresentable {
var stringToUpdateTextView: String
public func makeUIViewController(context: Context) -> ViewControllerA {
let viewcontrollerA = ViewControllerA(testString: testingString)
return viewcontrollerA
}
public func updateUIViewController(_ uiViewController: ViewControllerA, context: Context) {}
}
ViewControllerA
open class ViewControllerA: UIViewController {
public var stringToUpdateTextView: String
override open func viewDidLoad() {
super.viewDidLoad()
htmlTextView.text = stringToUpdateTextView
}
#IBOutlet weak var htmlTextView: UITextView!
public init(testString: String) {
self.testString = testString
super.init(nibName: nil, bundle: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Crash occurs at htmlTextView.text = stringToUpdateTextView saying that htmlTextView.text is nil even though its an IBOutlet.
Any Change made to the htmlTextView like background color ,etc, also causes a crash if called in viewDidAppear or viewDidLoad
When instantiating your view controller in makeUIViewController, the outlets haven't been initialised yet.
The following code loads your view controller from the storyboard, and updates the properties in updateUIViewController:
ViewController.swift
import UIKit
import SwiftUI
class ViewController: UIViewController {
#IBOutlet weak var htmlTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
struct ViewControllerWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = ViewController
#Binding var text: String
func makeUIViewController(context: Context) -> ViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let viewController = storyboard.instantiateViewController(
identifier: "ViewController") as? ViewController else {
fatalError("Cannot load from storyboard")
}
return viewController
}
func updateUIViewController(_ uiViewController: ViewController, context: Context) {
uiViewController.htmlTextView.text = text
}
}
struct ViewControllerPreview: PreviewProvider {
static var previews: some View {
ViewControllerWrapper(text: .constant("hello world!"))
}
}
SwiftUIView.swift
struct SwiftUIView: View {
#State var text = "Text"
var body: some View {
HStack {
TextField("Text:", text: $text)
ViewControllerWrapper(text: $text)
}
}
}
I did a exmaple long time ago how to send a simple message from an iPhone to a Apple Watch using Swift:
import UIKit
import WatchConnectivity
class ViewController: UIViewController, WCSessionDelegate {
// MARK: Outlets
#IBOutlet weak var textField: UITextField!
// MARK: Variables
var wcSession : WCSession! = nil
// MARK: Overrides
override func viewDidLoad() {
super.viewDidLoad()
wcSession = WCSession.default
wcSession.delegate = self
wcSession.activate()
}
// MARK: Button Actions
#IBAction func sendText(_ sender: Any) {
let txt = textField.text!
let message = ["message":txt]
wcSession.sendMessage(message, replyHandler: nil) { (error) in
print(error.localizedDescription)
}
}
// MARK: WCSession Methods
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
// Code
}
func sessionDidBecomeInactive(_ session: WCSession) {
// Code
}
func sessionDidDeactivate(_ session: WCSession) {
// Code
}
}
Now I'm trying to do the same using SwiftUI but no success so far.
Can anyone help with this problem?
I just need to know how to use the WCSession Class and the WCSessionDelegate with SwiftUI.
Thanks
I just had the same question as you and I figured it out:
First you need to implement a class that conforms to WCSessionDelegate. I like to use a separate class for that:
import WatchConnectivity
class ConnectivityProvider: NSObject, WCSessionDelegate {
private let session: WCSession
init(session: WCSession = .default) {
self.session = session
super.init()
self.session.delegate = self
}
func send(message: [String:Any]) -> Void {
session.sendMessage(message, replyHandler: nil) { (error) in
print(error.localizedDescription)
}
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
// code
}
func sessionDidBecomeInactive(_ session: WCSession) {
// code
}
func sessionDidDeactivate(_ session: WCSession) {
// code
}
}
Now you need a ViewModel that takes your ConnectivityProvider as an argument. The ViewModel will be responsible for the connection of your View and the ConnectivityProvider. It also holds the value for the Textfield that later gets defined inside your View.
import SwiftUI
final class ViewModel: ObservableObject {
private(set) var connectivityProvider: ConnectivityProvider
var textFieldValue: String = ""
init(connectivityProvider: ConnectivityProvider) {
self.connectivityProvider = connectivityProvider
}
func sendMessage() -> Void {
let txt = textFieldValue
let message = ["message":txt]
connectivityProvider.send(message: message)
}
}
Now you can build a simple View that consists of a Textfield and a Button. Your View will be dependent on your ViewModel that you just defined.
import SwiftUI
struct ContentView: View {
#ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
TextField("Message Content", text: $viewModel.textFieldValue)
Button(action: {
self.viewModel.sendMessage()
}) {
Text("Send Message")
}
}
}
}
Last but not least you need to combine your ConnectivityProvider, ViewModel and View inside of your SceneDelegate:
let viewModel = ViewModel(connectivityProvider: ConnectivityProvider())
let contentView = ContentView(viewModel: viewModel)
...
window.rootViewController = UIHostingController(rootView: contentView)
==================================
Update: How to activate the Session?
First add a new function to your ConnectivityProvider that activates the session:
class ConnectivityProvider: NSObject, WCSessionDelegate {
...
func connect() {
guard WCSession.isSupported() else {
print("WCSession is not supported")
return
}
session.activate()
}
...
}
Now you can call the connect function whenever you need your WCSession to be connected. You should be able to connect it everywhere, like in your SceneDelegate, inside your ViewModel, or even directly inside of the init of your ConnectivityProvider:
ConnectivityProvider init:
class ConnectivityProvider: NSObject, WCSessionDelegate {
private let session: WCSession
init(session: WCSession = .default) {
self.session = session
super.init()
self.session.delegate = self
self.connect()
}
...
}
ViewModel:
import SwiftUI
final class ViewModel: ObservableObject {
private(set) var connectivityProvider: ConnectivityProvider
var textFieldValue: String = ""
init(connectivityProvider: ConnectivityProvider) {
self.connectivityProvider = connectivityProvider
self.connectivityProvider.connect()
}
func sendMessage() -> Void {
let txt = textFieldValue
let message = ["message":txt]
connectivityProvider.send(message: message)
}
}
SceneDelegate:
let connectivityProvider = ConnectivityProvider()
connectivityProvider.connect()
let viewModel = ViewModel(connectivityProvider: connectivityProvider)
let contentView = ContentView(viewModel: viewModel)
...
window.rootViewController = UIHostingController(rootView: contentView)
I have a problem with my delegate use in a protocol, many person face the same problem but no answer works for me.
My first class is FavorisHeaderTableView
import UIKit
protocol FavorisHeaderDelegate {
func changeFavoris(sender: FavorisHeaderTableViewCell)
}
class FavorisHeaderTableViewCell: UITableViewCell {
#IBOutlet weak var lblTitle: UILabel!
#IBOutlet weak var txtFavoriteNameInput: UITextField!
#IBOutlet weak var lblIcon: UILabel!
#IBOutlet weak var lblTime: UILabel!
#IBOutlet weak var lblDescription: UILabel!
#IBOutlet weak var btnFavHeart: UIButton!
#IBOutlet weak var btnFavHome: UIButton!
#IBOutlet weak var btnFavShop: UIButton!
#IBOutlet weak var btnFavWork: UIButton!
#IBOutlet weak var btnFavGolf: UIButton!
var myDelegate: FavorisHeaderDelegate? = nil
var defaultIcon:FavIconType = .heart
var selectedIcon:UIButton? = nil {
didSet {
selectedIcon!.backgroundColor = Design.Palette.red
selectedIcon?.layer.cornerRadius = 3
selectedIcon?.tintColor = Design.Palette.white
}
willSet {
if selectedIcon != nil {
selectedIcon!.backgroundColor = UIColor.clear
selectedIcon?.tintColor = UIColor(red:0.671, green:0.651, blue:0.635, alpha:1)
}
}
}
#IBAction func didSelectIcon(_ sender: UIButton) {
selectedIcon = sender
self.myDelegate?.changeFavoris(sender: self)
}
#IBAction func changeTitle(_ sender: Any) {
txtFavoriteNameInput.text = "gare centro"
print("delegate: ",myDelegate)
if myDelegate != nil {
myDelegate?.changeFavoris(sender: self)
}
}
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
}
}
The second class who use the protocol is
addFavoriteViewController: UIViewController {
// MARK properties
let defaultLocalizer = AMPLocalizeUtils.defaultLocalizer
var favorisName:String? = nil
var defaultIcon:FavIconType = .heart
var delegate:handleFavorite? = nil
#IBOutlet weak var favTableView: UITableView!
var headerCell:FavorisHeaderTableViewCell?
override func viewDidLoad() {
super.viewDidLoad()
// Localization of labels
//lblAddToFavorite.text = defaultLocalizer.stringForKey(key: "str_favorites_addTitle")
//lblFavoriteName.text = defaultLocalizer.stringForKey(key: "str_favorites_nameInput")
favTableView.delegate = self
favTableView.dataSource = self
self.headerCell?.myDelegate = self
}
override func viewWillAppear(_ animated: Bool) {
// Text Field
//favorisName.clearButtonMode = .whileEditing
}
var place:PlaceModel? = nil
var itinerary:(source:PlaceModel, destination:PlaceModel)? = nil
let db = DataController.shared
var favorite:FavoritesMO? = nil
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension UGOaddFavoriteViewController: FavorisHeaderDelegate {
func changeFavoris(sender: FavorisHeaderTableViewCell) {
defaultIcon = sender.defaultIcon
favorisName = sender.txtFavoriteNameInput.text
}
}
When I try this code "myDelegate" is always nil and I don't understand what's wrong despite of all topic read about this problem.
You are setting self as the delegate of the wrong cell!
Here:
self.headerCell?.myDelegate = self
you set the headerCell's delegate to self, but headerCell is never actually displayed on the screen!
You need to actually set the delegates of the cells on the screen, not the delegate of a random cell that you created.
The best place to do this is cellForRowAtIndexPath:
let cell = tableView.dequeueResusableCell(withIdentifier:...)!
// configure your cell
cell.delegate = self // set the delegate here!
I wanted to programmatically control the menu view so I tried the following:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var menuView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func menuBtn(_ sender: UIButton) {
print("menuBtn")
print(type(of: menuView!)) // <- `Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)`
}
}
And click the button, console says
fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
Both are connected to ViewController.
How can I get print(type(of: menuView!))?
===============================================================
ps.
I've simplified my real problem. this is my real code:
button on ViewController.Swift
#IBAction func openModal(_ sender: UIButton) {
print("open btn clicked")
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "menuViewController") as! MenuViewController
self.addChildViewController(vc)
self.view.addSubview(vc.contentView!) /// <- This cause problem
}
MenuViewController.swift
import UIKit
class MenuViewController: UIViewController {
#IBOutlet weak var contentView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
view.isOpaque = false
}
#IBAction func closeBtn(_ sender: UIButton) {
print("close btn clicked")
self.view.removeFromSuperview()
}
}
and Why I wan't using it:
I can't scrolling when menuView appeared.. I want to use the buttons in the menu view and scroll at the same time.
I begin to learn swift language and i've a problem.
I try to display a label when i put the button. I show you :
#IBAction func nextRule(sender : UIButton) {
rule = Rules(game: Int(randomNumber))
}
#IBOutlet var lTitle: UILabel!
#IBOutlet var lRule: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
lTitle.text = rule.title
lRule.text = rule.rule
Rules(game: Int) contain a model whith "title" And "rule"
When i press the button, i want to display a new Rule, is it possible by doing something like his?
Thanks for your answer.
How about assign your rule to lTitle and lRule like this
#IBAction func nextRule(sender : UIButton) {
rule = Rules(game: Int(randomNumber))
lTitle.text = rule.title
lRule.text = rule.rule
}