Passing a tabelview indexPath.row as String to VC WebView - objective-c

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.

Related

using active campaign api with swift and Alamofire

Im fairly new to iOS development and I'm working on a project that requires integration with Active Campaign.
I simply want to make a post request using their API to add a contact to the database when a button is pressed.
I've first attempted a get request for the current contacts using Alamofire to make sure I can get to it and I can't seem to get the desired output. I've searched and googled quite a bit to find a solution. I've found a few different ways to do it online but nothing has seemed to work.
When I run my current code to add a contact I get this error:
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
Below is my code to add a contact. I will say this is after trying many different solutions I've come across and I may have confused myself. Any help is much appreciated!!
import UIKit
import Alamofire
import SwiftyJSON
class emailEntry: UIViewController {
#IBOutlet weak var f_name: UITextField!
#IBOutlet weak var l_name: UITextField!
#IBOutlet weak var email: UITextField!
#IBOutlet weak var center_frame: UIView!
var api_key = "MY_KEY_IS_HERE"
let urlBase = "BASE_URL_HERE"
#IBAction func submit_but(_ sender: UIButton) {
let url = "\(urlBase)/admin/api.php?api_action=contact_add"
guard let authHeader = Request.authorizationHeader(user: "AnyString", password: api_key) else{
print("Nothing")
return
}
let parameters:Parameters = ["first_name":f_name,
"last_name":"l_name",
"email":"email"
]
let headers:HTTPHeaders = [authHeader.key: authHeader.value]
Alamofire.request(url, method: .post , parameters: parameters, headers: headers).validate().responseJSON { response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
}
}
That error indicates the response you got back was not JSON. Most likely it was some sort of HTML error page. Check the API docs and make sure you're properly formatting your request. Also, you can use responseString to see the content of the response in plain text.

Searching PDF using PDFKIT in Swift

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)

Core Data - Get managed object by URI

I'm trying to fetch managed objects from Core Data by their URI. For this I found an Objective-C example of a method (http://www.cocoawithlove.com/2008/08/safely-fetching-nsmanagedobject-by-uri.html) and converted it to Swift ...
func getManagedObjectWithURI(uri:NSURL) -> NSManagedObject?
{
if let psc = persistentStoreCoordinator
{
let objID = psc.managedObjectIDForURIRepresentation(uri);
if (objID != nil)
{
let obj:NSManagedObject = managedObjectContext!.objectWithID(objID!);
if (!obj.fault)
{
return obj;
}
let prd = NSComparisonPredicate(leftExpression: .expressionForEvaluatedObject(), rightExpression: NSExpression(forConstantValue: obj), modifier: .DirectPredicateModifier, type: .EqualToPredicateOperatorType, options: .allZeros);
let req = NSFetchRequest();
req.entity = objID?.entity;
req.predicate = prd;
var results:[NSManagedObject] = managedObjectContext!.executeFetchRequest(req, error: nil) as! [NSManagedObject];
if (!results.isEmpty)
{
return results.first;
}
}
}
return nil;
}
However the method always returns nil, i.e. the fetch request returns empty-handed and I don't know why. Up to the NSFetchRequest everything looks valid. Does anyone has an idea what could be wrong?
Check that the entity and the predicate contain the expected values.
Another suggestion is to write your predicate with NSPredicate(format:) for clarity.
request.predicate = NSPredicate(format: "self = %#", object)
I have changed your variable names for readability.
Solved the issue. It was actually related to another, deeper problem in my core data code explained here: Mac OSX - Core data isn't stored
The above method works fine otherwise.

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.

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")!)