I am new to IOS development. And I am working to get page load time of web on IOS emulators.
Since, I am targeting top 100 alexa websites, it would be difficult to load each url and record time for load. So, I am planning to automate it.
Below is my code:
import UIKit
class ViewController: UIViewController, UIWebViewDelegate{
var startTime = Date()
#IBOutlet weak var WebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// let URL = Foundation.URL(string: "http://www.youtube.com")
startTime = Date()
print(startTime)
for url in returnURLArray(){
WebView.delegate = self
WebView.loadRequest(URLRequest(url: URL(string: url)!))
print("I am trying to load...."+url)
sleep(100)
print("back to execute other urls")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func webViewDidFinishLoad(_ WebView: UIWebView)
{
//Check here if still webview is loding the content
if (WebView.isLoading){
print("I am loading now...")
return;
}
//after code when webview finishes
let finishTime = Date()
print(finishTime.timeIntervalSince(startTime))
NSLog("Webview loding finished")
}
func returnURLArray() -> [String] {
let file = "topalexawebsites.txt" //this is the file. we will write to and read from it
var text2 = String()
var urlArr = [String]()
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let path = dir.appendingPathComponent(file)
do{
print(path)
text2 = try String(contentsOf: path, encoding: String.Encoding.utf8).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
urlArr = text2.components(separatedBy: "\n")
// print(text2)
// for urls in urlArr{
// print(urls)
//}
}
catch let err as NSError{
print(err)
}
}
return urlArr
}
}
I want to execute all urls one by one in my topalexawebsites.txt and record load time for it.
But, here I am seeing only one cycle is working, and since urls are in a loop, only the also one gets loaded.
Related
I use Alamofire to download the iTunes search Api's trial music.
And when I download finished, I want to play the music.
I try to fix it, but it also no sounds to play.
How to solve this problem?
Thanks.
import UIKit
import AVFoundation
import Alamofire
import CryptoSwift
class FirstViewController: UIViewController {
let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"
override func viewDidLoad() {
super.viewDidLoad()
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileName = self.urlString.md5()
let fileURL = documentsURL.appendingPathComponent("\(fileName).m4a")
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(urlString, to: destination).response { response in
if response.error == nil {
var audioPlayer: AVAudioPlayer!
do {
audioPlayer = try AVAudioPlayer(contentsOf: response.destinationURL!)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print("Error:", error.localizedDescription)
}
}
}
}
}
The problem is caused by the fact that audioPlayer is a local variable, therefore it gets deallocated when you leave the scope of completion closure. Because audioPlayer isn't retained anywhere else, the moment you leave the closure's scope, audioPlayer reference count is equal to 0, which causes ARC to deallocate it.
Also, you use force unwrapping operator - ! - a lot, which is:
1) incorrect
2) unsafe
Use either if let construct or guard statement
What you need to to is store the player as instance variable of your FirstViewController class.
class FirstViewController: UIViewController {
let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"
var audioPlayer : AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// (...)
Alamofire.download(urlString, to: destination).response { [weak self] (response) in
if response.error == nil {
guard let url = response.destinationURL else { return }
do {
self?.audioPlayer = try AVAudioPlayer(contentsOf: url)
self?.audioPlayer?.prepareToPlay()
self?.audioPlayer?.play()
} catch {
print("Error:", error.localizedDescription)
}
}
}
}
}
Just move audioPlayer to controller
class FirstViewController: UIViewController {
let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"
var audioPlayer: AVAudioPlayer?
//Downloading code......
}
Trying to create a simple example code block in Swift 2.0 on iOS 9.1 using Xcode 7.1. Tried this article in techotopia; which I suspect is based on swift 1.2.
Made a few tiny changes so that it would compile & run, but although it appears to work, it doesn't seem to save my string into the file. Is there capability or something subtle I have missed here.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textBox: UITextField!
var fileMgr: NSFileManager = NSFileManager.defaultManager()
var docsDir: String?
var dataFile: String?
var string: String = ""
override func viewDidLoad() {
super.viewDidLoad()
let dirPaths = NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true)
docsDir = dirPaths[0] as String
let dataFile = NSURL(fileURLWithPath: docsDir!).URLByAppendingPathComponent("datafile.dat")
string = "\(dataFile)"
print(string)
if fileMgr.fileExistsAtPath(string) {
let databuffer = fileMgr.contentsAtPath(string)
let datastring = NSString(data: databuffer!,
encoding: NSUTF8StringEncoding)
textBox.text = datastring as? String
}
}
#IBAction func saveText(sender: AnyObject) {
let databuffer = (textBox.text)
let data = databuffer?.dataUsingEncoding(NSUTF8StringEncoding)
fileMgr.createFileAtPath(string, contents: data,
attributes: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
More testing; noticed I get this error when I try and create the file... error in __connection_block_invoke_2: Connection interrupted; which explains why it isn't working, if only I could workout what it is talking about?
Continued to try to debug; added UIFileSharingEnabled but cannot see Documents directory; added more code to test its presence, and create it if missing; fails telling me it is already there... even if it is evidently invisible...
When you do this, string ends up being a string representation of the file URL, e.g. file://.... That file:// prefix is a URL "scheme" (like http:// or ftp://). But including the scheme at the start of the string means that this is not a valid path. You have to remove the scheme.
The easiest way to do this is to use the path method to get the path from a NSURL without that scheme. I'd also use URLForDirectory to get the URL for the documents folder nowadays.
class ViewController: UIViewController {
#IBOutlet weak var textBox: UITextField!
lazy var fileMgr = NSFileManager.defaultManager()
var path: String!
override func viewDidLoad() {
super.viewDidLoad()
let documents = try! fileMgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
path = documents.URLByAppendingPathComponent("datafile.dat").path
if fileMgr.fileExistsAtPath(path) {
if let data = fileMgr.contentsAtPath(path) {
textBox.text = String(data: data, encoding: NSUTF8StringEncoding)
}
}
}
#IBAction func saveText(sender: AnyObject) {
let data = textBox.text?.dataUsingEncoding(NSUTF8StringEncoding)
fileMgr.createFileAtPath(path, contents: data, attributes: nil)
}
}
Or I might stay entirely in the world of URLs, retiring paths altogether, also using methods that throw meaningful error messages:
class ViewController: UIViewController {
#IBOutlet weak var textBox: UITextField!
lazy var fileMgr = NSFileManager.defaultManager()
var fileURL: NSURL!
override func viewDidLoad() {
super.viewDidLoad()
do {
let documents = try fileMgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
fileURL = documents.URLByAppendingPathComponent("datafile.dat")
var reachableError: NSError?
if fileURL.checkResourceIsReachableAndReturnError(&reachableError) {
textBox.text = try String(contentsOfURL: fileURL)
}
} catch {
print(error)
}
}
#IBAction func saveText(sender: AnyObject) {
do {
try textBox.text?.writeToURL(fileURL, atomically: true, encoding: NSUTF8StringEncoding)
} catch {
print(error)
}
}
}
Copied and Pasted this code principally. Compiles and runs, but plays nothing. Using Xcode 7.1 and IOS 9.1. What have I missed... Loaded sound file into main program and AVAssets...
import UIKit
import AVFoundation
class ViewController: UIViewController {
var buttonBeep : AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
buttonBeep = setupAudioPlayerWithFile("hotel_transylvania2", type:"mp3")
//buttonBeep?.volume = 0.9
buttonBeep?.play()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? {
//1
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
//2
var audioPlayer:AVAudioPlayer?
// 3
do {
try audioPlayer? = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
}
You've got this line backwards:
try audioPlayer? = AVAudioPlayer(contentsOfURL: url)
It should be:
audioPlayer = try AVAudioPlayer(contentsOfURL: url)
Side note: the conversion to and from NSString is not necessary here, just use String - and you should not force unwrap the result of NSBundle:
func setupAudioPlayerWithFile(file:String, type:String) -> AVAudioPlayer? {
//1
guard let path = NSBundle.mainBundle().pathForResource(file, ofType: type) else {
return nil
}
let url = NSURL.fileURLWithPath(path)
//2
var audioPlayer:AVAudioPlayer?
// 3
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
This question already has answers here:
How to open file and append a string in it, swift
(5 answers)
Closed 7 years ago.
I'm working on application where I need to append a new line when i touch the button on iPhone.
I did this all but every time it writes over what i have written.
How to append a new line each time I press the button save.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myAge: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// get the documents folder url
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func writeNow(sender: UIButton) {
let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let fileDestinationUrl = documentDirectoryURL.URLByAppendingPathComponent("fileForIphoneAbdulla.txt")
var text = myAge.text
do {
try text!.writeToURL(fileDestinationUrl, atomically: true, encoding: NSUTF8StringEncoding)
print("file is saved succefully")
do {
let mytext = try String(contentsOfURL: fileDestinationUrl, encoding: NSUTF8StringEncoding)
print(mytext) // "some text\n"
} catch let error as NSError {
print("error loading from url \(fileDestinationUrl)")
print(error.localizedDescription)
}
} catch let error as NSError {
print("error writing to url \(fileDestinationUrl)")
print(error.localizedDescription)
}
}
}
The high level file methods are made to write the entire file.
To append you can use an NSFileHandle. It has methods like seekToEndOfFile to move the file pointer to the end and then writeData to add data to the end of the file.
BTW, your sample code is in Swift but you're using the jquery tag. I assume you're looking for help in Swift?
I am following a tutorial about getting images from the web and storing them on the phone in Swift. For my purpose, I would like to know how I could only store them for one 'session', which means until the user stops using the app. The reason is that I want to change the image of the url every day.
Anyone any idea?
#IBOutlet var overLay: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
// self.overLay.image = image
var documentsDirectory:String?
var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
if paths.count > 0 {
documentsDirectory = paths[0] as? String
var savePath = documentsDirectory! + "/overLay.jpg"
NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)
self.overLay.image = UIImage(named: savePath)
}
}
})
}
thank you so much!
Since you're only interested in keeping the image for the lifecycle of the app, it's perfectly viable to just hold a pointer to a UIImage object in memory, likely via some long-living object (AppDelegate would be a possible choice here).
Since you already have a UIImage from the data coming down the pipe, I'd simplify your code as such, or if you want to use some Singleton like the AppDelegate to manage the image state, see what happens when iWantToUseAppDelegate is set to true
#IBOutlet var overLay: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let iWantToUseAppDelegate = false // for demonstration purposes
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
if iWantToUseAppDelegate {
let appDelegate = UIApplication.sharedApplication().delegate as! YourAppDelegateClass // YourAppDelegateClass has some property called "cachedImage"
appDelegate.cachedImage = image
self.overLay.image = appDelegate.cachedImage
} else {
self.overLay.image = image
}
}
})
}
You may need to tweak a few things but this code might work a little easier.
Used what mindfreek add to correct the code.
#IBOutlet var overLay: UIImageView!
var defaults: NSUserDefaults = NSUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
NSUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(image!), forKey: "image")
if let imagedSaved: AnyObject = defaults.valueForKey("image")
{ overLay.image = image }
else { NSKeyedUnarchiver.unarchiveObjectWithData(NSUserDefaults().dataForKey("image")!) as UIImage }
}
})