Choose specific url without writing a lot of if statement - ios

I'm working on an horoscope application now I have a problem after user selected is zodiac how can I know what php url to show him for example:
there is 12 zodiac's so how can I give him his horoscope for this url for example
NSURL: "blablabla_horscope.com/libra/today_horoscope"
I mean I don't want to write in Xcode twelve options of url, and start making if statements for example "if this user and then use here is NSUserDefaults with his choosed zodiac"
since then I will have to start making a list of a lot of if statement and it will make my app work slow and it's a bad idea so I have thinking about making some kinda of php file, that will handle all that after the user registered in the background but where to start for that?
I'm currently working on Swift, core-data, php.
let urlString = "http://www.blablabla/?sign=libra&time=today"
let url = NSURL (string: urlString)
let dataURL = try? NSData(contentsOfURL: url!, options: [])
let result: String = String(data: dataURL!, encoding: NSUTF8StringEncoding)!
print("the result is %#", result)

Set your constant for the sign type prior to setting your urlString.
let sign = "libra"
or
let sign = "cancer"
etc...
and then you can:
let urlString = "http://www.blablabla/?sign=\(sign)&time=today"
Late

Related

How to set correct cookies Value against AVURLAssetHTTPCookiesKey while initialising AVURLAsset

I have to play HLS stream and it is secured/protected. In order to download manifest file and further ts file it is expected that request have valid Cookies information sent. I do receive Cookies information from server but it is not part of response header whereas it comes as part response String. It means Cookies automatically does not become part of NSHTTPStorage and application have to consume response string and fetch Cookies information from there; further need to be set while initialising AVURLAsset. As per AVURLAsst documentation in order to send Cookie information we should use options "AVURLAssetHTTPCookiesKey". I have mentioned in below code how to initialise AVURLAsset using this key
let cookieOptions = [AVURLAssetHTTPCookiesKey: Any]
let assets = AVURLAsset(url: url as URL, options: cookieArrayOptions)
My main problem how to set value against AVURLAssetHTTPCookiesKey. It take value of 'Any' type.Since Apple just mention it expect Any value and does not tell how internally it interpret and convert that value in correct format.
I tried two approach to set value: Say I have to set two Cookies key viz MyCookies1, MyCookies2
Approach 1 using NSHTTPStorage
let propertiesKey1 = [HTTPCookiePropertyKey.domain : "Domain=abc.com",HTTPCookiePropertyKey.path:"/",HTTPCookiePropertyKey.secure:true,HTTPCookiePropertyKey.init("HttpOnly"):true,HTTPCookiePropertyKey.value:"abc1",HTTPCookiePropertyKey.name:"MyCookies1"] as [HTTPCookiePropertyKey : Any]
let propertiesKey2 = [HTTPCookiePropertyKey.domain : "Domain=abc.com",HTTPCookiePropertyKey.path:"/",HTTPCookiePropertyKey.secure:true,HTTPCookiePropertyKey.init("HttpOnly"):true,HTTPCookiePropertyKey.value:"abc2",HTTPCookiePropertyKey.name:"MyCookies2"] as [HTTPCookiePropertyKey : Any]
let cookieKey1 = HTTPCookie(properties: propertiesKey1)
let cookieKey2 = HTTPCookie(properties: propertiesKey2)
HTTPCookieStorage.shared.setCookie(cookieKey1!)
HTTPCookieStorage.shared.setCookie(cookieKey2!)
let cookiesArray = HTTPCookieStorage.shared.cookies!
let cookieArrayOptions = [AVURLAssetHTTPCookiesKey: cookiesArray]
guard let url = URL(string:"abc.com") else { return }
let assets = AVURLAsset(url: url as URL, options: cookieArrayOptions)
But this is not working and AVPlayer just initializing and stopped working
Approach 2
let values = ["Cookie": "MyCookies1=abc1; MyCookies2=abc2"]
let cookieArrayOptions = [AVURLAssetHTTPCookiesKey: values]
guard let url = URL(string:"abc.com") else { return }
let assets = AVURLAsset(url: url as URL, options: cookieArrayOptions)
But this options always crashes.May be I am not setting values in correct format.
I have tried to provide as much information as possible but let me know if you need any further information.
After couple of tries I am able to make it working with Approach 1 usign NSHTTPStorage. I made a mistake of not using HTTPS streaming URL. I had already allowed to play non-HTTP url by passsing ATS and allow arbitrary loads. But AVURLAssetHTTPCookiesKey expect to provide only HTTPS url to be set for cookies. I used HTTPS streams and ultimately Cookies started to be sent internally in request header while downloading manifest/segment file in playing HLS stream

iOS swift extracting permalink from deeplink URL

I am implementing Firebase dynamic links in my iOS project. It is working fine and it is opening my iOS Home screen properly. But now I would like to extract values from url and open appropriate screen based on url.
for example:
https://www.dd.com/forums/hot-deals-online/topics/smart-tv-carniva
in this url I would like to get 'hot-deals-online' and 'smart-tv-carniva' permalink which I will pass to view controller to open that screen on the app
can someone suggest me best approach for this.
Shortest is to access path of URLComponents object:
let url = "https://www.dd.com/forums/hot-deals-online/topics/smart-tv-carniva"
if let comps = URLComponents(string: url) {
var elements = comps.path.split(separator: "/").map(String.init)
// ["forums", "hot-deals-online", "topics", "smart-tv-carniva"]
// To build an url back, example:
var url = URL(string: comps.host!)!
url.appendPathComponent(elements[0])
url.appendPathComponent(elements[1])
// Result: www.dd.com/forums/hot-deals-online
}
P.S. calling .map(String.init) makes in-place conversion from array of substrings to normal String array.

Resume downloads when download URL changes

I have an API that generates signed download links that expire after a short amount of time. I'd like to add the ability to resume downloads, but the URLSession APIs don't provide the native ability to resume downloads if the URL for the asset changes.
My attempt at solving this was to track the bytes downloaded at the time of pausing, store the data blob that was downloaded, fetch a new signed download url, resume downloading using Range headers, and then concatenate all the data blobs together when the download is completed.
Here's the code used to start the download:
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: signedURL)
self.sessionDownloadRequest = task
The problem that I am facing is that the resume data var doesn't appear to actually contain the data that was downloaded.
self.sessionDownloadRequest.cancel(byProducingResumeData: { (data) in
print(data.count) //This surprisingly always returns the same count
}
It appears that the size of that data blob is always the same regardless of how long I let the download continue for before pausing. Where/How can I access the chunk of data that was downloaded?
Thanks!
The resume data that is returned by:
- (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler;
is actually a plist that includes:
NSURLSessionDownloadURL
NSURLSessionResumeBytesReceived
NSURLSessionResumeCurrentRequest
NSURLSessionResumeEntityTag
NSURLSessionResumeInfoTempFileName
NSURLSessionResumeInfoVersion
NSURLSessionResumeOriginalRequest
NSURLSessionResumeServerDownloadDate
You can access the plist with the following code:
if let resumeDictionary = try? PropertyListSerialization.propertyList(from: self, options: PropertyListSerialization.MutabilityOptions.mutableContainersAndLeaves, format: nil), let plist = resumeDictionary as? [String: Any] {
print(plist)
}
You don't actually need to store and concatenate the data blobs as you initially suggested. You can replace the current request stored in the plist (NSURLSessionResumeCurrentRequest) with a new one with your updated signed URL. After this, create a new resumeData instance to use instead of the original.
guard let bytesReceived = plist["NSURLSessionResumeBytesReceived"] as? Int
else {
return nil
}
let headers = ["Range":"bytes=\(bytesReceived)"]
let newReq = try! URLRequest(url: signedURL, method: .get, headers: headers)
let archivedData = NSKeyedArchiver.archivedData(withRootObject: newReq)
if let updatedResumeData = try? PropertyListSerialization.data(fromPropertyList: plist, format: PropertyListSerialization.PropertyListFormat.binary, options: 0) {
return updatedResumeData
}
From there you can manipulate the plist and actually create a new one to pass it thru to the instance method:
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
NOTE: If you are working with iOS 10 and macOS10.12.*, there is a bug that prevents the resume ability to work as the plist is corrupted. Check this article out for a fix. You may need to fix the plist before accessing certain properties on it.
Resume NSUrlSession on iOS10

Why can't I convert this String to a URL?

I have x 2 questions about urls and webViews.
Question 1:
I have a string which I am getting from an API that is supposed to be a url. The string is https://godochurch.blob.core.windows.net/sermons/1031/30-1-2017-Vision Sunday-Devotion.mp3
When trying to convert to a url I'm getting nil.
Here is the code:
if let sermonUrl = sermonUrl {
if let url = URL(string: sermonUrl) {
let requestObj = URLRequest(url: url)
webView.loadRequest(requestObj)
}
}
I have worked out that the space between 'Vision' and 'Sunday' is the problem.
Should I be encoding the string in some way before trying to convert it to a URL? What's confusing is that if I paste the string into my browser it works just fine, but I notice the browser is percent encoding the space.
If I am supposed to be encoding the string, how do I do that?
Question 2:
I see that URL(string: "urlStringHere") is only available from iOS 10. My app needs to work for iOS 9. How can I convert the above code so it works on iOS 9 and 10.
Thanks in advance for your time.
1: escape that space with %20 or +:
if let url = URL(string: "https://godochurch.blob.core.windows.net/sermons/1031/30-1-2017-Vision%20Sunday-Devotion.mp3") {
// ...
}
2: URL was introduced with Swift 3, which is compatible with iOS 8 and later. See this question on how to make it work with older versions of iOS.
Edit: the easiest way to percent-escape a URL is to use URLComponents:
var components = URLComponents(string: "https://godochurch.blob.core.windows.net")!
components.path = "/sermons/1031/30-1-2017-Vision Sunday-Devotion.mp3"
if let url = components.url {
// ...
}
If you happen to get you URL strings from a webservice and it contains a space, that service is bad. Space is not allowed in an URL. Web browsers relax that rule because they know there are bad URLs out there. Swift won't take it.

'NSURLRequest?' does not have a member named 'URL' - Swift

Hi I am really new to coding in Swift, and am trying to follow the codes in this book: http://www.apress.com/9781484202098. Learn iOS 8 App Development 2nd Edition by James Bucanek
In particular, I am working through Chapter 3 - building a URL shortening app, but despite having copied the code exactly, I am getting an error on the code in Page 76:
if let toShorten = webView.request.URL.absoluteString {
which states 'NSURLRequest?' does not have a member named 'URL'.
I have tried googling an answer, but unfortunately have not come across anything. Any response I can find seems to suggest that my code ought to be working (e.g. How to get url which I hit on UIWebView?). This seems to have the closest answer SWIFT: Why I can't get the current URL loaded in UIWebView? but the solution does not appear to work for me. If I add a ? after the request, it will then at least build it, but I then have a nil variable returned.
I am using Xcode v6.1.1. Here is the piece of code that is coming up with the error in ViewController.swift:
let GoDaddyAccountKey = "0123456789abcdef0123456789abcdef" //this is replaced by my actual account key in my own code
var shortenURLConnection: NSURLConnection?
var shortURLData: NSMutableData?
#IBAction func shortenURL( AnyObject ) {
if let toShorten = webView.request?.URL.absoluteString { // ? now added
let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) //added if here and removed !
let request = NSURLRequest(URL:firstrequest)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
If you have any suggestions on how I can fix this, I would really appreciate it!
Update:
Following suggestions from Ashley below, I have amended my code so that it is no longer bringing up the error (see comments above). However, it is now no longer running. This appears to be because the urlString is being created as http://api.x.co/Squeeze.svc/text/d558979bb9b84eddb76d8c8dd9740ce3?url=Optional("http://www.apple.com/"). The problem is therefore the Optional() that is included and thus makes it an invalid URL. Does anyone have a suggestion on how to remove this please?
request is an optional property on UIWebView:
var request: NSURLRequest? { get }
also stringByAddingPercentEscapesUsingEncoding returns an optional:
func stringByAddingPercentEscapesUsingEncoding(_ encoding: UInt) -> String?
What you need is to make user of optional binding in a few places:
if let toShorten = webView.request?.URL.absoluteString {
if let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) { // If a method can return a nil, don't force unwrap it
let request = NSURLRequest(URL:first request)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
See Apple's docs on optional chaining for details
See Apple's docs for NSURL class

Resources