I want this to update every 4 seconds with fresh data form the url, but i dont know how to do this. This is what i have so far and it works fine but without the refresher! The Refresher needs to work like a youtube subscriber counter that update every 4 seconds or so. I have looked at a timer but i couldn't make it work because (i think) its a searchBarSearchButtonClicked function and the urlRequestid has to have a input! Please help! Thanks!
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let urlRequestid = URLRequest(url: URL(string: "https://www.mylink.com/\(searchBar.text!.replacingOccurrences(of: " ", with: "%20"))/?__a=1")!)
if (interstitial.isReady){
interstitial.present(fromRootViewController: self)
interstitial = createAndLoadInterstitial()
}
let task = URLSession.shared.dataTask(with: urlRequestid) { (data, response, error) in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let user = json["user"] as? [String : AnyObject] {
let profile_pic_url_hd = user["profile_pic_url_hd"] as! String
let urlstr = "\(profile_pic_url_hd)"
if var comps = URLComponents(string: urlstr) {
var path = comps.path
var pathComps = path.components(separatedBy: "/")
pathComps.remove(at: 2) // this removes the s320x320
path = pathComps.joined(separator: "/")
comps.path = path
if let newStr = comps.string {
print(newStr)
self.imgURL = "\(newStr)"
}
}
if let bio = user["biography"] as? String {
self.bioS = bio
}
if let naam = user["username"] as? String {
self.naamS = naam
}
if let followed_by = user["followed_by"] as? [String : AnyObject] {
self.VolgS = followed_by["count"] as! Int
}
if let follows = user["follows"] as? [String : AnyObject] {
self.volgD = follows["count"] as! Int
}
if let media = user["media"] as? [String : AnyObject] {
self.postS = media["count"] as! Int
}
}
if let _ = json["error"] {
self.exists = false
}
DispatchQueue.main.async {
if self.exists{
self.imgView.downloadImage(from: self.imgURL!)
self.naam.text = "#\(self.naamS ?? "")"
if self.bioS == nil {
self.bio.text = "This Person has no biography!"
} else {
self.bio.text = "\(self.bioS ?? "")"
}
self.volgers.text = "\(self.VolgS!)"
self.volgend.text = "\(self.volgD!)"
self.post.text = "\(self.postS!)"
} else {
self.exists = true
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
}
task.resume()
}
}
One quick but admittedly clumsy fix would be to store the latest UISearchBar instance from the searchBarSearchButtonClicked parameter in a local instance variable:
var currentSearch: UISearchBar = UISearchBar()
var timer: Timer?
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
currentSearch = searchBar
// Add the rest of the method code below...
...
}
// Call this method to begin repetition
func repeatSearch() {
self.timer = Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true,
block: { (timer) in
self.searchBarSearchButtonClicked(self.currentSearch)
})
}
You can achieve it by using the Timer, schedule it for every 4 seconds.
DEMO
FOR iOS 10.0 and Above
var timer: Timer?
func callMe() {
func doSomrThing(str: String) {
print(str)
}
doSomrThing(str: "first time")
self.timer = Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true, block: { (timer) in
doSomrThing(str: "after 4 second")
})
}
For below iOS 10.0
var timer: Timer?
func callMe() {
self.doSomeThing(str: "first time")
self.timer = Timer.scheduledTimer(timeInterval: 4.0, target: self, selector: #selector(AddTextVC.timerHandler), userInfo: nil, repeats: true)
}
func doSomeThing(str: String) {
print(str)
}
func timerHandler() {
self.doSomeThing(str: "after 4 seconds")
}
Just replace your code according to the demo.
And add this code to your viewController :
deinit {
self.timer?.invalidate()
self.timer = nil
}
Related
I have a JSON API I want my app to download in background.
My Quotes app send out notifications with timeintervals and I want the quotes to be in the notification.
struct Quotetype: Codable {
let text: String?
let author: String?
}
class ViewModel: ObservableObject {
#Published var quotes: [Quotetype]?
#Published var isLoading: Bool = true
var quoteText: String = ""
var quoteAuthor: String = ""
init() {
fetchQuotes()
setUpNotificationPermission()
setUpNotificationTriggers()
}
func fetchQuotes() {
guard let url = URL(string: "https://type.fit/api/quotes") else { return }
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
if error == nil {
if let data = data {
do {
let jsonContent = try JSONDecoder().decode([Quotetype].self, from: data)
DispatchQueue.main.async { [self] in
self?.quotes = jsonContent
if self?.quotes?.count != nil {
let randomNumber = Int.random(in: 0..<self!.quotes!.count )
self?.isLoading = false
self?.quoteText = self!.quotes?[randomNumber].text ?? ""
self?.quoteAuthor = self!.quotes?[randomNumber].author ?? ""
}
}
} catch {
print("\(error)")
}
} else {
print("Data nil")
}
} else {
print("err \(String(describing: error))")
}
}.resume()
}
func setUpNotificationTriggers() {
let content = UNMutableNotificationContent()
content.title = "Quote of the Day"
content.subtitle = quoteText
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
this is my fetch & Notification. How can I get the quoteText in background so notification can go through?
please provide with examples.
I have loaded iframe form into wkwebview and its working fine. When the tap scanner button inside an iframe and it opens the camera to scan the document, after document uploaded to the server it will return to wkweb view but here wkweb view is not refreshed and showing a blank white screen.
Here is my code for wkweb view:
private func loadWebView(){
webView.uiDelegate = self
webView.allowsBackForwardNavigationGestures = true
do {
guard let filePath = Bundle.main.path(forResource: "index", ofType: "html")
else {
// File Error
print ("File reading error")
return
}
let contents = try String(contentsOfFile: filePath, encoding: .utf8)
let baseUrl = URL(fileURLWithPath: "https://url")
DispatchQueue.main.async {
self.webView.loadHTMLString(contents as String, baseURL: baseUrl)
}
}
catch {
print ("File HTML error")
}
webView.configuration.preferences.javaScriptEnabled = true
webView.configuration.userContentController.add(self, name: "jsHandler")
webView.configuration.userContentController.add(self, name: "saveHandler")
webView.configuration.userContentController.add(self, name: "openCamera")
}
func makeSaveForm(ProcessInstanceId: String, FullFormKey: String, TaskIdValue: String, FormValues: String) -> saveFormModel {
let newForm = saveFormModel()
newForm.ProcessInstanceId = ProcessInstanceId
newForm.FullFormKey = FullFormKey
newForm.TaskIdValue = TaskIdValue
newForm.FormValues = FormValues
return newForm
}
func ProcessInstanceIDApiCall(ProcessInstId: String){
let authToken = UserDefaults.standard.string(forKey: "authToken")
print("id for process instance", ProcessInstId)
let bearerToken: String = "Bearer " + (authToken ?? "")
print("baearer token::\(bearerToken)")
let headers:HTTPHeaders = ["Content-Type":"Application/json",
"Authorization": "Bearer " + (authToken ?? ""),
"Accept":"application/json"]
AF.request("https://api url/process-instance/\(ProcessInstId)/variables", method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON { (response:AFDataResponse<Any>) in
print("process instance id api",response.result)
switch response.result {
case .success:
print("instance response", response.value )
guard let data = response.value else {
// print("request failed \(error)")
return
}
self.anyValueJson = response.value
self.jsonStringProcessInstanceID = self.JSONStringify(value: data as AnyObject)
print("raw response: \(String(describing: self.jsonStringProcessInstanceID))")
case .failure(let error):
print("Error:", error)
}
}
}//api call end
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "jsHandler" {
// print(message.body)
} else if message.name == "saveHandler" {
let values = message.body
print(values)
let jsonString = JSONStringify(value: values as AnyObject)
print(jsonString)
formValues = jsonString
let newSaveForm = self.makeSaveForm(ProcessInstanceId: self.processInstanceId ?? "", FullFormKey: self.fullFormKey ?? "", TaskIdValue: self.taskIdValue ?? "", FormValues: jsonString )
//realm create/update saveform based task id
let realm = try! Realm()
if realm.object(ofType: saveFormModel.self, forPrimaryKey: newSaveForm.TaskIdValue) != nil {
try! realm.write {
print("already exist")
//.all is equivalent to true and .error is equivalent to false
realm.add(newSaveForm, update: .all)
}
} else {
try! realm.write {
print("new document written")
realm.add(newSaveForm) //RLMException occurs here
}
}
} else if message.name == "openCamera" {
print("open camera",message.body)
let base64Encoded = message.body
let jsonString = JSONStringify(value: base64Encoded as AnyObject)
do{
if let json = jsonString.data(using: String.Encoding.utf8){
if let jsonData = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String:AnyObject]{
let id = jsonData["scannerData"] as! String
print("scanner data ::", id)
let vc1 = ScannerViewController()
let v = vc1.scanParameters(scannerDataBase64: id)
print("v", v)
let newVC = A8Scan(self)
newVC.showScanner()
}
}
}catch {
print(error.localizedDescription)
}
func loadFormView(){
let setPath = "https://api url/\(formKey ?? "")/index.html";
let js = "setFrame('" + setPath + "')";
print("js::\(js)")
webView.evaluateJavaScript(js) { (r, error) in
if error == nil {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0){
print(r ?? "empty")
let realm = try! Realm()
let object = realm.object(ofType: saveFormModel.self, forPrimaryKey: self.taskIdValue)
print("object", object ?? "")
print("json api string", self.jsonStringProcessInstanceID ?? "")
let authValue = "Bearer \(self.authTokenValue ?? "")"
if object?.FullFormKey != nil {
if let jsonStr = self.jsonStringProcessInstanceID {
let l = "loadform('\(object?.FullFormKey ?? "")', '\(authValue)', '\(object?.ProcessInstanceId ?? "")', \(object?.FormValues ?? ""), \(jsonStr))"
self.webView.evaluateJavaScript(l, completionHandler: nil)
}
} else {
if let jsonStr = self.jsonStringProcessInstanceID {
print("json str::::", jsonStr)
let l = "loadform('\(self.fullFormKey ?? "")', '\( authValue)', '\(self.processInstanceId ?? "")', \(jsonStr))"
self.webView.evaluateJavaScript(l, completionHandler: nil)
}
}
self.tapCallback = {
print("tap called save")
// let s = "submitEvent('\(self.saveArg)')"
let save = "submitEvent('save');"
self.webView.evaluateJavaScript(save, completionHandler: nil)
}
}
} else {
print("web view didfinish loading error",error)
}
}
}
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Web View didFinish Loading");
loadFormView()
}
My issue when I'm returning to wkweb view after from scanner SDK it shows a blank white screen. How to refresh the screen when I return to the web view each time scanner SDK close?
Any help much appreciated, please...
The problem is being caused by AVG AntiVirus's webshield. For some reason AVG webshield treats all network communication from the simulator as fraudulent.
The following screenshot shows the safari app running on simulator. It says that www.apple.com is not safe or any other website.
The following screenshot is from system.log showing errors with webkit.
You can replicate this problem by installing AVG antivirus and turning on the webshield. WKWebview in your App(On the simulator) wouldn't load anything.
taken from here
I have got myself into confusion.I need someone to help me.
I have been trying to use Action sheet picker and everything was good but I need to get the selected item. How can I do it?
ActionSheetMultipleStringPicker.show(withTitle: "Select Country", rows: [
countriesArray,], initialSelection: [0],
doneBlock: {
picker, indexes, values in
print("values = \(values)")
print("indexes = \(indexes)")
print("picker = \(picker)")
DispatchQueue.main.async {
// Update UI
self.performSegue(withIdentifier: "pdfsegue", sender: nil)
}
return
}, cancel:
{
ActionMultipleStringCancelBlock in return
}, origin: sender)
these are my arrays:
var emiratesArray = [String]()
var emiratesIdArray = [Int]()
I am getting values into my arrays from JSON:
let url = NSURL(string: EMIRATES_URL)
URLSession.shared.dataTask(with: (url as?URL)!, completionHandler: {(data,response,error) ->
Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
print(jsonObj.value(forKey: "data")!)
if let messageArray = jsonObj.value(forKey: "data") as? NSArray
{
for message in messageArray
{
if let messageDict = message as? NSDictionary
{
if let data = data {
let successmessage = jsonObj.value(forKey: "success") as? Int
if(successmessage == 1)
{
if let emirate_name = messageDict.value(forKey: "emirate_name")
{
self.emiratesArray.append(emirate_name as! String)
print(emirate_name)
}
if let company_id = messageDict.value(forKey: "id")
{
self.emiratesIdArray.append(company_id as! Int)
print(company_id)
}
} else
{
}
}
}
}
}
}
}).resume()
someone help me How to get the selected item?If i were using tableview then I would have taken the id from the [indexpath.row] but in UIActionsheet picker,I dont know how get the id of selected value. Please someone help me please
I didn't found any Custom Class in your given code. You can create a class like below:
class Emirate: NSObject {
var id: Int
var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
override var description: String {
return self.name
}
}
I have override the description property because ActionSheetMultipleStringPicker shows description of object given in the array if it is not String.
Declare your Emirate array
var emiratesArray = [Emirate]()
Your API request and Parsing should be like this:
let url = NSURL(string: "EMIRATES_URL")
URLSession.shared.dataTask(with: (url as?URL)!, completionHandler: {(data,response,error) ->
Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
{
print(jsonObj.value(forKey: "data")!)
if let messageArray = jsonObj.value(forKey: "data") as? NSArray
{
for message in messageArray
{
if let messageDict = message as? NSDictionary
{
if let data = data {
let successmessage = jsonObj.value(forKey: "success") as? Int
if(successmessage == 1)
{
if let emirate_name = messageDict.value(forKey: "emirate_name") as? String, let company_id = messageDict.value(forKey: "id") as? Int
{
self.emiratesArray.append(Emirate(id: company_id, name: emirate_name))
print(emirate_name)
}
} else
{
}
}
}
}
}
}
}).resume()
Now feed your action sheet self.emiratesArray
ActionSheetMultipleStringPicker.show(withTitle: "Select Country", rows: [
self.emiratesArray], initialSelection: [0],
doneBlock: {
picker, indexes, values in
print("values = \(values)")
print("indexes = \(indexes)")
print("picker = \(picker)")
DispatchQueue.main.async {
// Update UI
self.performSegue(withIdentifier: "pdfsegue", sender: nil)
}
return
}, cancel:
{
ActionMultipleStringCancelBlock in return
}, origin: sender)
You will now get the selected Emirate class objects in values array.
N.B- This code is just to give you an idea about how it can work.
I have this func in a Swift file, and it returns the value of the data in the database and prints it out in the counsel.
I want to use the value in the other View Controller but I can't get this to work, so I hope somebody can help me.
It is the nameUser, statusUser and pointUser I like to use in other View Controller.
import Foundation
import UIKit
var code = "100"
var getStatusUSer = ""
class getJSON: NSObject, URLSessionDataDelegate
{
//properties
var data : NSMutableData = NSMutableData()
func downloadItems()
{
let url = NSMutableURLRequest(url: NSURL(string: "http://www.hholm.dk/time_app/qrcode4.php")! as URL)
url.httpMethod = "POST"
let postString = "username=\(code)"
url.httpBody = postString.data(using: String.Encoding.utf8)
print(url.httpBody = postString.data(using: String.Encoding.utf8))
var session: URLSession!
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url as URLRequest)
task.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
self.data.append(data as Data);
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
if error != nil
{
print("Not Found", error)
}
else
{
print("Ok")
self.parseJSON()
}
}
func parseJSON()
{
var jsonResult: NSArray = NSArray()
do
{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
print("jsonResult.count",jsonResult.count)
}
catch let error as NSError
{
print("jsonResult: ", error)
}
var jsonElement: NSDictionary = NSDictionary()
var contador = 0
for i in (0..<jsonResult.count)
{
jsonElement = jsonResult[i] as! NSDictionary
if let nameUser = jsonElement["name"] as? String,
let pointUser = jsonElement["point"] as? String,
let statusUser = jsonElement["status"] as? String
{
getStatusUSer = statusUser
print("Name: ", nameUser)
print("Status: ", statusUser)
print("Point: ", pointUser)
}
}
}
}
Hi Woof this is what i have in my viewcontroler:
import UIKit
class inputcodeViewController: UIViewController {
#IBOutlet weak var input: UITextField!
#IBAction func but(_ sender: Any) {
downloadItems()
}
func downloadItems(){
let getJson = GetJSON()
//setting the delegate
getJson.delegate = self
//starting download
getJson.downloadItems()
}
}
extension inputcodeViewController: GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String){
//now you can use values in your view controller
}
}
how can i print the values
You can use protocol to return those values:
import Foundation
import UIKit
var code = "100"
var getStatusUSer = ""
//define the protocol
protocol GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String)
}
//I've changed the first char of the class name to uppercase
class GetJSON: NSObject, URLSessionDataDelegate{
//properties
var data : NSMutableData = NSMutableData()
//delegate
var delegate: GetJSONDelegate?
func downloadItems(){
let url = NSMutableURLRequest(url: NSURL(string: "http://www.hholm.dk/time_app/qrcode4.php")! as URL)
url.httpMethod = "POST"
let postString = "username=\(code)"
url.httpBody = postString.data(using: String.Encoding.utf8)
print(url.httpBody = postString.data(using: String.Encoding.utf8))
var session: URLSession!
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url as URLRequest)
task.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
self.data.append(data as Data);
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
if error != nil
{
print("Not Found", error)
}
else
{
print("Ok")
self.parseJSON()
}
}
func parseJSON()
{
var jsonResult: NSArray = NSArray()
do
{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
print("jsonResult.count",jsonResult.count)
}
catch let error as NSError
{
print("jsonResult: ", error)
}
var jsonElement: NSDictionary = NSDictionary()
var contador = 0
for i in (0..<jsonResult.count)
{
jsonElement = jsonResult[i] as! NSDictionary
if let nameUser = jsonElement["name"] as? String,
let pointUser = jsonElement["point"] as? String,
let statusUser = jsonElement["status"] as? String
{
getStatusUSer = statusUser
print("Name: ", nameUser)
print("Status: ", statusUser)
print("Point: ", pointUser)
//here we will return received data to the delegate
self.delegate?.didReceiveValues(name: nameUser, status: statusUser, point: pointUser)
}
}
}
}
Now we need to set your controller as a delegate for that protocol:
//this is an example, you need to add the methods described in your controller where you want to use those values
class YourViewController: UIViewController{
// the method that is called by you to get values
func downloadItems(){
let getJson = GetJSON()
//setting the delegate
getJson.delegate = self
//starting download
getJson.downloadItems()
}
}
//defining protocol methods in the extension of the view controller
extension YourViewController: GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String){
//now you can use values in your view controller
}
}
i am a beginner with swift an Progrmamming i need values from the JSON it looks Like this:
{
"response": {
"version":"0.1",
"termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"astronomy": 1
}
}
, "moon_phase": {
"percentIlluminated":"23",
"ageOfMoon":"5",
"phaseofMoon":"Erstes Viertel",
"hemisphere":"North",
"current_time": {
"hour":"8",
"minute":"28"
},
"sunrise": {
"hour":"6",
"minute":"55"
},
"sunset": {
"hour":"19",
"minute":"50"
},
"moonrise": {
"hour":"9",
"minute":"50"
},
"moonset": {
"hour":"0",
"minute":"06"
}
},
"sun_phase": {
"sunrise": {
"hour":"6",
"minute":"55"
},
"sunset": {
"hour":"19",
"minute":"50"
}
}
}
i will get the hour & minute from sunset and sunrise to a variable!
my code :
var sunriseHour: [String] = []
var sunriseMinute: [String] = []
var sunsetHour: [String] = []
var sunsetMinute: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
let url=URL(string:"http://api.wunderground.com/api/dbd539bd631e/astronomy/lang:DL/q/DL/iphofen.json")
do {
let allData = try Data(contentsOf: url!)
let data = try JSONSerialization.jsonObject(with: allData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = data["moon_phase"] {
if let sunriseData = arrJSON["sunrise"]{
print(sunriseData)
}
if let sunsetData = arrJSON["sunset"]{
print(sunsetData)
}
}
print("hour: ",sunriseHour)
print("minute: ",sunriseMinute)
print("hour: ",sunsetHour)
print("minute: ",sunsetMinute)
}
catch {
}
}
i get with print(sunriseData) and print(sunsetData) the right data from this :
Optional({
hour = 6;
minute = 55; }) Optional({
hour = 19;
minute = 50; }) hour: [] minute: [] hour: [] minute: []
How do i get it in the variable sunriseHour, sunriseMinute, sunsetHour, sunsetMinute..
thanks from your help..!
All hour and minute values are (single) String not [String] (array).
Declare all variables as empty strings
var sunriseHour = ""
var sunriseMinute = ""
var sunsetHour = ""
var sunsetMinute = ""
Then do not load data synchronously from a remote URL, use always an asynchronous way:
let url = URL(string:"http://api.wunderground.com/api/dbd539bd631e/astronomy/lang:DL/q/DL/iphofen.json")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
} else {
do {
guard let jsonData = try JSONSerialization.jsonObject(with:data!) as? [String:Any],
let moonPhase = jsonData["moon_phase"] as? [String:Any] else { return }
let sunrise = moonPhase["sunrise"] as! [String:String]
let sunset = moonPhase["sunset"] as! [String:String]
sunriseHour = sunrise["hour"]!
sunriseMinute = sunrise["minute"]!
sunsetHour = sunset["hour"]!
sunsetMinute = sunset["minute"]!
print("Sunrise - \(sunriseHour):\(sunriseMinute)"
print("Sunset - \(sunsetHour):\(sunsetMinute)"
} catch {
print(error)
}
}
}
task.resume()
The data for sunrise and sunset are in dictionaries derived from moon_phase. All values are forced unwrapped because sunrise and sunset are supposed to exist every day ;-)
PS : Consider to define more descriptive variable names, arrJSON is not very meaningful.