Open Facebook profile in app - xcode

I am trying to make that when the user press Facebook button, it opens the Facebook application, or in browser.
Import code:
import Foundation
Extension code:
extension UIApplication {
class func tryURL(urls: [String]) {
let application = UIApplication.sharedApplication()
for url in urls {
if application.canOpenURL(NSURL(string: url)!) {
application.openURL(NSURL(string: url)!)
return
}
}
}
}
Function code:
func fimageTapped()
{
UIApplication.tryURL([
"fb://profile/1357163924", // App
"http://www.facebook.com/1357163924" // Website if app fails
])
}
I get error at line:
class func tryURL(urls: [String]) {
Error message:
Invalid redeclaration of "tryURL"
This is where i found the code from: Xcode swift link to facebook page
Anyone has any idea what is wrong here?

In Swift 3 use this:
let facebookID: String = "000000000000"
let facebookName: String = "name"
let facebookURLID = URL(string: "fb://profile/\(facebookID)")!
let facebookURLWeb = URL(string: "https://m.facebook.com/\(facebookName)?id=\(facebookID)")!
if(UIApplication.shared.canOpenURL(facebookURLID)){
UIApplication.shared.openURL(facebookURLID)
} else {
UIApplication.shared.openURL(facebookURLWeb)
}
Remember that from iOS 9 and 10 you need to declare in the Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fb</string>
</array>
With this the queries for the Facebook schemes will not fail with a permission error:
"This app is not allowed to query for scheme fb"

Used this, worked fine:
var fbURLWeb: NSURL = NSURL(string: "https://www.facebook.com/ID")!
var fbURLID: NSURL = NSURL(string: "fb://profile/ID")!
if(UIApplication.sharedApplication().canOpenURL(fbURLID)){
// FB installed
UIApplication.sharedApplication().openURL(fbURLID)
} else {
// FB is not installed, open in safari
UIApplication.sharedApplication().openURL(fbURLWeb)
}

Swift 3:
Important: UIApplication is declared in UIKit so make sure you import UIKit aswell.
import Foundation
import UIKit
extension UIApplication {
class func tryURL(_ urls: [String]) {
let application = UIApplication.shared
for url in urls {
if application.canOpenURL(URL(string: url)!) {
application.open(URL(string: url)!, options: [:], completionHandler: nil)
return
}
}
}
}
Furthermore:
application.openURL(NSURL(string: url)!)
have in Swift 3 changed to open and with completionHandler:
application.open(URL(string: url)!, options: [:], completionHandler: nil)
Next in your viewController: declare your facebook app and web-urls above viewDidLoad and create a function or IBAction func where you do your UIapplication.tryURL:
import UIKit
class ViewController: UIViewController {
let fbAppUrl = "facebook://profile/yourFBprofileID"
let fbWebUrl = "https://www.facebook.com/yourFBprofileID"
override func viewDidLoad() {
super.viewDidLoad()
}
func openFacebook() {
UIApplication.tryURL([fbAppUrl, fbWebUrl])
}
}
First iOS will try to open the fbAppUrl but if the facebook app is not installed on the device it will open fbWebUrl in Safari instead.

For Swift 4
let webURL: NSURL = NSURL(string: "https://www.facebook.com/ID")!
let IdURL: NSURL = NSURL(string: "fb://profile/ID")!
if(UIApplication.shared.canOpenURL(IdURL as URL)){
// FB installed
UIApplication.shared.open(webURL as URL, options: [:], completionHandler: nil)
} else {
// FB is not installed, open in safari
UIApplication.shared.open(webURL as URL, options: [:], completionHandler: nil)
}

Related

iOS Swift app calls the SquarePOS app on iPad -Square app's screen displays briefly then reverts to my screen's calling view controller-did nothing

This app is intentionally tiny - the UI is just a button to initiate the api call. The appDelegate simply shows a console log proving the callback was executed. I did this because I can not get the Square payment system to work even thought the code and url setup etc looks right to me. I am wondering if I misunderstand something in the documentation.
My app ID is: sq0idp-TbgQGqSrC84qkfcXSTntNg
bundleID is: com.craig.POSSDKTest2
My info.plist setup is a screenshot:info.plist and URLScheme setup
My code in the api calling VC:
// ViewController.swift
// POSSDKTest2
//
// Created by Dr Craig E Curphey on 2022-06-14.
//
import UIKit
import SquarePointOfSaleSDK
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}//------------------------------------
#IBAction func doPaymentTapped(_ sender: Any) {
//------ API to Square right here ******-----------------
let callbackURL = URL(string: "POSSDKTest2Scheme://")!
SCCAPIRequest.setApplicationID("sq0idp-TbgQGqSrC84qkfcXSTntNg")
var money: SCCMoney?
do {
// Specify the amount of money to charge - $1.00
let todaysFeePennies = 100
money = try SCCMoney(amountCents: todaysFeePennies, currencyCode: "CAD")
} catch {
print("money conversion failed.")
}
let LoginID = "TestPatient"
//log values used to console:
print("Initiating payment api request")
print("callback: \(callbackURL)")
print("money: \(money!)")
print("LoginID: TestPatient")
print("Creating payment api request")
do
{
let apiRequest =
try SCCAPIRequest(
callbackURL: callbackURL,
amount: money!,
userInfoString: LoginID,
locationID: "",
notes: "TestingSDK2",
customerID: "tester2",
supportedTenderTypes: .all,
clearsDefaultFees: false,
returnsAutomaticallyAfterPayment: false,
disablesKeyedInCardEntry: false,
skipsReceipt: false
)
print("api initiating!")
try SCCAPIConnection.perform(apiRequest)
} catch let error as NSError {
print("Error detected: \(error.localizedDescription)")
}//end API
print("End of payment api function.")
}//------------------------------------
}
Here is my appDelegate code - I just want to see if I get a callback - I'll add the code to process the response later ...
// AppDelegate.swift
// POSSDKTest2
//
// Created by Dr Craig E Curphey on 2022-06-14.
//
var squareTokenID = "not specified - let it fail - I just want a callback!"
import UIKit
import SquarePointOfSaleSDK
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
//-------------------------------------------
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("Callback was executed!")
guard SCCAPIResponse.isSquareResponse(url) else {
print("\(SCCAPIResponse.isSquareResponse(url))")
return true
}
do {
let response = try SCCAPIResponse(responseURL: url)
if let error = response.error {
// Handle a failed request.
print(error.localizedDescription)
} else {
// Handle a successful request.
}
} catch let error as NSError {
// Handle unexpected errors.
print(error.localizedDescription)
}
return true
}//-------------------------------------------------------
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}//-------------------------------------------------------
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}//--------------------------------------------------------
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}//---------------------------------------------------------
}
Screenshot of console log from trying to do the api:
Console log
The work environment is Xcode 13.3, Swift, macOSMonterey 12.1 beta, iPad 10.2" (I think) mounted in a Square iPad kiosk with attached card reader, running iOS 15.5.
I would be very happy to send the whole project in a zip file to anyone who would be willing to take a look into why it is failing.

Implementing AdMob Interstitial Ads in SwiftUI (5) and Xcode (12.4)

I am working on implementing Interstitial ads in my app and running into some confusion with the docs provided by Admob and the new SwiftUI app structure.
Here is the app.swift file, showing that I've implemented the GoogleMobileAds and started it in the didFinishLaunchingWithOptions method.
import SwiftUI
import GoogleMobileAds
#main
struct adamsCalcApp: App {
var calculator = Calculator()
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView().environmentObject(calculator)
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// Setup google admob instance
GADMobileAds.sharedInstance().start(completionHandler: nil)
return true
}
}
In my ContentView.swift File, I have the interstitial variable created like...
#State var interstitial: GADInterstitialAd?
Then on the main stack in the view, I call onAppear(perform: ) to load the ad, however I keep getting this error.
.onAppear(perform: {
let request = GADRequest()
GADInterstitialAd.load(withAdUnitID:"ca-app-pub-3940256099942544/4411468910",
request: request,
completionHandler: { [self] ad, error in
if let error = error {
return
}
interstitial = ad
interstitial?.fullScreenContentDelegate = self
}
)
})
"Cannot assign value of type 'ContentView' to type
'GADFullScreenContentDelegate?'"
I am feeling a bit clueless after trying a few different workarounds and trying to look up a setup that is like mine, AdMob docs still show how to implement with class ViewControllers and I would like to figure out how to do this is SwiftUI.
import SwiftUI
import GoogleMobileAds
import AppTrackingTransparency
import AdSupport
class AdsManager: NSObject, ObservableObject {
private struct AdMobConstant {
static let interstitial1ID = "..."
}
final class Interstitial: NSObject, GADFullScreenContentDelegate, ObservableObject {
private var interstitial: GADInterstitialAd?
override init() {
super.init()
requestInterstitialAds()
}
func requestInterstitialAds() {
let request = GADRequest()
request.scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
GADInterstitialAd.load(withAdUnitID: AdMobConstant.interstitial1ID, request: request, completionHandler: { [self] ad, error in
if let error = error {
print("Failed to load interstitial ad with error: \(error.localizedDescription)")
return
}
interstitial = ad
interstitial?.fullScreenContentDelegate = self
})
})
}
func showAd() {
let root = UIApplication.shared.windows.last?.rootViewController
if let fullScreenAds = interstitial {
fullScreenAds.present(fromRootViewController: root!)
} else {
print("not ready")
}
}
}
}
class AdsViewModel: ObservableObject {
static let shared = AdsViewModel()
#Published var interstitial = AdsManager.Interstitial()
#Published var showInterstitial = false {
didSet {
if showInterstitial {
interstitial.showAd()
showInterstitial = false
} else {
interstitial.requestInterstitialAds()
}
}
}
}
#main
struct YourApp: App {
let adsVM = AdsViewModel.shared
init() {
GADMobileAds.sharedInstance().start(completionHandler: nil)
}
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(adsVM)
}
}
Toggle the showInterstitial parameter in the AdsViewModel anywhere in the application and the advertisement will be shown.
In order to use the Admob docs with the newest SwiftUI release, you need to change this line...
.onAppear(perform: {
let request = GADRequest()
GADInterstitialAd.load(withAdUnitID:"ca-app-pub-3940256099942544/4411468910",
request: request,
completionHandler: { [self] ad, error in
if let error = error {
return
}
// Change these two lines of code
interstitial = ad
interstitial?.fullScreenContentDelegate = self
// To...
interstitial = ad
let root = UIApplication.shared.windows.first?.rootViewController
self.interstitial!.present(fromRootViewController: root!)
}
)
})

Getting a fatal error when trying to play sound in Swift

I have worked my way through this tutorial here. One of the last things you do is have a button make sound when it is pressed. I wanted to then continue using that same logic to make a sound board app. However when I stripped the non-essential parts besides it making noise inside a new project I started getting a fatal error.
Here is my ViewController.swfit file:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var sample : AVAudioPlayer?
func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? {
//1
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
//2
var audioPlayer:AVAudioPlayer?
// 3
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
override func viewDidLoad() {
super.viewDidLoad()
if let sample = self.setupAudioPlayerWithFile("Stomach", type:"aif") {
self.sample = sample
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed() {
sample?.play()
}
}
Here is my project when the fatal error hits
I have also tried this solution but I got errors as well.
I am running on El Capitan 10.11.3 with Xcode 7.3
Have you included the an audio file named "Stomach.aif" in your project? If not, pathForResource will return nil and you'll crash when attempting to force unwrap that path. You can use a safer version of this function, although if it can't locate that file it still won't play the audio On the bright side it shouldn't crash.
func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? {
var audioPlayer:AVAudioPlayer? = nil
if let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String) {
let url = NSURL.fileURLWithPath(path)
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
}
return audioPlayer
}

Delegate functions are not called - NSURLConnection

I'm new to swift coding, so most of my code is "this is how I found it on the internet" status.
I'm trying to send a HTTP GET request and then work with it. I'm using NSURLConnection for this. I have 2 swift files in my Xcode project (it is a swift console project, not playground), one is main one and 2nd contains my class I would like to use for delegation:
import Foundation
class Remote: NSObject, NSURLConnectionDelegate {
var data = NSMutableData()
func connect() {
var url = NSURL(string: "https://www.google.com")
var request = NSURLRequest(URL: url!)
NSLog("Is%# main thread", NSThread.isMainThread() ? "" : " NOT");
var conn = NSURLConnection(request: request, delegate: self, startImmediately: false)
conn?.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
conn?.start()
sleep(2)
}
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
println("didReceiveResponse")
}
func connection(connection: NSURLConnection!, didReceiveData conData: NSData!) {
println("didReceiveData")
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
println("DidFinishLoading")
}
deinit {
println("deiniting")
}
}
Here is my main swift code:
import Foundation
var xxx = Remote()
xxx.connect()
sleep(10)
sleep(2)
When I set breakpoints on each println in delegate functions, they are never hit. Execution is done from main thread according to NSLog output.
In debugger I can see that data are sent and received over the network, but I never get any output. I've seen many similar questions here but nothing helped me.
What am I doing wrong?
As Martin R suggested I added correct NSRunLoop into my code right after starting NSURLConnection:
self.shouldKeepRunning = true
let theRL = NSRunLoop.currentRunLoop()
while self.shouldKeepRunning && theRL.runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeInterval: 1.0, sinceDate: NSDate())) { }
shouldKeepRunning is bool variable defined in my class and it set to false in delegate function connectionDidFinishLoading, so

SKStoreProductViewController not showing up in swift (in-app purchases)

I am trying to add in-app purchases to my iOS app. I followed a tutorial and I created the following code:
import UIKit
import StoreKit
let secondViewController: SKStoreProductViewController = SKStoreProductViewController();
class GameViewController: UIViewController, UITextFieldDelegate, GKGameCenterControllerDelegate, SKStoreProductViewControllerDelegate{
func buycoin(){
println("buycoin")
secondViewController.delegate = self
var someitunesid:String = "coin200a"
var productparameters = [SKStoreProductParameterITunesItemIdentifier: someitunesid]
secondViewController.loadProductWithParameters(productparameters, {
(success:Bool!, error: NSError!) -> Void in
if success == true{
self.presentViewController(secondViewController, animated: true, completion: nil)
println("succes")
}
else{
NSLog("%#", error)
println("nosucces")
}
})
}
func productViewControllerDidFinish(viewController: SKStoreProductViewController!) {
secondViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
This code works fine. When the function buycoin() activates, I only get printed buycoin in the console, nothing else.
What am I doing wrong?

Resources