Searching PDF using PDFKIT in Swift - objective-c

I am extremely new to swift so bear with me. I am trying to figure out how to search the PDF document for a particular string. I am assuming I need to use the findString function. I just do not know exactly how the parameters should be implemented. I am using Apple Docs. and couldn't see a description of this.
Thanks!=]
private func loadPDF(){
guard
let url = Bundle.main.url(forResource: pdfTitle, withExtension: "pdf"),
let document = PDFDocument(url:url)
else {fatalError()}
pdfView.document = document
}
func findString(_ string: String,
withOptions options: NSString.CompareOptions = []) -> [PDFSelection]

To get a list of matches you do something like this:
let matches = document.findString("foo", withOptions: .caseInsensitive)

Related

Passing a tabelview indexPath.row as String to VC WebView

I have a TableViewController which I am attempting to pass through a URL to a WebView on another ViewController
I am overriding the below function, which works find if I make the URL static as you can see in the comment out let newsLink constant
let newsLink = "http://www.stuff.co.nz/business/industries/69108799/Kirkcaldie-Stains-department-store-to-become-David-Jones"
However with the below pulling the URL from indexPath.row it fails for some reason and passes through a nil value
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let newsLink = (posts.objectAtIndex(indexPath.row).valueForKey("link") as! String)
//let newsLink = "http://www.stuff.co.nz/business/industries/69108799/Kirkcaldie-Stains-department-store-to-become-David-Jones"
println(newsLink)
let newsWebViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("idNewsWebViewController") as! NewsWebViewController
newsWebViewController.newsURL = NSURL(string: newsLink)
showDetailViewController(newsWebViewController, sender: self)
}
If I println() the below, I get exactly the same output as the URL I ahve hardcoded in the test let newsLink constant
println(posts.objectAtIndex(indexPath.row).valueForKey("link") as! String)
I can't figure out why this is failing. Hopefully someone smarter than me can help.
The code on the receiving end VC is below"
var newsURL : NSURL!
//var newsURL = NSURL(string: "http://www.google.co.nz")
#IBOutlet weak var newsWebView: UIWebView!
#IBOutlet weak var descTextView: UITextView!
and in the viewDidAppear function
let request : NSURLRequest = NSURLRequest(URL: newsURL!)
newsWebView.loadRequest(request)
More Info
var types
var posts = NSMutableArray()
var elements = NSMutableDictionary()
how I am adding objects
elements.setObject(urlLink, forKey: "link")
posts.addObject(elements)
Could you show the declaration / structure of the "posts" variable?
Without more information, the only thing I can think of is that the value of "link" is not actually a String, but something (maybe a NSURL) that when printed shows that content. That would explain the println showing the same url but the cast failing.
When you print, or implicitly convert any object to a String (as in the println), it calls the "description" method of that object.
For example:
class MyURLContainer {
var link:String
override func description() -> String {
return link
}
}
let url = MyURLContainer()
let url.link = "http://www.example.com"
println( "my link: \(url)" ) // this would show the link correctly
let link = url as? String // this will be nil, as url can't be casted to String
I think (posts.objectAtIndex(indexPath.row).valueForKey("link") does not return a String type. It might already be a NSURL, and hence showing you correct value in println()
Could you post some more details about it. Hope this helped.
It turns out it was the encoding on the URL that NSURL didn't like.
The solution was to use the below:
var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
I'm new to swift, but this seems a bit messy.

Multiple encoding types for Alamofire Request

I need to make a POST request with an HTTP Body with a JSON object, but I also need to use url query parameters in the same request.
POST: http://www.example.com/api/create?param1=value&param2=value
HTTP Body: { foo : [ bar, foo], bar: foo}
Is this supported by Alamofire? How would I go about doing this?
This is definitely a valid use case. I've ran into similar issues with trying to append access tokens as query parameters to a POST request. Here's a function that should make things a bit easier for the time being that is similar to your approach.
func multiEncodedURLRequest(
method: Alamofire.Method,
URLString: URLStringConvertible,
URLParameters: [String: AnyObject],
bodyParameters: [String: AnyObject]) -> NSURLRequest
{
let tempURLRequest = NSURLRequest(URL: NSURL(string: URLString.URLString)!)
let URLRequest = ParameterEncoding.URL.encode(tempURLRequest, parameters: URLParameters)
let bodyRequest = ParameterEncoding.JSON.encode(tempURLRequest, parameters: bodyParameters)
let compositeRequest = URLRequest.0.mutableCopy() as NSMutableURLRequest
compositeRequest.HTTPMethod = method.rawValue
compositeRequest.HTTPBody = bodyRequest.0.HTTPBody
return compositeRequest
}
With that said, could you make sure to put in a feature request issue on the Github? This is certainly something we need to figure out how to make easier in Alamofire since it's such a common use case. If you could put in a really good description of your use case, then I'm sure it will get attention. I will certainly help press to get support added.
At this point, I've decided to solve this by manually encoding an NSURLRequest with the URL parameters, retrieving the URL from that request, and using that to create the final request. I've created a function to return the query parameter encoded request:
private func queryParameterEncodedRequestURL(urlString: String,
values: [String]) -> NSURL {
let URL = NSURL(string: urlString)
var request = NSURLRequest(URL: URL)
let parameters = [
"param1": values[0]!,
"param2": values[1]!
]
let encoding = Alamofire.ParameterEncoding.URL
(request, _) = encoding.encode(request, parameters: parameters)
return (request.URL, nil)
}
This works fine, but I would definitely like to see Alamofire support multiple encoding types more easily. This feels like a workaround to me.

CFURLCopyResourcePropertyForKey failed because passed URL no scheme

I have a program that saves a file to the iCloud and this has worked great for iOS7, but now I get this error with iOS8 and cannot seem to find the answer on how to fix it. Anyone else had this problem? Any ideas would be greatly appreciated.
The Error:
CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme: /var/mobile/Containers/Data/Application/ASFHDDE3-B1BB-41D7-A47C-DCC328362W21/Documents/mypictostore.png
The Line of Code Throws Error:
[fileManager setUbiquitous:YES itemAtURL:backupUrl destinationURL:[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError];
URLS:
destinationURL: file:///private/var/mobile/Library/Mobile%20Documents/ABC23455~MY-Program/
backupUrl: /var/mobile/Containers/Data/Application/ASDFGEEW-B1BB—6FR6-A47C-DCCF21876D36/Documents/mypic.png
Thank you,
Jon
For me this problem was fixed by adding
file://
right before the file path address like this:
var filePath = "file://\(fileURLpath)"
Or maybe you can use NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mypictostore", ofType: "png")!) instead of using NSURL(string: NSBundle.mainBundle().pathForResource("mypictostore", ofType: "png")!)
Look this link for Objective-c answer: CFURLSetResourcePropertyForKey failed when disable data backup on NSDocumentDirectory
Older Swift version answer:
var str:String = "/var/mobile/Containers/Data/Application/3039975A-5E05-4A4C-8000-55C681A7C35F/Documents/index.html"
var url:URL = URL.init(fileURLWithPath: str)
Swift 4 Answer:
var str:String = "/var/mobile/Containers/Data/Application/3039975A-5E05-4A4C-8000-55C681A7C35F/Documents/index.html"
var url:URL = URL(string: str)!
Depending on what you need to do with the path, you may need to prepend the scheme file://. See more at documentation/foundation/url
If you need the file path, use fileURLWithPath:
let imageURL = URL(fileURLWithPath: imagePath)
it will give you the path as
file:///var/mobile/Containers/Data/Application/7C1D854B-8A2E-4FF0-BD30-0652AEE10B6F/Documents/image_8ZMAM.jpg
If you need the path without the scheme, use string:
let imageURL = URL(string: imagePath)
it will give you the path as
/var/mobile/Containers/Data/Application/7C1D854B-8A2E-4FF0-BD30-0652AEE10B6F/Documents/image_8ZMAM.jpg
look, I find this,The url is The location to write the data into. we should tell the system a file path.
var filePath = "file://(fileURLpath)"
var url:URL = URL.init(fileURLWithPath: fileURLpath)
Data
You can also try this, I think the following code is great as if you are not sure any particular url is correct or not for the CFURLCopyResourcePropertyForKey
if testURL.isFileURL == false {
testURL = URL(fileURLWithPath: testURL.absoluteString)
}
var url = USL(fileUrlWithString: "/private/var/...")

NSUserDefaults Not Saving TextField Text (Swift)

I'm trying to create a game with Swift, and I want to add the ability to create a username, which will be saved in NSUserDefaults. This is my code:
println("Textfield Text: \(usernameTextfield.text)")
NSUserDefaults.standardUserDefaults().setObject(usernameTextfield.text, forKey:"Username")
NSUserDefaults.standardUserDefaults().synchronize()
println(NSUserDefaults.standardUserDefaults().objectForKey("Username") as? String)
The output is:
Textfield Text: MyUsername
nil
The only explanation I can see as to why it is printing nil is that either the saving or the loading of the username is failing. Is there any way this can be corrected or am I doing something wrong?
Any help is appreciated!
println("Textfield Text: \(usernameTextfield.text)")
var myValue:NSString = usernameTextfield.text
NSUserDefaults.standardUserDefaults().setObject(myValue, forKey:"Username")
NSUserDefaults.standardUserDefaults().synchronize()
var myOutput: AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("Username")
println(myOutput)
In Swift 4.1
UserDefaults.standard.set(textfield.text, forKey: "yourKey") // saves text field text
UserDefaults.standard.synchronize()
// To Retrieve
textfield.text = UserDefaults.standard.value(forKey:"yourKey") as? String
I made a small modification to Roman's answer with Swift 2.0 and Xcode 6.4.
saving:
var myValue:NSString = usernameTF.text
NSUserDefaults.standardUserDefaults().setObject(myValue, forKey:"Username")
NSUserDefaults.standardUserDefaults().synchronize()
retrieving:
var myOutput = NSUserDefaults.standardUserDefaults().objectForKey("Username")
if (myOutput != nil)
{
self.title = "Welcome "+((myOutput) as! String)
}
In Swift 3.0
let userDefult = UserDefaults.standard //returns shared defaults object.
if let userName = usernameTextfield.text {
//storing string in UserDefaults
userDefult.set(userName, forKey: "userName") //Sets the value of the specified default key in the standard application domain.
}
print(userDefult.string(forKey: "userName")!)//Returns the string associated with the specified key.
For swift 3.0, You can create user default by,
UserDefaults.standard.set("yourValue", forKey: "YourString")
To Print the value in console :
print(UserDefaults.standard.string(forKey: "YourString")!)

NSPredicateEditorRowTemplate, specifying of Key Path with spaces?

As per a previous question, I have reluctantly given up on using IB/Xcode4 to edit an NSPredicateEditor and done it purely in code.
In the GUI way of editing the fields, key paths can be specified with spaces, like 'field name', and it makes them work as 'fieldName'-style key paths, while still displaying them in the UI with spaces. How do I do this in code? When I specify them with spaces, they don't work. When I specify them in camelCase, they work but display in camelCase. I'm just adding a bunch of NSExpressions like this:
[NSExpression expressionForKeyPath:#"original filename"]
The proper way to get human readable strings in the predicate editor's row views is to use the localization capabilities of NSRuleEditor and NSPredicateEditor.
If you follow the instructions in this blog post, you'll have everything you need to localize the editor.
As an example, let's say your key path is fileName, you support 2 operators (is and contains), and you want the user to enter a string. You'll end up with a strings file that looks like this:
"%[fileName]# %[is]# %#" = "%1$[fileName]# %2$[is]# %3$#";
"%[fileName]# %[contains]# %#" = "%1$[fileName]# %2$[contains]# %3$#";
You can use this file to put in human-readable stuff, and even reorder things:
"%[fileName]# %[is]# %#" = "%1$[original filename]# %2$[is]# %3$#";
"%[fileName]# %[contains]# %#" = "%3$# %2$[is contained in]# %1$[original filename]#";
Once you've localized the strings file, you hand that file back to the predicate editor, and it'll pull out the translated values, do its magic, and everything will show up correctly.
If you don't want to localize everything, just map the key paths consider overriding value(forKey:) in your evaluated object like this:
class Match: NSObject {
var date: Date?
var fileName: String?
override func value(forKey key: String) -> Any? {
// Alternatively use static dictionary for mapping key paths
super.value(forKey: camelCasedKeyPath(forKey: key))
}
private func camelCasedKeyPath(forKey key: String) -> String {
key.components(separatedBy: .whitespaces)
.enumerated()
.map { $0.offset > 0 ? $0.element.capitalized : $0.element.lowercased() }
.joined()
}
}