I am facing a strange issue with AWSS3.
Setup:
AWS Mobile HUB
Cognito
DynamoDB
S3
--> Cognito, Dynamo & even S3 (through cognito user data) work.
However I now tried to connect directly to AWS3 with the following code:"
let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = "XXXXXXXXXXXX"
uploadRequest?.key = "user-data/" + awsId! + "/primary_profile_picture.png"
uploadRequest?.body = imgUrl as URL
transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error as? NSError {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error uploading: \(uploadRequest?.key) Error: \(error)")
}
} else {
print("Error uploading: \(uploadRequest?.key) Error: \(error)")
}
return nil
}
let uploadOutput = task.result
print("Upload complete for: \(uploadRequest?.key)")
return nil
})
and am getting the error:
AWSiOSSDK v2.5.1 [Debug] AWSInfo.m line:122 | -[AWSServiceInfo initWithInfoDictionary:checkRegion:] | Couldn't read the region configuration from Info.plist for the client. Please check your `Info.plist` if you are providing the SDK configuration values through `Info.plist`.
2017-02-20 19:29:21.748997 [2210:1152801] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The service configuration is `nil`. You need to configure `Info.plist` or set `defaultServiceConfiguration` before using this method.'
I am using the downloaded plist configuration from AWS Mobiel HUB and am therfore a bit surprised that it does not work (as all other components do).
Any ideas what the issue might be? The plist actually contains the bucket ID & region.
For me, I had to configure the credentials with the following code, before uploading:
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast1,identityPoolId:PoolID)
let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
Where PoolID is my Cognito identity. I hope this helps others.
Your info.plist needs to have S3TransferManager in it.
So, **AWS -> S3TransferManager -> Default -> Region -> ...**
You can find an example of one here
Swift 3 - Xcode 8.3.3
For people still having this issue, I just spent 3h fighting against this annoying setup issue.
I added both these chunks in my Info.plist (replace the variables between ** ** in the second bloc) and now it's working again.
Amazon's documentation isn't updated properly I think. I hope this can save some people some time.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>amazonaws.com</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>amazonaws.com.cn</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
and:
<key>AWS</key>
<dict>
<key>CredentialsProvider</key>
<dict>
<key>CognitoIdentity</key>
<dict>
<key>Default</key>
<dict>
<key>PoolId</key>
<string>**YourCognitoIdentityPoolId**</string>
<key>Region</key>
<string>**AWSRegionUnknown**</string>
</dict>
</dict>
</dict>
<key>S3TransferManager</key>
<dict>
<key>Default</key>
<dict>
<key>Region</key>
<string>**AWSRegionUnknown**</string>
</dict>
</dict>
</dict>
I had the same issue instead of S3TransferManager you should put DynamoDBObjectMapper
e.g..
<key>DynamoDBObjectMapper</key>
<dict>
<key>Default</key>
<dict>
<key>Region</key>
<string>us-east-1</string>
</dict>
</dict>
The problem was, region should be:
us-east-1
Instead of; US_EAST_1
Add Service configuration file with the data
If the above marked solution is not working for some cases. Try the below solution.
As the error says, the service configuration file is nil. So, we need to add the awsconfiguration.json file with the below data.
{
"Version": "1.0",
"IdentityManager": {
"Default": {}
},
"CredentialsProvider": {
"CognitoIdentity": {
"Default": {
"PoolId": "REPLACE_ME",
"Region": "REPLACE_ME"
}
}
},
"S3TransferUtility": {
"Default": {
"Bucket": "REPLACE_ME",
"Region": "REPLACE_ME"
}
}
}
Replace the bucket, region, poolId of your project.
Related
I have built an ios app which is using azure ad login and it was working fine but after install microsoft authenticator app the azure ad login is not working anymore
in fact the alert which does say " app wants to use 'microsoftonline.com' to sign in"
not coming
and uninstalling the authenticator my ios app can login via azure ad again
let kClientID = [clientid]
let kGraphEndpoint = "https://graph.microsoft.com/"
let kAuthority = "https://login.microsoftonline.com/xxxxxxxxx"
let kRedirectUri = [URI]
let kScopes: [String] = ["user.read"]
func initMSAL() throws {
guard let authorityURL = URL(string: kAuthority) else {
print("Unable to create authority URL")
return
}
let authority = try MSALAADAuthority(url: authorityURL)
let msalConfiguration = MSALPublicClientApplicationConfig(clientId: kClientID,
redirectUri: kRedirectUri,
authority: authority)
self.applicationContext = try MSALPublicClientApplication(configuration: msalConfiguration)
self.initWebViewParams()
}
func initWebViewParams() {
self.webViewParamaters = MSALWebviewParameters(authPresentationViewController: self)
}
func acquireTokenInteractively() {
guard let applicationContext = self.applicationContext else { return }
guard let webViewParameters = self.webViewParamaters else { return }
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: webViewParameters)
parameters.promptType = .selectAccount
applicationContext.acquireToken(with: parameters) { (result, error) in
if let error = error {
print("Could not acquire token: \(error)")
return
}
guard let result = result else {
print("Could not acquire token: No result returned")
return
}
self.accessToken = result.accessToken
let aduser=MicrososftUser.init(id: result.uniqueId ?? "", mail: result.account.username ?? "", givenName: result.account.username ?? "", surname: "");
self.adLoginRequest(aduser: aduser)
//self.getContentWithToken()
}
}
info.plist
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.674973595907-gsm9poebb8u1vvb28rvt7osv</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msalv2</string>
<string>msaalv3</string>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
<key>UIAppFonts</key>
<array>
<string>Inter.ttf</string>
<string>Inter-Black.ttf</string>
<string>Inter-ExtraLight.ttf</string>
<string>Inter-Regular.ttf</string>
<string>Inter-Bold.ttf</string>
<string>Inter-Light.ttf</string>
<string>Inter-SemiBold.ttf</string>
<string>Inter-ExtraBold.ttf</string>
<string>Inter-Medium.ttf</string>
<string>Inter-Thin.ttf</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
<string>remote-notification</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
</dict>
</plist>
when i click on azure ad login button the following error is showing in debug window
Could not acquire token: Error Domain=MSALErrorDomain Code=-50000 "(null)" UserInfo={MSALErrorDescriptionKey=Failed to delete broker key with error: -34018, MSALInternalErrorCodeKey=-42708, MSALCorrelationIDKey=4A0C2756-0173-7068-AC4F-AFEC1C84BCB3}
could any one help me with this issue
sorry for my bad english
solving the issue by disabling the access from my app to authenticator.
Adding the following line in initMSAL function
MSALGlobalConfig.brokerAvailability = .none
got help from following links:
https://github.com/AzureAD/microsoft-authentication-library-for-objc/issues/845
https://github.com/AzureAD/microsoft-authentication-library-for-objc/blob/dev/MSAL/src/public/configuration/MSALGlobalConfig.h#L74
I'm having this problem with reading from a txt file from a website without a certificate even though I have allowed it in Info.plist.
My Swift code looks like this:
let url = URL(string: "http://newskit.matsworld.io/domaci/text.txt")!
let task = URLSession.shared.downloadTask(with: url) { localURL, urlResponse, error in
if let localURL = localURL {
if let string = try? String(contentsOf: localURL) {
print(string)
}
}
}
task.resume()
And the Info.plist looks like this:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>http://newskit.matsworld.io</key>
<dict>
<key>ExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>IncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
I'm stuck with this and can't figure it out. Thanks for help!
The domain key is supposed to be just the domain without the scheme (http) and without subdomains if IncludesSubdomains is specified
<key>matsworld.io</key>
I am facing a strange issue with AWSS3.
Setup:
AWS Mobile HUB
Cognito
DynamoDB
S3
--> Cognito, Dynamo & even S3 (through cognito user data) work.
However I now tried to connect directly to AWS3 with the following code:"
let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = "XXXXXXXXXXXX"
uploadRequest?.key = "user-data/" + awsId! + "/primary_profile_picture.png"
uploadRequest?.body = imgUrl as URL
transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error as? NSError {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error uploading: \(uploadRequest?.key) Error: \(error)")
}
} else {
print("Error uploading: \(uploadRequest?.key) Error: \(error)")
}
return nil
}
let uploadOutput = task.result
print("Upload complete for: \(uploadRequest?.key)")
return nil
})
and am getting the error:
AWSiOSSDK v2.5.1 [Debug] AWSInfo.m line:122 | -[AWSServiceInfo initWithInfoDictionary:checkRegion:] | Couldn't read the region configuration from Info.plist for the client. Please check your `Info.plist` if you are providing the SDK configuration values through `Info.plist`.
2017-02-20 19:29:21.748997 [2210:1152801] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The service configuration is `nil`. You need to configure `Info.plist` or set `defaultServiceConfiguration` before using this method.'
I am using the downloaded plist configuration from AWS Mobiel HUB and am therfore a bit surprised that it does not work (as all other components do).
Any ideas what the issue might be? The plist actually contains the bucket ID & region.
For me, I had to configure the credentials with the following code, before uploading:
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USEast1,identityPoolId:PoolID)
let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
Where PoolID is my Cognito identity. I hope this helps others.
Your info.plist needs to have S3TransferManager in it.
So, **AWS -> S3TransferManager -> Default -> Region -> ...**
You can find an example of one here
Swift 3 - Xcode 8.3.3
For people still having this issue, I just spent 3h fighting against this annoying setup issue.
I added both these chunks in my Info.plist (replace the variables between ** ** in the second bloc) and now it's working again.
Amazon's documentation isn't updated properly I think. I hope this can save some people some time.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>amazonaws.com</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>amazonaws.com.cn</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
and:
<key>AWS</key>
<dict>
<key>CredentialsProvider</key>
<dict>
<key>CognitoIdentity</key>
<dict>
<key>Default</key>
<dict>
<key>PoolId</key>
<string>**YourCognitoIdentityPoolId**</string>
<key>Region</key>
<string>**AWSRegionUnknown**</string>
</dict>
</dict>
</dict>
<key>S3TransferManager</key>
<dict>
<key>Default</key>
<dict>
<key>Region</key>
<string>**AWSRegionUnknown**</string>
</dict>
</dict>
</dict>
I had the same issue instead of S3TransferManager you should put DynamoDBObjectMapper
e.g..
<key>DynamoDBObjectMapper</key>
<dict>
<key>Default</key>
<dict>
<key>Region</key>
<string>us-east-1</string>
</dict>
</dict>
The problem was, region should be:
us-east-1
Instead of; US_EAST_1
Add Service configuration file with the data
If the above marked solution is not working for some cases. Try the below solution.
As the error says, the service configuration file is nil. So, we need to add the awsconfiguration.json file with the below data.
{
"Version": "1.0",
"IdentityManager": {
"Default": {}
},
"CredentialsProvider": {
"CognitoIdentity": {
"Default": {
"PoolId": "REPLACE_ME",
"Region": "REPLACE_ME"
}
}
},
"S3TransferUtility": {
"Default": {
"Bucket": "REPLACE_ME",
"Region": "REPLACE_ME"
}
}
}
Replace the bucket, region, poolId of your project.
This question already has answers here:
NSURLSession/NSURLConnection HTTP load failed on iOS 9
(13 answers)
Closed 6 years ago.
Here the code:
let url = NSURL(string: "http://a337.phobos.apple.com/us/r30/Music/d5/a8/6b/mzi.msfqeogi.aac.p.m4a")
let downloadTask = self.downloadSession.downloadTaskWithURL(url!)
downloadTask.resume()
-> OK
Replace the URL with:
http://s1mp3.r41s223.vcdn.vn/d3f549abeeef07b15efe/2937387453157939420?key=c2WuQChtsmR9yfdz9I-jnw&expires=1480695588&filename=Only%20Love%20-%20Trademark.mp3
-> it doesn't work; nothing happens
By default starting in iOS 9 all connections must be https. If the website for the second URL doesn't support https:// then the download would fail.
I suggest checking the error code you get back from the Download
If you want to use url with HTTP connection, then in your info.plist file add the following
App Transport Security Setting and in that add subsection Allow Arbitrary Loads and set the value to YES.
Please add in Plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>akamaihd.net</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>facebook.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>fbcdn.net</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>graph.facebook.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
</plist>
Then using Alamofire 4.0 Swift 3.0
Using below method, you can download any thing, ex. PDF
// Mark:- Download File
func DownloadFile(strFileUrl : String, strFileName : String, success:#escaping (_ strResultURL: String) -> Void , failure:#escaping (_ responseObject:AnyObject) -> Void) {
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendingPathComponent("\(strFileName)")
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(strFileUrl, to: destination).response { response in
if SVProgressHUD.isVisible() {
SVProgressHUD.dismiss()
}
if response.error == nil {
success("\(response.destinationURL!)")
}
else {
failure(response.error as AnyObject)
}
}.downloadProgress { (progress) in
print("Download Progress: \(progress.fractionCompleted)")
SVProgressHUD.showProgress(Float(progress.fractionCompleted), status: AppAlertMsg.KDownloadingPDFs)
}
}
Our REST based application can be used for testing on multiple internal environments each with a different REST end point. Is there a simple way to set up environment level configuration within an iOS (Swift 3) app? I've seen a few approaches but they all seem pretty involved.
This is my approach of doing things when we have multiple end points. I used to make a ConfigurationManager class something like this
Swift 3.0 code
import Foundation
import UIKit
let kEnvironmentsPlist:NSString? = "Environments"
let kConfigurationKey:NSString? = "ActiveConfiguration"
let kAPIEndpointKey:NSString? = "APIEndPoint"
let kLoggingEnabledKey:NSString? = "LoggingEnabled"
let kAnalyticsTrackingEnabled:NSString? = "AnalyticsTrackingEnabled"
class ConfigurationManager:NSObject {
var environment : NSDictionary?
//Singleton Method
static let sharedInstance: ConfigurationManager = {
let instance = ConfigurationManager()
// setup code
return instance
}()
override init() {
super.init()
initialize()
}
// Private method
func initialize () {
var environments: NSDictionary?
if let envsPlistPath = Bundle.main.path(forResource: "Environments", ofType: "plist") {
environments = NSDictionary(contentsOfFile: envsPlistPath)
}
self.environment = environments!.object(forKey: currentConfiguration()) as? NSDictionary
if self.environment == nil {
assertionFailure(NSLocalizedString("Unable to load application configuration", comment: "Unable to load application configuration"))
}
}
// CurrentConfiguration
func currentConfiguration () -> String {
let configuration = Bundle.main.infoDictionary?[kConfigurationKey! as String] as? String
return configuration!
}
// APIEndpoint
func APIEndpoint () -> String {
let configuration = self.environment![kAPIEndpointKey!]
return (configuration)! as! String
}
// isLoggingEnabled
func isLoggingEnabled () -> Bool {
let configuration = self.environment![kLoggingEnabledKey!]
return (configuration)! as! Bool
}
// isAnalyticsTrackingEnabled
func isAnalyticsTrackingEnabled () -> String {
let configuration = self.environment![kAnalyticsTrackingEnabled!]
return (configuration)! as! String
}
func applicationName()->String{
let bundleDict = Bundle.main.infoDictionary! as NSDictionary
return bundleDict.object(forKey: "CFBundleName") as! String
}
}
In Project--> Info Add some new configurations as per your need.
I have added Staging and QA as extra endpoints.Generally I use to make Staging as Release config and QA as Debug. So it will look like:
Now go to Targets -> Build Settings and add a User Defined Setting
Give the name of the user defined like ACTIVE_CONFIGURATION.
Add a key named ActiveConfiguration in info.plist with a variable name as $(ACTIVE_CONFIGURATION) same as given in User Defined Settings with a $ in the beginning. We gave the name of key as ActiveConfiguration because we are using the same name in our ConfigurationManager.swift class for kConfigurationKey.
let kConfigurationKey:NSString? = "ActiveConfiguration"
You can define as per your naming convention.
It will look like:
Now in the ConfigurationManager class I am getting a path for Environments.plist file.
I will just make a Environments.plist file like this:
The actual description source of this file is
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Development</key>
<dict>
<key>APIEndPoint</key>
<string>https://dev</string>
<key>LoggingEnabled</key>
<true/>
<key>AnalyticsTrackingEnabled</key>
<true/>
<key>Flurry</key>
<dict>
<key>FlurryApplicationID</key>
<string></string>
<key>FlurryApplicationSecret</key>
<string></string>
</dict>
<key>Facebook</key>
<dict>
<key>FacebookAppID</key>
<string></string>
<key>FacebookAppSecret</key>
<string></string>
</dict>
</dict>
<key>QA</key>
<dict>
<key>APIEndPoint</key>
<string>https://qa</string>
<key>LoggingEnabled</key>
<true/>
<key>AnalyticsTrackingEnabled</key>
<true/>
<key>Flurry</key>
<dict>
<key>FlurryApplicationID</key>
<string></string>
<key>FlurryApplicationSecret</key>
<string></string>
</dict>
<key>Facebook</key>
<dict>
<key>FacebookAppID</key>
<string></string>
<key>FacebookAppSecret</key>
<string></string>
</dict>
</dict>
<key>Staging</key>
<dict>
<key>APIEndPoint</key>
<string>https://staging</string>
<key>LoggingEnabled</key>
<false/>
<key>AnalyticsTrackingEnabled</key>
<true/>
<key>Flurry</key>
<dict>
<key>FlurryApplicationID</key>
<string></string>
<key>FlurryApplicationSecret</key>
<string></string>
</dict>
<key>Facebook</key>
<dict>
<key>FacebookAppID</key>
<string>840474532726958</string>
<key>FacebookAppSecret</key>
<string></string>
</dict>
</dict>
<key>Production</key>
<dict>
<key>APIEndPoint</key>
<string>https://production</string>
<key>LoggingEnabled</key>
<true/>
<key>AnalyticsTrackingEnabled</key>
<true/>
<key>Flurry</key>
<dict>
<key>FlurryApplicationID</key>
<string></string>
<key>FlurryApplicationSecret</key>
<string></string>
</dict>
<key>Facebook</key>
<dict>
<key>FacebookAppID</key>
<string></string>
<key>FacebookAppSecret</key>
<string></string>
</dict>
</dict>
</dict>
</plist>
We are now good to go. Now you have to just call
ConfigurationManager.sharedInstance.APIEndpoint()
for your respective end points.
Now you just have to change the schemes from Edit Schemes and you are done and change the Build Configuration in info.
This not only manages API End Points but also other things like whether to enable analytics or tracking for the respective end point or different ids of Facebook for different end points.
As Zac Kwan suggested, you can use different schemes to accomplish this, but you don't necessarily have to create a different configuration as well. Each scheme can specify unique environment variables. Then, access them from Swift:
let prodURL = "http://api.com"
let baseURL = ProcessInfo.processInfo.environment["BASE_URL"] ?? prodURL
I found that creating different Scheme and Configuration for your project works best. My setup is as follow:
I usually have 3 different scheme, MyApp-dev, MyApp-staging and MyApp.
Each of the scheme i created User-Defined-Attribute to have different string appending to my Bundle Display Name. So it can concurrently appear on my iOS device as MyApp-d, MyApp-s and MyApp. Each also have its own Bundle ID Then I create custom flags for each of them.
So in my Routes.swift files i have something like this at the top:
#if PRODUCTION
static let hostName = "http://production.com/api/v1/"
#elseif STAGING
static let hostName = "http://staging.com/api/v1/"
#else
static let hostName = "http://development.com/api/v1/"
#endif
There is quite a few ways in how to update different hostname. But ultimately creating different Scheme and Configuration is always the first step.
Here is a few links that might help you get started:
https://medium.com/#danielgalasko/change-your-api-endpoint-environment-using-xcode-configurations-in-swift-c1ad2722200e#.o6nhic3pf
http://limlab.io/swift/2016/02/22/xcode-working-with-multiple-environments.html
I ended up using https://github.com/theappbusiness/ConfigGenerator:
A command line tool to auto-generate configuration file code, for use
in Xcode projects. The configen tool is used to auto-generate
configuration code from a property list. It is intended to create the
kind of configuration needed for external URLs or API keys used by
your app. Currently supports both Swift and Objective-C code
generation.