I try trigger new version available at app store, then i will redirect user to app store. Then inside there i update the app. After finish download, i click open inside app store then my app will open a splash screen then it will auto close. I not get any crash log. This is my code.
DispatchQueue.global().async {
do {
let update = try self.needsUpdate()
print("update",update)
DispatchQueue.main.async {
if update{
self.popupUpdateDialogue();
}
}
} catch {
print(error)
}
}
func popupUpdateDialogue(){
var versionInfo = ""
do {
versionInfo = try self.getAppStoreVersion()
}catch {
print(error)
}
let alertMessage = "Please update this app to version "+versionInfo;
let alert = UIAlertController(title: "New Version Available", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert)
let okBtn = UIAlertAction(title: "Update", style: .default, handler: {(_ action: UIAlertAction) -> Void in
if let url = URL(string: "itms-apps://itunes.apple.com/sg/app/myApp/idxxxx"),
UIApplication.shared.canOpenURL(url){
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
})
let noBtn = UIAlertAction(title:"Skip this Version" , style: .destructive, handler: {(_ action: UIAlertAction) -> Void in
})
alert.addAction(okBtn)
alert.addAction(noBtn)
self.present(alert, animated: true, completion: nil)
}
func needsUpdate() -> Bool {
let infoDictionary = Bundle.main.infoDictionary
let appID = infoDictionary!["CFBundleIdentifier"] as! String
let url = URL(string: "http://itunes.apple.com/sg/lookup?bundleId=\(appID)")
let data = try? Data(contentsOf: url!)
let lookup = (try? JSONSerialization.jsonObject(with: data! , options: [])) as? [String: Any]
if let resultCount = lookup!["resultCount"] as? Int, resultCount == 1 {
if let results = lookup!["results"] as? [[String:Any]] {
if let appStoreVersion = results[0]["version"] as? String{
let currentVersion = infoDictionary!["CFBundleShortVersionString"] as? String
if !(appStoreVersion == currentVersion) {
print("Need to update [\(appStoreVersion) != \(currentVersion)]")
return true
}
}
}
}
return false
}
I really dont know why the app will auto terminate/close. I also already checked on this link App Crash when after updating, https://stackoverflow.com/questions/17795920/ios-app-goes-crash-on-startup-after-updating-from-the-app-store,https://stackoverflow.com/questions/15409323/ios-app-cannot-be-opened-after-update but still not get what solution for this issue.
Related
How can I get location, time, lng, lat, mag and depth data from this API in Swift?
https://api.hknsoft.com/earthquake/v1/last24hours?limit=500
//API
let url = URL(string: "https://api.hknsoft.com/earthquake/v1/last24hours?limit=500")
let session = URLSession.shared
let task = session.dataTask(with: url!) { data, response, error in
if error != nil {
let alert = UIAlertController(title: "Error!", message: error?.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
} else {
if data != nil {
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String, Any>
DispatchQueue.main.async {
//print(jsonResponse)
if let result = jsonResponse["earthquakes"] as? [String : Any] {
if let location = result["location"] as? String {
print(location)
}
if let time = result["time"] as? String {
print(time)
}
if let mag = result["mag"] as? Double {
print(mag)
}
if let lat = result["lat"] as? Double {
print(lat)
}
if let lng = result["lng"] as? Double {
print(lng)
}
if let depth = result["depth"] as? Double {
print(depth)
}
}
}
} catch {
print("alert")
let alert = UIAlertController(title: "Error!", message: error.localizedDescription, preferredStyle: UIAlertController.Style.alert)
let okButton = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
}
}
}
}
task.resume()
In my application I have pick the image using UIImagePickerController from photos and then compress and convert to base64 string. Finally I upload the base64 string to server. Here the server was not accept the base64 string and does not work, but in Android and Postman it works well. I couldn't find the mistake in my code.
Here I mention the UIImagePickerControllerDelegate:
// MARK: UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
selectedImage = selectedImage.resizeWithWidth(width: 700)!
picker.dismiss(animated: true, completion: nil)
DispatchQueue.main.async {
self.collPhotos.reloadData()
}
}
Here I mention the Base64 Conversion and post the parameter string to server:
func addImagesApiCAll() {
let imagedata1:UIImage = selectedImage as! UIImage
let compressData = UIImagePNGRepresentation(imagedata1)
let base64 = compressData?.base64EncodedString(options: .lineLength64Characters)
print("charCount",base64!.count)
if Reachability()!.isReachable {
let id = Singleton.sharedInstance.selectedCategory!
let parameterStr = "property_id=\(self.PropertyID)&photos=\(base64!)&lang_code=\(lanuguage_selection.value(forKey: "language") ?? "en")&base_id=\(id)&user_id=\(login_session.value(forKey: "UserId")!)"
Network.shared.POSTRequest(withParameterString: parameterStr, serviceURL: SAVE_PHOTO_LISTING, APIKEY: "SAVE_PHOTO_LISTING")
} else {
showInformation(title: "Network Error", message: "Please check your internet connection")
}
}
extension AddPhotoViewController: HTTP_POST_STRING_REQUEST_PROTOCOL {
func httpPostRequest(APIKEY: String, requestURL: String, responseDict: NSDictionary, errorDict: String) {
ListingActivityDelegate.hideActivity()
if APIKEY == "SAVE_PHOTO_LISTING"{
if errorDict.count == 0 {
print(responseDict)
let mod = RentYourSpaceModel(fromDictionary: responseDict as! [String : Any])
if mod.status! != 0 {
Singleton.sharedInstance.rentYourSpace = mod
if Singleton.sharedInstance.rentYourSpace.result[0].step5.productImage.count == 0{
imageFromResponse = "NO"
} else {
imageFromResponse = "YES"
}
}
self.showInformation(title: "Application", message: mod.message)
}
else {
}
}
}
}
Here I mention the code for Select Image from Camera or Gallery:
#IBAction func act_AddPhoto(_ sender: UIButton) {
let actionSheet = UIAlertController(title: "Home Stay", message: "Choose Image", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
self.openCamera()
}))
actionSheet.addAction(UIAlertAction(title: "Photos", style: .default, handler: { _ in
self.openGallary()
}))
actionSheet.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
//If you want work actionsheet on ipad then you have to use popoverPresentationController to present the actionsheet, otherwise app will crash in iPad
switch UIDevice.current.userInterfaceIdiom {
case .pad:
actionSheet.popoverPresentationController?.sourceView = sender
actionSheet.popoverPresentationController?.sourceRect = sender.bounds
actionSheet.popoverPresentationController?.permittedArrowDirections = .up
default:
break
}
self.present(actionSheet, animated: true, completion: nil)
}
//MARK: - Open the camera
func openCamera() {
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)){
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
//If you dont want to edit the photo then you can set allowsEditing to false
imagePicker.allowsEditing = true
imagePicker.delegate = self
self.present(imagePicker, animated: true, completion: nil)
}
else{
let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
//MARK: - Choose image from camera roll
func openGallary(){
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
//If you dont want to edit the photo then you can set allowsEditing to false
imagePicker.allowsEditing = true
imagePicker.delegate = self
self.present(imagePicker, animated: true, completion: nil)
}
Here I give the POSTRequest Method:
//MARK:- Post request with parameter String.
func POSTRequest(withParameterString: String , serviceURL: String , APIKEY: String)
{
var RESPONSE_ERROR = String()
var RESPONSE_DATA = NSDictionary()
let Url = String(format: serviceURL)
guard let serviceUrl = URL(string: Url) else { return }
var request = URLRequest(url: serviceUrl)
let postString = withParameterString
// print(postString)
request.httpBody = postString.data(using: String.Encoding.utf8);
//request.addValue("application/json", forHTTPHeaderField: "content-type")
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request, completionHandler: {
data, response, error in
if let response = response {
print(response)
}
if let resdata = data {
do {
// print(response)
let json = try JSONSerialization.jsonObject(with: resdata, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
//print(json)
if parseJSON.object(forKey: "status") as! NSInteger == 1 {
if error != nil {
RESPONSE_ERROR = (error?.localizedDescription)!
}
DispatchQueue.main.async {
RESPONSE_DATA = parseJSON
self.HTTP_POST_STRING_REQUEST_DELEGATE?.httpPostRequest(APIKEY: APIKEY, requestURL: serviceURL, responseDict: RESPONSE_DATA, errorDict: RESPONSE_ERROR)
}
} else {
DispatchQueue.main.async {
RESPONSE_DATA = parseJSON
self.HTTP_POST_STRING_REQUEST_DELEGATE?.httpPostRequest(APIKEY: APIKEY, requestURL: serviceURL, responseDict: RESPONSE_DATA, errorDict: RESPONSE_ERROR)
}
}
} else {
DispatchQueue.main.async {
RESPONSE_ERROR = "No Data"
self.HTTP_POST_STRING_REQUEST_DELEGATE?.httpPostRequest(APIKEY: APIKEY, requestURL: serviceURL, responseDict: RESPONSE_DATA, errorDict: RESPONSE_ERROR)
}
}
}catch {
DispatchQueue.main.async {
RESPONSE_ERROR = "Check your input datas"
self.HTTP_POST_STRING_REQUEST_DELEGATE?.httpPostRequest(APIKEY: APIKEY, requestURL: serviceURL, responseDict: RESPONSE_DATA, errorDict: RESPONSE_ERROR)
}
}
} else {
DispatchQueue.main.async {
RESPONSE_ERROR = (error?.localizedDescription)!
self.HTTP_POST_STRING_REQUEST_DELEGATE?.httpPostRequest(APIKEY: APIKEY, requestURL: serviceURL, responseDict: RESPONSE_DATA, errorDict: RESPONSE_ERROR)
}
}
})
task.resume()
}
It looks like you are trying to send base64 string as query string. It would be too long to be a query string. You need to share details for POSTRequest method. For more information.
Network.shared.POSTRequest(withParameterString: parameterStr, serviceURL: SAVE_PHOTO_LISTING, APIKEY: "SAVE_PHOTO_LISTING")
And you need to avoid using exclamation (!) in your application. Your code would crash in many points.
For example:
if Reachability()?.isReachable
You can use optional values to prevent crashes.
let parameters = ["property_id":self.PropertyID,
"photos":base64 ?? "",
"lang_code":lanuguage_selection.value(forKey: "language") ?? "en",
"base_id":id,
"user_id":login_session.value(forKey: "UserId") ?? ""];
Network.shared.POSTRequest(parameters: parameters, serviceURL: SAVE_PHOTO_LISTING, APIKEY: "SAVE_PHOTO_LISTING")
in method add json data:
if let jsonData = try? JSONSerialization.data(withJSONObject: parameters) {
request.httpBody?.append(jsonData)
}
Hello i have implemented Share extension for my app in which picks images from gallery and send to a particular view. Now the problem is when i'm trying to save array of images(images picked from gallery)
func manageImages() {
let content = extensionContext!.inputItems[0] as! NSExtensionItem
let contentType = kUTTypeImage as String
for (index, attachment) in (content.attachments as! [NSItemProvider]).enumerated() {
if attachment.hasItemConformingToTypeIdentifier(contentType) {
attachment.loadItem(forTypeIdentifier: contentType, options: nil) { data, error in
if error == nil, let url = data as? URL {
do {
let imageData = try Data(contentsOf: url)
let image = UIImage(data: imageData)
self.selectedImages.append(image!)
if index == (content.attachments?.count)! - 1 {
self.imgCollectionView.reloadData()
UserDefaults.standard.set(self.selectedImages, forKey: "PHOTOKEY")
UserDefaults.standard.synchronize()
}
}
catch let exp {
print("GETTING ERROR \(exp.localizedDescription)")
}
} else {
print("GETTING ERROR")
let alert = UIAlertController(title: "Error", message: "Error loading image", preferredStyle: .alert)
let action = UIAlertAction(title: "Error", style: .cancel) { _ in
self.dismiss(animated: true, completion: nil)
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
}
}
}
and fetching that array in AppDelegate method
func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if let key = url.absoluteString.components(separatedBy: "=").last, let _ = UserDefaults.standard.array(forKey: key) {
let myVC = UIStoryboard.getViewController(storyboardName: "Main",
storyboardId: "MyViewController")
let navVC = UIStoryboard.getViewController(storyboardName: "Main",
storyboardId: "MyNavigationVC") as! UINavigationController
navVC.viewControllers.append(myVC)
self.window?.rootViewController = navVC
self.window?.makeKeyAndVisible()
return true
}
return false
}
I'm sending url let url = URL(string: "unfoldsPrintsShare://dataUrl=PHOTOKEY") and able to get PHOTOKEY
successfully but array getting nil and hence condition is false.
What should i do ?, i googled a lot but didn't find any answer
Also i'm not getting logs when i'm trying to attach extension process via debug.
P.S. : Using Xcode 8.3.3 iOS 10.3, iPhone 6 physical device
Update: Tried Via App Groups Suit Names also
let userDefaults = UserDefaults(suiteName: "group.com.company.appName")
userDefaults?.set(self.selectedImages, forKey: "PHOTOKEY")
userDefaults?.synchronize()
Still No luck
According to #Stefan Church, i tried like this
let imagesData: [Data] = []
saving image Data format into array instead of UIImage
let userDefaults = UserDefaults(suiteName: "group.com.myconmanyName.AppName")
userDefaults?.set(self?.imagesData, forKey: key)
userDefaults?.synchronize()
and it works
Thanks Stefan Church
I am trying to pass a users' email address to another ViewController via a delegate when the user has successfully logged in.
The snippet of code in question (marked *) works fine where it is and the data is passed successfully. However, at this point the user has not successfully logged in, therefore I would rather insert the snippet where the /**** is, a little further down.
However it does work when in that position. Why is that? (I am new to Swift)
Thanks
#IBAction func loginButtonTapped(_ sender: AnyObject)
{
let userEmail = userEmailTextField.text;
let userPassword = userPasswordTextField.text;
if (userPassword!.isEmpty || userEmail!.isEmpty) { return; }
// send user data to server side
let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/userLogin.php");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "email=\(userEmail!)&password=\(userPassword!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
// spinningActivity!.hide(true)
if(error != nil)
{
//Display an alert message
let myAlert = UIAlertController(title: "Alert", message: error!.localizedDescription, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler:nil)
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
*if self.delegate != nil {
self.delegate?.userLoggedIn(data: userEmail! )
}
// retrieve login details and check to see if all ok
if let parseJSON = json {
let returnValue = parseJSON["status"] as? String
if(returnValue != "error")
{
/**** if self.delegate != nil {
self.delegate?.userLoggedIn(data: userEmail! )
} ****/
UserDefaults.set(UserDefaults.standard)(true, forKey: "isUserLoggedIn");
let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")
let mainPageNav = UINavigationController(rootViewController: mainPage!)
let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = mainPageNav
self.dismiss(animated: true, completion: nil)
} else {
// display an alert message
let userMessage = parseJSON["message"] as? String
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler:nil)
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil)
}
}
} catch
{
print(error)
}
}
}
I am trying to return a result from a JSON object but unable to do so. I am new to Swift so kindly explain me how to do so. In the below code I want to return json_level_number in the return of function fetchNumberOfSections () where i have hard coded as 5 right now return 5. If i declare a variable json_level_number just above the reachability code it sort of solves the problem but then it is returning '0' for the first time. The API returns 2 each time.
Code as below:
func fetchNumberOfSections () -> Int {
if Reachability.isConnectedToNetwork() == true {
// Below code to fetch number of sections
var urlAsString = "http://themostplayed.com/rest/fetch_challenge_sections.php"
urlAsString = urlAsString+"?apiKey="+apiKey
print (urlAsString)
let url = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
print(error!.localizedDescription)
}
do {
let jsonResult = (try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
let json_level_number: String! = jsonResult["level_number"] as! String
//
dispatch_async(dispatch_get_main_queue(), {
// self.dateLabel.text = jsonDate
// self.timeLabel.text = jsonTime
print(json_level_number)
// self.activityIndicatorStop()
})
}
catch let errorJSON {
print (errorJSON)
// alert box code below
let alert = UIAlertController(title: "JSON Error!", message:"Error processing JSON.", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { _ in
// Put here any code that you would like to execute when
self.dismissViewControllerAnimated(true, completion: {})
}
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
// alert box code end
}
})
jsonQuery.resume()
// End
}
else {
print("Internet connection FAILED")
self.performSegueWithIdentifier("nointernet", sender: nil)
}
return 5
}