Can't get results from ConsentDocument by identifier. ResearchKit - ios

Here is what I want to do: use results from ConsentDocument for view it in ViewController using identifier of step. But signature is always nil. So, how can I get fisrt and last name from Consent Document?
override func viewDidLoad() {
super.viewDidLoad()
let signatureResult = ORKConsentSignatureResult(identifier: "ConsentReviewStep")
let signature = signatureResult.signature
let label = UILabel(frame: CGRectMake(0, 0, 200, 21))
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = signature?.givenName
self.view.addSubview(label)}
Here I'm creating step, where user gave me givenName(first name) and familyName(last name). This step named reviewConsentStep.
#IBAction func joinButtonTapped(sender: UIButton) {
let consentDocument = ConsentDocument()
let consentStep = ORKVisualConsentStep(identifier: "VisualConsentStep", document: consentDocument)
let healthDataStep = HealthDataStep(identifier: "Health")
let signature = consentDocument.signatures!.first!
let reviewConsentStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: signature, inDocument: consentDocument)
reviewConsentStep.text = "Review the consent form."
reviewConsentStep.reasonForConsent = "Consent to join the Developer Health Research Study."
let passcodeStep = ORKPasscodeStep(identifier: "Passcode")
passcodeStep.text = "Now you will create a passcode to identify yourself to the app and protect access to information you've entered."
let completionStep = ORKCompletionStep(identifier: "CompletionStep")
completionStep.title = "Welcome aboard."
completionStep.text = "Thank you for joining this study."
let orderedTask = ORKOrderedTask(identifier: "Join", steps: [consentStep, reviewConsentStep, healthDataStep, passcodeStep, completionStep])
let taskViewController = ORKTaskViewController(task: orderedTask, taskRunUUID: nil)
taskViewController.delegate = self
presentViewController(taskViewController, animated: true, completion: nil)
}
}

Related

Cannot create an Envelope using online signing mode

I'm trying to create an Envelop and sign it using online mode.
At first, I logged in to my account
#IBAction private func signDocument(_ sender: UIButton) {
guard let hostURL = URL(string: Environment.current.docuSignHost) else { return }
isLoading = true
DSMManager.login(withEmail: Environment.current.docuSignUserID,
password: Environment.current.docuSignPass,
integratorKey: Environment.current.docuSignIntegratorKey,
host: hostURL) { [weak self] info, error in
self?.isLoading = false
if let error = error {
self?.error = error
} else {
self?.showDocuSign(info: info)
}
}
}
// MARK: - Helpers
private func showDocuSign(info: DSMAccountInfo?) {
guard let info = info else { return }
envelopManager.perform(with: info, presentingController: self)
}
After that, I created my test Envelop:
final class EnvelopeManager {
private let envelopesManager = DSMEnvelopesManager()
private let templateManager = DSMTemplatesManager()
// MARK: - Lifecycle
func perform(with config: DSMAccountInfo, presentingController: UIViewController) {
guard let documentURL = R.file.tgkCapitalPortfolioBAgreementPdf(),
let documentData = try? Data(contentsOf: documentURL) else { return }
let envelopDefinition = DSMEnvelopeDefinition()
envelopDefinition.envelopeName = "Some name"
envelopDefinition.emailSubject = "Please Sign Envelope on Document"
envelopDefinition.emailBlurb = "Hello, Please sign my Envelope"
let document = DSMDocument()
document.name = R.file.tgkCapitalPortfolioBAgreementPdf.name
document.documentId = "1"
document.documentBase64 = documentData.base64EncodedString()
envelopDefinition.documents = [document]
let signHere = DSMSignHere()
signHere.documentId = document.documentId
signHere.pageNumber = 1
signHere.recipientId = "1"
signHere.anchorXOffset = 100
signHere.anchorYOffset = 100
signHere.tabId = "1"
let tabs = DSMTabs()
tabs.signHereTabs = [signHere]
let signer = DSMSigner()
signer.canSignOffline = false
signer.email = config.email
signer.name = config.userName
signer.recipientId = "1"
signer.tabs = tabs
let signers: [DSMSigner] = [signer]
let recipients = DSMRecipients()
recipients.signers = signers
envelopDefinition.recipients = recipients
envelopDefinition.status = "sent"
envelopesManager.composeEnvelope(with: envelopDefinition, signingMode: .online) { [weak self] envelopID, error in
if let envelopID = envelopID {
print(envelopID)
self?.presentSigning(presenter: presentingController,
envelopeID: envelopID)
} else {
print(error.localizedDescription)
}
}
}
private func presentSigning(presenter: UIViewController, envelopeID: String) {
envelopesManager.presentSigning(withPresenting: presenter,
envelopeId: envelopeID,
animated: true) { (viewController, error) in
if let viewController = viewController {
print(viewController)
}
if let error = error {
print(error.localizedDescription)
}
}
}
}
But here
envelopesManager.composeEnvelope(with: envelopDefinition, signingMode: .online) { [weak self] envelopID, error in
if let envelopID = envelopID {
print(envelopID)
self?.presentSigning(presenter: presentingController,
envelopeID: envelopID)
} else {
print(error.localizedDescription)
}
}
I have an error:
Envelope creation online is not supported at this moment. Please try
offline mode
When I switched to offline mode I can't use the method
envelopesManager.presentSigning(withPresenting:, enveloped: , animated:, completeion)
Because it works only for envelops which were created in the online mode. And in my case completion block is not executed.
How to resolve this issue? How I can create an envelope in online mode and sign it? What I'm doing wrong? I just want to select my pdf which contains in the project bundle and in some position add the sign.
The sample project which was provided here doesn't match my requirements. Because there is using a template from server and creating envelop via presentComposeEnvelopeController method for choosing document and etc.
XCode 12.4, iOS 13/14, DocuSign 2.4.1 included in the project via CocoaPods.
Edit1
I have updated my perform method:
func perform(with config: DSMAccountInfo, presentingController: UIViewController) {
guard let documentURL = R.file.tgkCapitalPortfolioBAgreementPdf(),
let documentData = try? Data(contentsOf: documentURL) else { return }
let envelopDefinition = DSMEnvelopeDefinition()
envelopDefinition.envelopeName = "Some name"
envelopDefinition.emailSubject = "Please Sign Envelope on Document"
envelopDefinition.emailBlurb = "Hello, Please sign my Envelope"
let document = DSMDocument()
document.name = R.file.tgkCapitalPortfolioBAgreementPdf.name
document.documentId = "1"
document.documentBase64 = documentData.base64EncodedString()
envelopDefinition.documents = [document]
let signHere = DSMSignHere()
signHere.documentId = document.documentId
signHere.pageNumber = 1
signHere.recipientId = "1"
signHere.frame = .init(originX: 100,
originY: 100,
width: 100,
height: 100,
originYOffsetApplied: 50)
signHere.tabId = "1"
let tabs = DSMTabs()
tabs.signHereTabs = [signHere]
let signer = DSMSigner()
signer.email = config.email
signer.name = config.userName
signer.recipientId = "1"
signer.tabs = tabs
let signers: [DSMSigner] = [signer]
let recipients = DSMRecipients()
recipients.signers = signers
envelopDefinition.recipients = recipients
envelopDefinition.status = "created"
envelopesManager.composeEnvelope(with: envelopDefinition, signingMode: .offline) { [weak self] envelopID, error in
if let envelopID = envelopID {
print(envelopID)
self?.presentSigning(presenter: presentingController,
envelopeID: envelopID)
} else {
print(error.localizedDescription)
}
}
}
and presentSigning method too:
private func presentSigning(presenter: UIViewController, envelopeID: String) {
envelopesManager.resumeSigningEnvelope(withPresenting: presenter,
envelopeId: envelopeID) { (viewController, error) in
if let viewController = viewController {
print(viewController)
}
if let error = error {
print(error.localizedDescription)
}
}
}
But now I have got the error in the presentSigning method: Envelope is ready for sync and can not be resumed for signing.
And any screen with my pdf document was not shown. How to resolve it? How I can preview this document and after that add the ability for a user to sign it?
Solution
The working code of the EnvelopManager class:
final class EnvelopeManager {
private let envelopesManager = DSMEnvelopesManager()
private let templateManager = DSMTemplatesManager()
// MARK: - Lifecycle
func sync() {
envelopesManager.syncEnvelopes()
}
func perform(with config: DSMAccountInfo, presentingController: UIViewController) {
guard let path = Bundle.main.path(forResource: R.file.tgkCapitalPortfolioBAgreementPdf.name, ofType: "pdf") else { return }
let envelopDefinition = DSMEnvelopeDefinition()
envelopDefinition.envelopeName = "Some name"
envelopDefinition.emailSubject = "Please Sign Envelope on Document"
envelopDefinition.emailBlurb = "Hello, Please sign my Envelope"
let builder = DSMDocumentBuilder()
builder.addDocumentId("1")
builder.addName(R.file.tgkCapitalPortfolioBAgreementPdf.name)
builder.addFilePath(Bundle.main.path(forResource: R.file.tgkCapitalPortfolioBAgreementPdf.name,
ofType: "pdf")!)
let document = builder.build()
envelopDefinition.documents = [document]
let signHere = DSMSignHere()
signHere.documentId = document.documentId
signHere.pageNumber = 1
signHere.recipientId = "1"
signHere.frame = .init(originX: 100,
originY: 100,
width: 100,
height: 100,
originYOffsetApplied: 50)
signHere.tabId = "1"
let tabs = DSMTabs()
tabs.signHereTabs = [signHere]
let signer = DSMSigner()
signer.email = config.email
signer.name = config.userName
signer.userId = config.userId
signer.clientUserId = config.userId
signer.routingOrder = 1
signer.recipientId = "1"
signer.tabs = tabs
let signers: [DSMSigner] = [signer]
let recipients = DSMRecipients()
recipients.signers = signers
envelopDefinition.recipients = recipients
envelopDefinition.status = "created"
envelopesManager.composeEnvelope(with: envelopDefinition, signingMode: .offline) { [weak self] envelopID, error in
if let envelopID = envelopID {
print(envelopID)
self?.presentSigning(presenter: presentingController,
envelopeID: envelopID)
} else {
print(error.localizedDescription)
}
}
}
private func presentSigning(presenter: UIViewController, envelopeID: String) {
envelopesManager.resumeSigningEnvelope(withPresenting: presenter,
envelopeId: envelopeID) { (viewController, error) in
if let viewController = viewController {
print(viewController)
}
if let error = error {
print(error.localizedDescription)
}
}
}
}
After you will have signed the document do not forget to call the sync method on the top view controller
But now I have got the error in the presentSigning method: Envelope is ready for sync and can not be resumed for signing.
Envelope is ready for sync and can not be resumed for signing. denotes the state that envelope has no local signers awaiting signing. This could happen because of a few reasons.
Taking a look at the adding recipient section of guide, this adds a Remote Signer to local envelope.
// Create an envelope recipient with name and email and assign an id and type with routing order
DSMEnvelopeRecipient *recipient = [[[[[[DSMRecipientBuilder builderForType: DSMRecipientTypeSigner]
addRecipientId: #"1"]
addSignerName: #"Jane Wood"]
addSignerEmail: #"JaneWood#docusign.com"]
addRoutingOrder: 1]
build];
No local signers have been added to capture signatures. If you need to add a local signer they could represent following cases:
SDK authenticated account could be used as a signer (DSMRecipientTypeSigner). In the example: #"JaneWood#docusign.com" is logged in with SDK with routingOrder (or SigningOrder) of 1.
SDK authenticated account could be used as a host to an in-person-signer (DSMRecipientTypeInPersonSigner). The following example would add an in-person-signer for #"JaneWood#docusign.com" as host:
// Create an envelope recipient with name and email and assign an id and type with routing order
DSMEnvelopeRecipient *recipient = [[[[[[[DSMRecipientBuilder builderForType: DSMRecipientTypeInPersonSigner]
addRecipientId: #"1"]
addHostName: #"Jane Wood"]
addHostEmail: #"JaneWood#docusign.com"]
addSignerName: #"IPS - John Local Doe"]
addRoutingOrder: 1]
build];
Only remote signers (non-local SDK account) have been added to envelope: Invoking syncEnvelopes on such envelopes will send documents and email the remote-signers to complete signing.
Note: All of the local signers have already completed signing: You'd reach this case once all local signatures have been captured, and using syncEnvelopes would send envelope to DocuSign servers.
#igdev: Thanks for adding code snippets and details explaining your approach.
How I can create an envelope in online mode and sign it?
As of current SDK version, creating online envelopes with EnvelopeDefinition is not yet supported.
Following method is only supported for remote-envelopes that have been already created (via DocuSign API or Web) and accessible on the DocuSign account under use by Native-SDK.
envelopesManager.presentSigning(withPresenting:, enveloped: , animated:, completion)
I just want to select my pdf which contains in the project bundle and in some position add the sign.
Compose flow based envelope creation would enable you to use the PDF from the bundle, position tabs and present signing in the offline mode. Here is a guide (Compose Envelope) that lists steps with sample code to get the desired result. Following snippet from compose envelope guide shows how such envelope can be presented for signing:
if (envelope) {
// Compose the envelope to automatically cache it
[self.envelopesManager composeEnvelopeWithEnvelopeDefinition: envelope
signingMode: DSMSigningModeOffline
completion: ^(NSString * _Nullable envelopeId, NSError * _Nonnull error) {
// error checks in case envelope compose failed. Also use notifications for caching related events.
if (error) { ... }
// Resume the envelope to start the signing process
[self.envelopesManager resumeSigningEnvelopeWithPresentingController: self
envelopeId: envelopeId
completion: ^(UIViewController * _Nullable presentedController, NSError * _Nullable error) {
// error checks in case UI presentation failed. Use notifications for other events.
if (error) { ... }
}];
}
];
}
The sample code prior to update (thanks for adding it) to use the tab-frame instead of anchors is correct step as anchors aren't supported in offline mode by the SDK. In order to avoid such issues, it's best to use the EnvelopeBuilder (which in turn uses Recipient and TabBuilder) to create tabs for individual recipients and assign correct frames (e.g. signHere.frame = CGRect(x: 100, y: 100, width: 50, height: 40)). Using EnvelopeBuilder also ensures that custom envelope data goes through validation process.
/*!
* #discussion add frame of the tab (e.g. CGFrameMake(100, 100, 50, 40) for Sign Tab) and return builder.
* #param frame a frame to draw tab within
*/
- (DSMTabBuilder *)addFrame:(CGRect)frame;
Check answer below for envelope ready for sync state:

View is not displayed

I have an alert box that takes user input and starts a download task. After the user clicks "Ok," I want the screen to show a UIView that I added an ActivityIndicator to while the download occurs. The download occurs successfully and the function correctly opens up the next controller, however, the custom view nor activity indicator are ever displayed. Here's my code:
private func getKeyFromAlert() {
let alert = UIAlertController(title: "Enter Key", message: "Enter your text key below. If you want to scan it instead, click \"Scan Key.\" ", preferredStyle: .alert)
alert.addTextField { (textField) in
let attribString = NSAttributedString(string: "Enter your app code here")
textField.attributedPlaceholder = attribString
}
let scanAction = UIAlertAction(title: "Scan Key", style: .default) { _ in
self.openSettingsForApp()
}
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
let textField = alert.textFields![0]
if let text = textField.text {
let encoded = text.toBase64()
let status = APIKeychain.storeToken(encoded)
if !status {
self.displayAlertForBadKeychain(useCamera: false)
} else {
self.addLoader()
self.dismissSetup()
}
} else {
let _ = APIKeychain.storeToken("")
self.addLoader()
self.dismissSetup()
}
}
alert.addAction(scanAction)
alert.addAction(okAction)
show(alert, sender: nil)
}
The function in question that I use to display the UIView is addLoader()
The code for addLoader is:
private func addLoader() {
let frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
let loaderView = UIView(frame: frame)
loaderView.alpha = 1.0
loaderView.backgroundColor = UIColor.white
let activitySpinner: UIActivityIndicatorView = UIActivityIndicatorView(frame: loaderView.frame)
activitySpinner.center = loaderView.center
activitySpinner.hidesWhenStopped = false
activitySpinner.style = .whiteLarge
activitySpinner.startAnimating()
loaderView.addSubview(activitySpinner)
self.view.addSubview(loaderView)
self.view.layoutIfNeeded()
}
I've tried several iterations of setNeedsDisplay and setNeedsLayout without luck. I've also tried explicitly declaring this in a DispatchQueue.main.async without any affect as well.
EDIT
I added the code below for dismissSetup()
private func dismissSetup() {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
DispatchQueue.global(qos: .background).async {
if self.updateDatabase {
//This will start the download process
let _ = WebDataFetcher(dataStack: self.dataStack)
}
dispatchGroup.leave()
}
dispatchGroup.wait()
let mainSB = UIStoryboard(name: "UserInputs", bundle: nil)
let mainVC = mainSB.instantiateViewController(withIdentifier: "userInputs")
appDelegate.window?.rootViewController = mainVC
}

UITabBarContoller, disappears last item from time to time

I have my custom TabBarController as usual, which contains 8 viewController.
class STTabBarController: UITabBarController,UITabBarControllerDelegate {
let tabBarOrderKey = "tabBarOrderKey"
private var messangerNavigationController: UINavigationController!
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
configureViewControllers()
setUpTabBarItemTags()
getSavedTabBarItemsOrder()
}
func configureViewControllers() {
let clientsController = STClientsViewController(nibName: "STClientsViewController", bundle: nil)
let clientNavigationController = UINavigationController(rootViewController: clientsController)
clientsController.title = "Clients"
clientNavigationController.tabBarItem.image = UIImage(named: "Client")
let openHouseController = STOpenHouseViewController(nibName: "STOpenHouseViewController", bundle: nil)
let openHouseNavigationController = UINavigationController(rootViewController: openHouseController)
openHouseController.title = "Open House"
openHouseNavigationController.tabBarItem.image = UIImage(named: "OpenHouse")
let performanceController = STChartsViewController(nibName: "STChartsViewController", bundle: nil)
let performanceNavigationController = UINavigationController(rootViewController: performanceController)
performanceController.title = "Performance"
performanceNavigationController.tabBarItem.image = UIImage(named: "Performance")
let calculatorsController = STCalculatorsViewController(nibName: "STCalculatorsViewController", bundle: nil)
let calculatorsNavigationController = UINavigationController(rootViewController: calculatorsController)
calculatorsController.title = "Calculators"
calculatorsNavigationController.tabBarItem.image = UIImage(named: "Calculators")
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let communityViewController = storyBoard.instantiateViewController(withIdentifier: "Navigation")
communityViewController.title = "Community"
communityViewController.tabBarItem.image = UIImage (named:"Community")
let industryProfessionalsController = STIndustryProfessionalsViewController(nibName: "STIndustryProfessionalsViewController", bundle: nil)
let industryProfessionalsNavigationController = UINavigationController(rootViewController: industryProfessionalsController)
industryProfessionalsController.title = "Vendors"
industryProfessionalsNavigationController.title = "Vendors"
industryProfessionalsNavigationController.tabBarItem.image = UIImage(named: "Industry-professionals")
let agentResourcesController = STAgentResourcesViewController(nibName: "STAgentResourcesViewController", bundle: nil)
let agentResourcesNavigationController = UINavigationController(rootViewController: agentResourcesController)
agentResourcesController.title = "Resources"
agentResourcesNavigationController.title = "Resources"
agentResourcesNavigationController.tabBarItem.image = UIImage(named: "Agent-Resources")
let settingsController = STSettingsViewController(nibName: "STSettingsViewController", bundle: nil)
let settingsNavigationController = UINavigationController(rootViewController: settingsController)
settingsController.title = "Settings"
settingsNavigationController.tabBarItem.image = UIImage(named: "Settings")
let coachController = STCoachsCornerViewController(nibName: "STCoachsCornerViewController", bundle: nil)
let coachNavigationController = UINavigationController(rootViewController: coachController)
coachController.navigationItem.title = "Action Plan"
coachNavigationController.tabBarItem.title = "Plan"
coachNavigationController.tabBarItem.image = UIImage(named: "Plan")
self.viewControllers = [clientNavigationController ,performanceNavigationController,calculatorsNavigationController, coachNavigationController,industryProfessionalsNavigationController,agentResourcesNavigationController,openHouseNavigationController, settingsNavigationController]
tabBar.isTranslucent = false
let topBorder = CALayer()
topBorder.frame = CGRect(x: 0, y: 0, width: 1000, height: 0.5)
topBorder.backgroundColor = UIColor.returnRGBColor(r: 229, g: 231, b: 235, alpha: 1).cgColor
tabBar.layer.addSublayer(topBorder)
tabBar.clipsToBounds = true
}
func setUpTabBarItemTags() {
var tag = 0
if let viewControllers = viewControllers {
for view in viewControllers {
view.tabBarItem.tag = tag
tag += 1
}
}
}
func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
if let tabBarOrder = UserDefaults.standard.object(forKey: tabBarOrderKey) as? [Int] {
for tag in tabBarOrder {
newViewControllerOrder.append(initialViewControllers[tag])
}
setViewControllers(newViewControllerOrder, animated: false)
}
}
}
func tabBarController(_ tabBarController: UITabBarController, didEndCustomizing viewControllers: [UIViewController], changed: Bool) {
var orderedTagItems = [Int]()
if changed {
for viewController in viewControllers {
let tag = viewController.tabBarItem.tag
orderedTagItems.append(tag)
}
UserDefaults.standard.set(orderedTagItems, forKey: tabBarOrderKey)
}
}
And I met the problem when I start my on different devices and from time to time it can hide Settings(last) item in "More" tab.This look kinda ridiculous because code is straightforward and simple as you see and I dont know what can be wrong here.
Does smb know what can it be? Thanks
The problem was in saving order of this tabs to User Defaults.
I had 7 controllers, but when was trying to save it, saved was only 6.
Here is final code of saving function:
func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
if let tabBarOrder = UserDefaults.standard.object(forKey: tabBarOrderKey) as? [Int] {
for tag in tabBarOrder {
newViewControllerOrder.append(initialViewControllers[tag])
}
let difference = Set(initialViewControllers).subtracting(newViewControllerOrder)
newViewControllerOrder.append(contentsOf: difference)
setViewControllers(newViewControllerOrder, animated: false)
}
}
}

Swift: Not Return to English Version after translate to Arabic

i want to localize my apps between English and Arabic version included RTL. but it not return to English Version with left to right after translate to Arabic, it just repeats to Arabic version when i click navigation item UIButton, also navigation item flag not show properly it is just repeating Arabic flag.
// here is my code
import UIKit
import Foundation
// homeCollectionViewController
class HomeCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
let navLanguageBtn = UIButton()
static var language = ""
override func viewDidLoad() {
super.viewDidLoad()
setupHomeNavBarBtn()
}
// NavigationBar
func setupHomeNavBarBtn() {
navLanguageBtn.frame = CGRect(x: 0, y: 0, width: CollectionViewSize.width / 15, height: CollectionViewSize.width / 15)
navLanguageBtn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, CollectionViewSize.width / 60, 0)
navLanguageBtn.setImage(UIImage(named: "arab_flag")?.withRenderingMode(.alwaysOriginal), for: .normal)
navLanguageBtn.contentMode = .scaleAspectFit
navLanguageBtn.addTarget(self, action: #selector(navLanguageBtnClick), for: .touchUpInside)
let navLanguageBtnItem = UIBarButtonItem(customView: navLanguageBtn)
self.navigationItem.setRightBarButtonItems([ navLanguageBtnItem], animated: true)
}
// ButtonClick
public func navLanguageBtnClick(){
if (navLanguageBtn.isSelected == true)
{
print("language btn click true English flag")
navLanguageBtn.setImage(UIImage(named: "english_flag")?.withRenderingMode(.alwaysOriginal), for: UIControlState.normal)
UIView.appearance().semanticContentAttribute = .forceRightToLeft
navLanguageBtn.isSelected = false
let path = Bundle.main.path(forResource: "ar-SA", ofType: "lproj")
let bundal = Bundle.init(path: path!)! as Bundle
HomeCollectionViewController.language = "ar"
navigationItem.title = bundal.localizedString(forKey: "home", value: nil, table: nil)
SecondHomeCell.newProductTrans = bundal.localizedString(forKey: "newProduct", value: nil, table: nil)
SecondHomeCell.populerStoriesTrans = bundal.localizedString(forKey: "populerStories", value: nil, table: nil)
let navController: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController as? UINavigationController)
let layout = UICollectionViewFlowLayout()
let control = HomeCollectionViewController(collectionViewLayout: layout)
navController?.pushViewController(control, animated: true)
let AR_POST_PARAMETERS = ["language": HomeCollectionViewController.language]
self.secondHomeCell?.secondHomeCellDataLoad(POST_PARAMETERS: AR_POST_PARAMETERS as! Dictionary<String, String>)
}
else
{
print("language btn click true arabic flag")
navLanguageBtn.setImage(UIImage(named: "arab_flag")?.withRenderingMode(.alwaysOriginal), for: UIControlState.selected)
UIView.appearance().semanticContentAttribute = .forceLeftToRight
// UIView.appearance().transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
navLanguageBtn.isSelected = true
// self.lblCountryName.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
let path = Bundle.main.path(forResource: "en", ofType: "lproj")
let bundal = Bundle.init(path: path!)! as Bundle
//home
HomeCollectionViewController.language = "en"
navigationItem.title = bundal.localizedString(forKey: "home", value: nil, table: nil)
SecondHomeCell.newProductTrans = bundal.localizedString(forKey: "newProduct", value: nil, table: nil)
SecondHomeCell.populerStoriesTrans = bundal.localizedString(forKey: "populerStories", value: nil, table: nil)
let navController: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController as? UINavigationController)
let layout = UICollectionViewFlowLayout()
let control = HomeCollectionViewController(collectionViewLayout: layout)
navController?.pushViewController(control, animated: true)
let AR_POST_PARAMETERS = ["language": HomeCollectionViewController.language]
self.secondHomeCell?.secondHomeCellDataLoad(POST_PARAMETERS: AR_POST_PARAMETERS as! Dictionary<String, String>)
}
}
}
For changing the language of application, from a button click within the appliaction, i suggest you to ask the user to relaunch the application, for the change to happen.
In my application, i am changing the language like this.
//On Button click:
if applicationLanguage() == "ar" {
setApplicationLanguage(languageCode: "en-US")
}
else if applicationLanguage() == "en" {
setApplicationLanguage(languageCode: "ar")
}
func applicationLanguage() -> String
{
let languages : NSArray = UserDefaults.standard.object(forKey: "AppleLanguages") as! NSArray
let selectedLanguage : String = languages[0] as! String
return selectedLanguage.components(separatedBy: "-").first!
}
func setApplicationLanguage(languageCode : String)
{
// Show Alert to restart the application. Present it in your view controller.
UserDefaults.standard.set([languageCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
The user should manually quit the application, for the change to happen.

App always goes back to main after enter background

The App has 2 viewControllers under navigationController, UINavigationController--(root view)-->UIViewController--(present modally)-->UIViewController2.
After entering UIViewController2, press home and let the App enter background, then reactive the App, it's screen goes back to UIViewController. This happens on real device, but not on simulator.
I had suspected that is the lack of memory, but there is few objects in UIViewController2. Any other reason makes the App to do so?
Update:
I found the problem when the iPhone was not connected with XCode!!!
I have just tested the App connecting with Xcode, when I press the home button to enter background, the App crashed!!! It means when I "reactive" the app, it actually restart again, and it do go to UIViewController.
I got the following errors
let localfilePath = NSBundle.mainBundle().URLForResource("home", withExtension: "html");
var webViewRequest:NSURLRequest!
override func viewDidLoad() {
super.viewDidLoad()
webViewRequest = NSURLRequest(URL: localfilePath!);
initSubviews()
}
func initSubviews() {
let fm: CGRect = UIScreen.mainScreen().bounds
self.mainScrollView = UIScrollView(frame:CGRectMake(0, 0, fm.size.width, fm.size.height))
self.mainScrollView!.contentSize = CGSizeMake(self.mainScrollView!.frame.size.width * CGFloat(numPages), self.mainScrollView!.frame.size.height)
self.mainScrollView!.backgroundColor = UIColor.whiteColor()
self.mainScrollView!.pagingEnabled = true
self.mainScrollView!.bounces = false
self.mainScrollView!.showsHorizontalScrollIndicator = false;
self.mainScrollView!.scrollRectToVisible(CGRectMake(mainScrollView!.frame.size.width, 0, mainScrollView!.frame.size.width, mainScrollView!.frame.size.height), animated: false)
self.mainScrollView!.delegate = self
self.view.addSubview(mainScrollView!);
prevWebView = runFunc.setWebView(0)
currWebView = runFunc.setWebView(runFunc.screenWidth)
nextWebView = runFunc.setWebView(runFunc.screenWidth*2)
currWebView.delegate = self
prevWebView.delegate = self
nextWebView.delegate = self
prevWebView.tag = 0
currWebView.tag = 1
nextWebView.tag = 2
prevWebView.backgroundColor = UIColor.whiteColor()
currWebView.backgroundColor = UIColor.whiteColor()
nextWebView.backgroundColor = UIColor.whiteColor()
mainScrollView.addSubview(prevWebView)
mainScrollView.addSubview(currWebView)
mainScrollView.addSubview(nextWebView)
currWebView.scrollView.delegate = self
prevWebView.scrollView.delegate = self
nextWebView.scrollView.delegate = self
prevWebView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal
currWebView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal
nextWebView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal
currWebView.loadRequest(webViewRequest);
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "loadPrevNext", userInfo: nil, repeats: false)
}
func loadPrevNext() {
let prev = getPrev(currVolume, theChapter: currChapter)
prevVolume = prev["volume"]!
prevChapter = prev["chapter"]!
prevChapterArr = runFunc.getLection(prev["volume"]!, theChapter: prev["chapter"]!)
let next = getNext(currVolume, theChapter: currChapter)
nextVolume = next["volume"]!
nextChapter = next["chapter"]!
nextChapterArr = runFunc.getLection(next["volume"]!, theChapter: next["chapter"]!)
prevWebView.loadRequest(webViewRequest);
nextWebView.loadRequest(webViewRequest);
}

Resources