Code:
AppDelegate.swift
func application(application:UIApplication!,
handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!,
reply: (([NSObject : AnyObject]!) -> Void)!)
{
let entityDescription =
NSEntityDescription.entityForName("Quote",
inManagedObjectContext: managedObjectContext!)
let request = NSFetchRequest()
request.entity = entityDescription
let pred = NSPredicate(format: "(quoteDate = %#)", "2015-03-08")
request.predicate = pred
var error: NSError?
var objects = managedObjectContext?.executeFetchRequest(request,
error: &error)
if let results = objects {
if results.count > 0 {
arrQuotes = NSMutableArray()
for(var i=0;i<results.count;i++){
let match = results[i] as! NSManagedObject
var quote = match.valueForKey("quote") as! NSString
arrQuotes.addObject(quote)
}
var dict = ["test": arrQuotes]
reply(dict)
} else {
}
}
catecontroller.swift
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
arrQuotes = NSMutableArray()
var dict = ["test" : arrQuotes]
if !WKInterfaceController.openParentApplication(dict, reply: { (reply,error) -> Void in
println("\(reply)") //your reply data as Dictionary
self.arrQuotes = dict["test"]!
println("\(self.arrQuotes.count)")
}) {
println("ERROR")
}
I am doing a sample watchkit project.What i am trying to do is fetch data from iPhone side and send it to watchkit app.I try to return the value as array of dictionary.but in watchkit side i am getting array count as zero.I do not know where i went wrong?any help will be appreciated.thanks in advance
I would guess that you have some trouble in your iOS app function. I think your reply closure is most likely not being called. I would try to simplify your logic first to make sure the reply is actually coming back correctly. Then you can work on passing the data correctly. I would simply the logic to the following first:
catecontroller.swift
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
WKInterfaceController.openParentApplication(["dummy": "dictionary"]) { reply, error in
println("Reply: \(reply)")
println("Error: \(error)")
}
}
AppDelegate.swift
func application(
application: UIApplication!,
handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!,
reply: (([NSObject : AnyObject]!) -> Void)!)
{
// Worry about this logic later...
reply(["test": "value"])
}
Once you have this simplified version passing the data correctly with no errors, then you can add the data passing logic.
Related
I'm currently making an ecommerce app in Swift 4 and linking data with Moltin. I'm doing this for school so I'm new at this. I'm also following CodeWithChris's tutorial but that is out of date and my layout is a bit different. I followed everything on it but I'm getting this error:
Type '[AnyHashable : Any]?' has no subscript members
I don't understand why.
self.objects = responseDictionary["result"] as? [AnyObject]
I tried changing as? to as! and it still didn't work.
Here's my complete code;
import UIKit
import Moltin
class TableViewController: UITableViewController {
var objects = [AnyObject]()
override func viewDidLoad() {
super.viewDidLoad()
Moltin.sharedInstance().setPublicID('***my store ID***')
Moltin.sharedInstance().product.listing(withParameters: nil, success: { (responseDictionary) in
self.objects = responseDictionary["result"] as? [AnyObject]
self.tableView.reloadData()
}) { (responseDictionary, error) in
print ("Something went wrong")
}
}
responseDictionary appears to be an optional which needs to be checked for existence:
Moltin.sharedInstance().product.listing(withParameters: nil, success: { (response) in
guard let responseDictionary = response as? [AnyHashable : Any] else {
print("Error: respnonse is empty")
return
}
self.objects = responseDictionary["result"] as? [AnyObject]
// ...
}
I have a data downloader class that downloads data from mySQL server.
The problem I am having is when the result is null - the app crashes with error message
Could not cast value of type '__NSArray0' (0x105548918) to 'NSMutableArray' (0x105549c00).
class userDetailsDownloader: NSObject, NSURLSessionDataDelegate {
weak var delegate: getUserDetails!
var data : NSMutableData = NSMutableData()
func downloadUserDetails(userEmail: String) {
let urlPath: String = "http://intouchmobile.co/phpscripts/getuserpassword.php?email=\(userEmail)"
let url: NSURL = NSURL(string: urlPath)!
var session: NSURLSession!
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration() //defaultSessionConfiguration()
session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTaskWithURL(url)
task.resume()
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.data.appendData(data);
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil
{
print("Failed to get password")
}
else
{
self.parseJSON()
print("Password Received")
}
}
func parseJSON() {
var jsonResult: NSMutableArray = NSMutableArray()
var password: String!
var firstName: String!
var lastName: String!
do{
jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
}
Don't say as! NSMutableArray. The term as! means "crash me", so you can hardly be surprised when you do crash. Say as? NSMutableArray. Test the result for nil. If it is nil, stop.
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as? NSMutableArray {
self.jsonResult = jsonResult
}
You may still have problems because this is never going to be a mutable array; it's just an array. So you might have to change it to:
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as? NSArray {
self.jsonResult = NSMutableArray(array: jsonResult)
}
(But, as vadian has said in a comment, it would be even better if you could abandon use of NSArray and NSMutableArray and use Swift types instead.)
Try it like this.
if NSJSONSerialization.isValidJSONObject(data) {
//your do catch
}
That should solve your problem.
I'm trying to download a file from Parse but I'm getting a fatal error: crash, it seems as if the message variable is nil. I've tried to troubleshoot, and I know there is an easy miss I'm just not seeing. Hoping the community can help as I am new to swift.
class InboxViewController: UITableViewController {
var messages: [PFObject] = []
var selectedMessage: PFObject?
var moviePlayer: MPMoviePlayerController?
override func viewDidLoad() {
super.viewDidLoad()
self.moviePlayer = MPMoviePlayerController()
let currentUser = PFUser.currentUser()
if currentUser != nil {
// Do stuff with the user
print("Current user: \(currentUser!.username)")
} else {
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let query = PFQuery(className: "Messages")
query.whereKey("recipientIds", equalTo: PFUser.currentUser()!.objectId!)
query.findObjectsInBackgroundWithBlock {
(objects : [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
let messages = object["file"] as! PFFile
self.tableView.reloadData()
print("Retreived \(self.messages.count) messages")
}
}
}
}
The crash breakpoint is at the beginning of the query.
Thank you community, another set of experienced eyes always helps.
you can safely unwrap the objects using if let construct
if let objects = objects {
for object in objects
let messages = object["file"] as? PFFile
print(messages)
// or you can also safely unwarp here
// if let messages = object["file"] as? PFFile {
// print(message)
// }
self.tableView.reloadData()
print("Retreived \(self.messages.count) messages")
}
}
I am retrieving posts in a data handler from a DB for a news feed and I run a php script and echo the JSON encoded data back to my application, at which point the data is parsed and stored in a model of a "post", there is a protocol that is used in the view controller to get the data once it has been downloaded. My problem is that I am getting the notorious "Unexpectedly found nil when unwrapping optional value" error when I pass the NSMutableArray of "post" objects to the function "itemsDownloaded" which is function of the protocol. I checked all the values being parsed and they exist, and I also checked the count of the array to make sure it has values. The exception is occurring on the line self.delegate.itemsDownloaded(posts)
The code to handle the data is this :
import Foundation
protocol PostDataHandlerProtocol: class {
func itemsDownloaded(items: NSArray)
}
class PostDataHandler: NSObject, NSURLSessionDataDelegate {
weak var delegate: PostDataHandlerProtocol!
var data : NSMutableData = NSMutableData()
//The path to the php script to be executed
let urlPath: String = "www.something.com/myphpscript.php"
func downloadItems() {
let url: NSURL = NSURL(string: urlPath)!
var session: NSURLSession!
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTaskWithURL(url)
task.resume()
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.data.appendData(data);
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded")
self.parseJSON()
}
}
func parseJSON() {
var jsonResult: NSMutableArray = NSMutableArray()
do{
jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement: NSDictionary = NSDictionary()
let posts: NSMutableArray = NSMutableArray()
for(var i = 0; i < jsonResult.count; i++)
{
jsonElement = jsonResult[i] as! NSDictionary
let post = PostModel()
//The following insures none of the JsonElement values are nil through optional binding
let username = jsonElement["username"] as? String
let imagePath = jsonElement["user_imagePath"] as? String
let postID = (jsonElement["post_id"] as! NSString).integerValue
let postRep = (jsonElement["post_rep"] as! NSString).integerValue
let postType = jsonElement["post_type"] as? String
let postDate = jsonElement["post_date"] as? String
let comment = jsonElement["comment"] as? String
post.username = username
post.imagePath = imagePath
post.postID = postID
post.postRep = postRep
post.postType = postType
post.postDate = postDate
post.comment = comment
posts.addObject(post)
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.delegate.itemsDownloaded(posts)
})
}
}
In my view controller, I create a new data handler let postHandler = PostDataHandler() and then once the view has loaded I call postHandler.downloadItems() and in the view controller declaration I conformed to the protocol and implemented itemsDownloaded:
func itemsDownloaded(items: NSArray) {
allPosts = items as! [PostModel]
indicator.stopAnimating()
self.tableVIew.reloadData()
}
Does anyone know why this is happening? I tried to look at the numerous postings regarding this error as I'm aware it's quite common, but couldn't find anything that helped me. Many of the postings say there should be a check to ensure it's not nil, the problem is I didn't think NSMutableArray can be optional, and also I checked all the values and they don't appear to be nil, so those answers did not help me. In the thread exceptions it says something related to a closure, which I think could be causing the issue, I'm just not exactly sure what or how.
None of the code that you showed ever set your PostDataHandler's delegate property to anything, so it is reasonable to suppose that it is still nil, which perfectly explains why you crash at runtime when you try to access it as if it were an actual object.
I am using code in tutorial by http://www.raywenderlich.com/76735/using-nsurlprotocol-swift
In that tutorial the code is caching every single request.
My question is when and how can I clear entity of caching (Core data)? Or We dont need to clear caching entity?
Caching entity is entity where I save all data requested by NSConnection. If we need to clear cache in core data how can I choose some data to stay and others to be deleted.
For example , I am making news app. Every VC has label such as title, date, category and UIWebView. And when app is closed I want to delete all caching links except "saved news". "Saved news" is category which users choose by tapping button "plus".
I am thinking to create new column named "isToSave". So, when user taps button to save. I need to parse content text and pull out links (src=) and in CoreData set the column "isToSave "to true. When app is closed I will delete all links with column "isTosave" = false
So shortly: is it good practice to clear entity "cacheURls" and if yes how can I clear urls by selection ?
Here is code:
import UIKit
import CoreData
var requestCount = 0
class MyURLProtocol: NSURLProtocol {
var connection: NSURLConnection!
var mutableData: NSMutableData!
var response: NSURLResponse!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
println("Request #\(requestCount++): URL = \(request.URL.absoluteString)")
if NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest: request) != nil {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override class func requestIsCacheEquivalent(aRequest: NSURLRequest,
toRequest bRequest: NSURLRequest) -> Bool {
return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
override func startLoading() {
// 1
let possibleCachedResponse = self.cachedResponseForCurrentRequest()
if let cachedResponse = possibleCachedResponse {
println("Serving response from cache")
// 2
let data = cachedResponse.valueForKey("data") as NSData!
let mimeType = cachedResponse.valueForKey("mimeType") as String!
let encoding = cachedResponse.valueForKey("encoding") as String!
// 3
let response = NSURLResponse(URL: self.request.URL, MIMEType: mimeType, expectedContentLength: data.length, textEncodingName: encoding)
// 4
self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.client!.URLProtocol(self, didLoadData: data)
self.client!.URLProtocolDidFinishLoading(self)
} else {
// 5
println("Serving response from NSURLConnection")
var newRequest = self.request.mutableCopy() as NSMutableURLRequest
NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
self.connection = NSURLConnection(request: newRequest, delegate: self)
}
}
override func stopLoading() {
if self.connection != nil {
self.connection.cancel()
}
self.connection = nil
}
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.client!.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.response = response
self.mutableData = NSMutableData()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.client!.URLProtocol(self, didLoadData: data)
self.mutableData.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
self.client!.URLProtocolDidFinishLoading(self)
self.saveCachedResponse()
}
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
self.client!.URLProtocol(self, didFailWithError: error)
}
func saveCachedResponse () {
println("Saving cached response")
// 1
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
let context = delegate.managedObjectContext!
// 2
let cachedResponse = NSEntityDescription.insertNewObjectForEntityForName("CachedURLResponse", inManagedObjectContext: context) as NSManagedObject
cachedResponse.setValue(self.mutableData, forKey: "data")
cachedResponse.setValue(self.request.URL.absoluteString, forKey: "url")
cachedResponse.setValue(NSDate(), forKey: "timestamp")
cachedResponse.setValue(self.response.MIMEType, forKey: "mimeType")
cachedResponse.setValue(self.response.textEncodingName, forKey: "encoding")
// 3
var error: NSError?
let success = context.save(&error)
if !success {
println("Could not cache the response")
}
}
func cachedResponseForCurrentRequest() -> NSManagedObject? {
// 1
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
let context = delegate.managedObjectContext!
// 2
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("CachedURLResponse", inManagedObjectContext: context)
fetchRequest.entity = entity
// 3
let predicate = NSPredicate(format:"url == %#", self.request.URL.absoluteString!)
fetchRequest.predicate = predicate
// 4
var error: NSError?
let possibleResult = context.executeFetchRequest(fetchRequest, error: &error) as Array<NSManagedObject>?
// 5
if let result = possibleResult {
if !result.isEmpty {
return result[0]
}
}
return nil
}
}