Change WebView url from AppDelegate - swift

I'm receiving notifications from Firebase in the AppDelegate class.
This notification contains a String named "notif_url". I've put this value in a var named "desired_url" and now I need to change my WebView url with the "desired_url" value.
But I can't access to the webview to change it url like this :
#IBOutlet weak var my_web_view: UIWebView!
func load_url(server_url: String){
let url = URL(string: server_url);
let request = URLRequest(url: url!);
my_web_view.loadRequest(request);
}
load_url(server_url: desired_url);
Do you know if I can do that and if yes, how ?
Images :
EDIT 1:
After adding breakPoint to know the wrong line, it seem't that the line is this one :
my_web_view.loadRequest(request)
EDIT 2:
If need, that's a part of my AppDelegate class code.
import UIKit
import UserNotifications
import Firebase
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
#IBOutlet weak var my_web_view: UIWebView!
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return true
}
}
// [START ios_10_message_handling]
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate{
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void){
print("Step : 12");
let userInfo = notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey]{
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
var url: String = userInfo[AnyHashable("url")] as! String;
load_url(server_url: url);
// Change this to your preferred presentation option
completionHandler([])
}
func load_url(server_url: String){
/*
let url = URL(string: server_url);
let request = URLRequest(url: url!);
my_web_view.loadRequest(request);
*/
guard let url = URL(string: server_url) else {
print("Invalid URL")
return
}
print("TRY : "+server_url);
let request = URLRequest(url: url)
my_web_view.loadRequest(request)
}
}
EDIT 3:
If need, that's my ViewController class code.
import Foundation
import UIKit
import SafariServices
import UserNotifications
class ViewController: UIViewController, UIWebViewDelegate{
#IBOutlet weak var my_web_view: UIWebView!
#IBOutlet weak var my_loading_view: UIView!
#IBOutlet weak var spinner : UIActivityIndicatorView!
#IBOutlet weak var app_logo : UIImageView!
#IBOutlet weak var deadlinePicker: UIDatePicker!
#IBOutlet weak var titleField: UITextField!
var new_url: String = "";
override func viewDidLoad(){
super.viewDidLoad()
let server_url = "https://www.sortirauhavre.com/";
NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
rotated();
spinner.startAnimating();
my_web_view.scrollView.bounces = false;
my_web_view.scrollView.isScrollEnabled = true;
let url = URL(string: server_url);
let request = URLRequest(url: url!);
my_web_view.loadRequest(request);
}
// CETTE FONCITON SE LANCE A LA ROTATION DE L'APPAREIL
func rotated(){
app_logo.center = my_loading_view.center;
let y = app_logo.frame.origin.y;
let h = app_logo.frame.size.height
app_logo.frame.origin.y = y-(h/2);
spinner.center = my_loading_view.center;
}
// CETTE FONCTION MET EN ARRIERE PLAN L'ANNIMATION DE CHARGEMENT
func removeLoader(){
self.view.addSubview(my_web_view);
}
// CETTE FONCTION MET EN PREMIER PLAN L'ANNIMATION DE CHARGEMENT
func addLoader(){
self.view.addSubview(my_loading_view);
}
// CETTE FONCTION SE DECLANCHE QUAND LES PAGES DE LA WEBVIEW COMMENCE A CHANGER
func webViewDidStartLoad(_ webView: UIWebView){
addLoader();
let server_url = "https://www.sortirauhavre.com/";
_ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.removeLoader), userInfo: nil, repeats: false);
if let text = webView.request?.url?.absoluteString{
if text.hasPrefix(server_url){
}
else if text != ""{
UIApplication.shared.openURL(URL(string: text)!)
my_web_view.goBack()
}
}
}
// CETTE FONCTION SE DECLANCHE QUAND LES PAGES DE LA WEBVIEW FINI DE CHANGER
func webViewDidFinishLoad(_ webView: UIWebView){
let server_url = "https://www.sortirauhavre.com/";
_ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.removeLoader), userInfo: nil, repeats: false);
if let text = webView.request?.url?.absoluteString{
if text.hasPrefix(server_url){
}
else if text != ""{
UIApplication.shared.openURL(URL(string: text)!)
my_web_view.goBack()
}
}
}
}

You are force unwrapping url which is not a valid URL. I would suggest adding a guard statement to prevent the crash if a invalid URL is created:
func load_url(server_url: String) {
guard let url = URL(string: server_url) else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
my_web_view.loadRequest(request)
}
As you are obtaining the URL in the AppDelegate you cannot simply update the UIWebView from this class. You will need to call a function in the my_web_view's parent class which updates the URL.
// App Delegate
var serverURL: String?
func load_url(server_url: String) {
serverURL = server_url
let notificationName = Notification.Name("updateWebView")
NotificationCenter.default.post(name: notificationName, object: nil)
}
// View Controller
override func viewDidLoad() {
let notificationName = Notification.Name("updateWebView")
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateWebView), name: notificationName, object: nil)
updateWebView()
}
func updateWebView() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let serverURL = appDelegate.serverURL
guard let url = URL(string: serverURL) else {
print("Invalid URL")
return
}
let request = URLRequest(url: URL)
my_web_view.loadRequest(request)
}

Instead of creating a new instance of your view controller, or trying to duplicate the outlet, you just need to access the current instance of your view controller. You can use either:
A global value for the view controller, or
A singleton-like pattern.
Then you can access the instance from your app delegate, by calling either myGlobalViewController.webView or ViewController.instance.webView.
So, here's an example:
import UIKit
private var thisViewController: ViewController? // Will hold the instance.
class ViewController: UIViewController {
static var instance: ViewController {
guard let thisViewController = thisViewController else { fatalError() } // Don't do this unless you're 100% sure that you'll never access this before the instance is loaded.
return thisViewController
}
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
thisViewController = self // Set the property to self.
}
...
}
After this, you can access the web view from your app delegate:
func load_url(server_url: String){
guard let url = URL(string: server_url) else {
return
}
let request = URLRequest(url: url)
ViewController.instance.webView.loadRequest(request)
}

Related

Presenting view controller from detached view controller is discouraged. Keeping User logged in issue

I'm trying to have the user move to automatically go to the Home Screen and not have to log in again. Basically, to remember the user. I used User Defaults to save the user login info and put the listener for the key in the viewDidLoad of the first login page. I used an if statement to switch the view controllers but it doesn't work and prints (Presenting view controller from detached view controller is discouraged).
LoginViewController:
import UIKit
import FirebaseAuth
import AVKit
class LoginViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var Back: UIButton!
#IBOutlet weak var passwordtextField: UITextField!
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
setupElements()
}
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
func setupElements(){
errorLabel.alpha = 0
Utilities.styleTextField(emailTextField)
Utilities.styleTextField(passwordtextField)
Utilities.styleFilledButton(loginButton)
}
func validateFields() -> String?
{
//make sure fields are filled
if emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || passwordtextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
{
return "Please fill all fields"
}
return nil
}
#IBAction func loginTapped(_ sender: Any) {
//creates a clean version of the text field
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordtextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let error = validateFields()
//sign in user
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
UserDefaults.standard.set(Auth.auth().currentUser!.uid, forKey: "user_uid_key")
UserDefaults.standard.synchronize()
if error != nil{
self.errorLabel.text = "Invalid Username/Password try again."
self.errorLabel.alpha = 1
}
else{
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
}
//make sure all fields are filled
}
override func viewWillAppear(_ animated: Bool) {
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "IMG_7211 2", ofType: "mov")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 0.8)
}
}
ViewController:
import UIKit
import AVKit
import Firebase
import FirebaseAuth
class ViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var logInButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.object(forKey: "user_uid_key") != nil {
print("i see u")
let navController = UINavigationController(rootViewController: HomeViewController())
navController.navigationBar.barStyle = .black
self.present(navController, animated: false, completion: nil)
}
else {
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
ViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
// Do any additional setup after loading the view.
setupElements()
}
func showhomepage() {
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
override func viewWillAppear(_ animated: Bool) {
//Set up video in background
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "Project", ofType: "mp4")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 1)
}
func setupElements(){
Utilities.styleFilledButton(signUpButton)
Utilities.styleHollowButton(logInButton)
}
}
Looks like you're using Firebase. Do not store any login information in the User defaults. What you should do is create a blank view controller that will check if the user is signed in. If the user is signed it, it will present your HomeViewController; if the user is not signed in, it will present the login screen. You can also choose to perform these checks in your AppDelegate/SceneDelegate if you want to avoid the extra view controller.
The empty ViewController should be the initial/root ViewController.
You cannot present view controllers from inside viewDidLoad, use viewDidAppear.
Here is a basic example for the view controller way:
// in the new empty view controller, import FirebaseAuth
var handle: AuthStateDidChangeListenerHandle!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(false)
handle = Auth.auth().addStateDidChangeListener { auth, user in
if user != nil {
// Go to Home Screen/ switch root
} else {
// Go to sign in screen/ switch root
}
}
}

How to import or access UITextField from another Class

I have Outlet of UITextField in the main VC and I want to access its text from another class... for more clarification please see my code below:
class ProductManagement : UIViewController, UITextFieldDelegate{
#IBOutlet weak var ProductName: UITextField!
}
and I want to read the text in below class
import Firebase
import FirebaseStorage
class XUpload {
static func UploadImage(Image : UIImage, Completion : #escaping (_ url : String)->()) {
guard let imageData = Image.pngData() else { return }
let storage = Storage.storage().reference()
let pathRef = storage.child("Images/Products")
let imageRef = pathRef.child( // I want the product name to be written here! )
imageRef.putData(imageData, metadata: nil) { (meta, error) in
imageRef.downloadURL { (url, error) in
print (url as Any)
}
}
}
}
I tried to create a custom protocol to delegate the UITextField but the problem is I couldn't conform it inside XUpload class !!
Please someone write for me how is my code should be because I'm beginner and new to Swift language.
Thank you in advance.
EDIT:
Elia Answer applied below:
ProductManagement Class + Extension
class ProductManagement : UIViewController, UITextFieldDelegate{
override func viewDidLoad() {
super.viewDidLoad()
self.ProductName.delegate = self
}
#IBOutlet weak var ProductName: UITextField!
#objc private func textFieldDidChange(_ sender: UITextField) {
NotificationCenter.default.post(name: .PnameInputText, object: nil, userInfo: ["text": sender.text!])
}
}
extension Notification.Name {
public static var PnameInputText = Notification.Name("PnameInputText")
}
XUpload Class
import Firebase
import FirebaseStorage
class XUpload {
private init() {
NotificationCenter.default.addObserver(self, selector: #selector(handle(_:)), name: .PnameInputText, object: nil)
}
public static var shared = XUpload()
var textFieldText : String = "" {
didSet {print("updated value > ", textFieldText)}
}
#objc private func handle(_ sender: Notification) {
if let userInfo = sender.userInfo as NSDictionary?, let text = userInfo["text"] as? String {
textFieldText = text
}
}
static func UploadImage(Image : UIImage, Completion : #escaping (_ url : String)->()) {
guard let imageData = Image.pngData() else { return }
let storage = Storage.storage().reference()
let pathRef = storage.child("Images/Products")
let imageRef = pathRef.child("img_"+shared.textFieldText)
print("var of textFieldText value: " + shared.textFieldText) //print nothing... empty value!!
imageRef.putData(imageData, metadata: nil) { (meta, error) in
imageRef.downloadURL { (url, error) in
print ("Image uploaded to this link >> " + url!.description)
guard let str = url?.absoluteString else { return }
Completion (str)
}
}
}
}
extension UIImage {
func upload(completion : #escaping (_ url : String) ->()) {
XUpload.UploadImage(Image: self) { (ImageURL) in completion (ImageURL)
}
}
}
As you can see there is no value given to var textFieldText by the Notification Center! why??
class ProductManagement : UIViewController, UITextFieldDelegate{
var productInputText: String = ""
#IBOutlet weak var ProductName: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
ProductName.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}
#objc private func textFieldDidChange(_ sender: UITextField) {
productInputText = sender.text ?? ""
}
}
This will store your input text into a variable basically with listen edit changes.
And if I get not wrong, you use UploadImage within ProductManagement class. Add a function property to UploadImage as below
class XUpload {
static func UploadImage(Image : UIImage, productName: String, Completion : #escaping (_ url : String)->()) {
guard let imageData = Image.pngData() else { return }
let storage = Storage.storage().reference()
let pathRef = storage.child("Images/Products")
let imageRef = pathRef.child( // I want the product name to be written here! )
imageRef.putData(imageData, metadata: nil) { (meta, error) in
imageRef.downloadURL { (url, error) in
print (url as Any)
}
}
}
}
and call it in ProductManagement class like below.
XUpload.UploadImage(image: myImage, productName: productInputText, Completion: {
}
EDIT:
After getting your comment, I decided the best way do it is using Notification, you use UITextField in ProductManagement class so there is no need to handle delegate method of them in XUpload
Describe notification name
extension Notification.Name {
public static var TextChange = Notification.Name("TextChange")
}
In ProductManagement, textDidChange method post text to Notification
#objc private func textFieldDidChange(_ sender: UITextField) {
NotificationCenter.default.post(name: .TextChange, object: nil, userInfo: ["text": sender.text])
}
I convert your XUpload class to a Singleton class.
class XUpload {
private init() {
NotificationCenter.default.addObserver(self, selector: #selector(handle(_:)), name: .TextChange, object: nil)
}
public static var Shared = XUpload()
#objc private func handle(_ sender: Notification) {
if let userInfo = sender.userInfo as NSDictionary?, let text = userInfo["text"] as? String {
textFieldText = text
}
}
var textFieldText: String = "" {
didSet {
print("updated value > " , textFieldText)
}
}
static func uploadImage() {
// use updated textfield text with textFieldText
}
}
Then store a variable in ProductManagement class as a singleton object and it wil work for you. The text in textfield updated every changes in XUpload class.
class ProductManagement : UIViewController, UITextFieldDelegate{
var staticVariable = XUpload.Shared
}

How Can I Change a String Using Remote Config?

I'm creating an app that plays a sound when a button is clicked. It consists of UIButton to play the sound, UIImageView to display the associated image, and another UIButton which I'm using like a label to describe the button. I want to be able to configure all three parameters so I can change them remotely from Firebase. So far I figured out how to change the label, but I want to be able to change the URL that the sound and image load from. Here is my code:
import UIKit
import Firebase
import AVKit
class FirebaseViewController: UIViewController, AVAudioPlayerDelegate {
//These variables are for my sound when I click a button
var firesound1 = AVPlayer()
var firesound2 = AVPlayer()
var firesound3 = AVPlayer()
//These outlets reference the labels(UIButton) and UIImageView in the storyboard
#IBOutlet weak var firelabel1: UIButton!
#IBOutlet weak var firelabel2: UIButton!
#IBOutlet weak var firelabel3: UIButton!
#IBOutlet weak var fireimage1: UIImageView!
#IBOutlet weak var fireimage2: UIImageView!
#IBOutlet weak var fireimage3: UIImageView!
func updateViewWithRCValues() {
//These remote config options allow me to change the text of the UIButton, which here I'm using like a UILabel
firelabel1.setTitle(buttonLabel1, for: .normal)
let buttonLabel2 = RemoteConfig.remoteConfig().configValue(forKey: "label2").stringValue ?? ""
firelabel2.setTitle(buttonLabel2, for: .normal)
let buttonLabel3 = RemoteConfig.remoteConfig().configValue(forKey: "label3").stringValue ?? ""
firelabel3.setTitle(buttonLabel3, for: .normal)
let url = RemoteConfig.remoteConfig().configValue(forKey: "url1").stringValue ?? ""
firelabel3.setTitle(buttonLabel3, for: .normal)
}
func setupRemoteConfigDefaults() {
let defaultValues = [
"label1": "" as NSObject,
"label2": "" as NSObject,
"label3": "" as NSObject
]
RemoteConfig.remoteConfig().setDefaults(defaultValues)
}
func fetchRemoteConfig() {
// Remove this before production!!
let debugSettings = RemoteConfigSettings(developerModeEnabled: true)
RemoteConfig.remoteConfig().configSettings = debugSettings!
RemoteConfig.remoteConfig().fetch(withExpirationDuration: 0) { [unowned self] (status, error) in guard error == nil else {
print ("Error fetching remote values: \(String(describing: error))")
return
}
print("Retrieved values from the cloud")
RemoteConfig.remoteConfig().activateFetched()
self.updateViewWithRCValues()
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupRemoteConfigDefaults()
fetchRemoteConfig()
//This code loads an image from a url into a UIImageView. I want to be able to configure the url like a parameter so I can change the url from the firebase website.
let url = URL(string: "https://ichef-1.bbci.co.uk/news/976/media/images/83351000/jpg/_83351965_explorer273lincolnshirewoldssouthpicturebynicholassilkstone.jpg")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if (error != nil)
{
print("ERROR")
}
else
{
var documentsDirectory: String?
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
if paths.count > 0
{
documentsDirectory = paths [0]
let savePath = documentsDirectory! + "/ImageOne"
FileManager.default.createFile(atPath: savePath, contents: data, attributes: nil)
DispatchQueue.main.async
{
self.fireimage1.image = UIImage(named: savePath)
}
}
}
}
task.resume()
}
//This code plays the sounds. I also want to be able to configure the url like a parameter.
#IBAction func soundpressed1(_ sender: Any) {
let sound1 = AVPlayerItem(url: URL(string: "https://firebasestorage.googleapis.com/v0/b/mlg-soundboard-2018-edition.appspot.com/o/hitmarker.mp3?alt=media&token=e5d342d6-4074-4c50-ad9d-f1e41662d9e9")!)
firesound1 = AVPlayer(playerItem: sound1)
firesound1.play()
}
override func didReceiveMemoryWarning() {
}
}
Basically I want to be able to swap out the URLs with Remote Config.
You can either create separate keys in Remote config for Text, Sound URL and Image URL.
Or you can create a key called button_config and supply all the three params in a JSON
button_config = {"text" : "My button label", "sound_url" : "https://foo.com/sound.mp3", "image_url" : "https://foo.com/image.png"}

URL validation not working in swift

started learning swift two weeks ago, with no previous programming experience, and I can't for the life of me figure out why this wouldn't work to check for nil. it just crashes when trying to load a web page if the user enters an invalid URL. This is the ENTIRETY of the code.
import UIKit; import WebKit
class ViewController: UIViewController {
#IBOutlet weak var adressBar: UITextField!
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func returnPressed(_ sender: Any) {
if let adressBarText = adressBar.text {
if let myURL = URL(string: adressBarText) {
let myRequest = URLRequest(url: myURL)
webView.load(myRequest)
adressBar.resignFirstResponder()
print("EYYYYY")
} else {
print("BOOOO")
}
}
}
}
Try this method
func verifyUrl (urlString: String?) -> Bool {
//Check for nil
if let urlString = urlString {
// create NSURL instance
if let url = NSURL(string: urlString) {
// check if your application can open the NSURL instance
return UIApplication.sharedApplication().canOpenURL(url)
}
}
return false
}
https://stackoverflow.com/a/30130535/8069241

FBLoginManager undeclared type

I installed FacebookSDK using Cocoapods, according to Terminal, I have installed FacebookSDK 4.8.0 (CoreKit, ShareKit and LoginKit), I imported the .h files in my BH-File.h, and already initialized everything in my AppDelegate.
For some reason, when trying to log in using a custom button, when I initialize FBLoginManager, I get an error Use of undeclared type "FBLoginManager".
this is my code
if (FBSDKAccessToken.currentAccessToken() == nil)
{
let fbLoginManager : FBSDKLoginManager =
fbLoginManager.logInWithReadPermissions(["public_profile", "email"], fromViewController: self, handler: { (loginResult, error) -> Void in
if error == nil {
print (FBSDKAccessToken.currentAccessToken().tokenString)
}
else {
print ("ERROR*****: \(error)")
}
})
}
What fixed to me was adding import FBSDKCoreKit and FBSDKLoginKit to my class, for some reason is not enough adding it in the BH-file.h
Try something like this, I just checked the code and it works (it's not exactly what you're looking for but I'm sure you can modify it as needed)
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ProfileViewController: UIViewController,FBSDKLoginButtonDelegate {
// #IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var fbLoginButton: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
self.fbLoginButton.delegate = self
self.fbLoginButton.readPermissions = ["public_profile"]
self.fbLoginButton.publishPermissions = ["publish_actions"]
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "fbProfileChanged:",
name: FBSDKProfileDidChangeNotification,
object: nil)
FBSDKProfile.enableUpdatesOnAccessTokenChange(true)
// If we have a current Facebook access token, force the profile change handler
if ((FBSDKAccessToken.currentAccessToken()) != nil)
{
self.fbProfileChanged(self)
} }
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//facebooks functions
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if (error != nil)
{
print( "\(error.localizedDescription)" )
}
else if (result.isCancelled)
{
// Logged out?
print( "Login Cancelled")
}
else
{
// Logged in?
print( "Logged in, segue now")
self.performSegueWithIdentifier("showHome", sender: self)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
}
//see bitfountain
func fbProfileChanged(sender: AnyObject!) {
let fbProfile = FBSDKProfile.currentProfile()
if (fbProfile != nil)
{
// Fetch & format the profile picture
let strProfilePicURL = fbProfile.imagePathForPictureMode(FBSDKProfilePictureMode.Square, size: imageView.frame.size)
let url = NSURL(string: strProfilePicURL, relativeToURL: NSURL(string: "http://graph.facebook.com/"))
let imageData = NSData(contentsOfURL: url!)
let image = UIImage(data: imageData!)
self.nameLabel.text = fbProfile.name
self.imageView.image = image
self.nameLabel.hidden = false
self.imageView.hidden = false
self.nextButton.hidden = false
}
else
{
self.nameLabel.text = ""
self.imageView.image = UIImage(named: "")
self.nameLabel.hidden = true
self.imageView.hidden = true
}
}
#IBAction func nextButtonPressed(sender: UIButton) {
self.performSegueWithIdentifier("showHome", sender: self)
}
}