I am getting EXC_BAD_ACCESS error when I try to access my author item in my CoreData.
I am gettin the error when I try to access author.authorName
func setupAuthorList(){
var error: NSError?
let request = NSFetchRequest(entityName: "AuthorList")
let results = self.context!.executeFetchRequest(request, error: &error) as! [AuthorList]
if let _error = error {
println("\(_error.localizedDescription)")
} else {
for author in results {
println("\(author.authorName)")
}
}
self.authorLabel.text = author!.authorName
let urlString = author!.authorImage
let url = NSURL(string: urlString)
self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.width/2
self.avatarImageView.clipsToBounds = true
self.avatarImageView.hnk_setImageFromURL(url!)
self.newspaperLabel.text = author!.newspaperName
}
Related
Hi I am calling block inside block but app is crashing with error libc++abi.dylib: terminating with uncaught exception of type NSException. There are no other description printed on console. unable to find issue.
GeocoderApi.shared.getAddress(lat: "\(coordinate.latitude)", lang: "\(coordinate.longitude)", reverseGeocodeHandler: { status, responseObject in
if let locality = responseObject as? String{
WeatherApi.shared.averageForecastName(cityName: locality, completionHandler: { status, responseObject in
LocationManager.shared.stopUpdatingLocation()
if let weatherArray = responseObject as? [Weather]{
if !weatherArray.isEmpty {
self.myJourney.weatherArray.remove(at: 0)
self.myJourney.weatherArray.insert(weatherArray[0], at: 0)
self.myJourney.weatherArray[0].upcomings.append(contentsOf: weatherArray)
self.myJourney.weatherArray[0].upcomings.remove(at: 0)
self.journeyView.reloadWeather()
}
}
})
}
})
func getAddress(lat:String,lang:String,reverseGeocodeHandler:#escaping (_ status:Bool, _ responseObject:Any)->()){
if !ReachabilityManager.shared.isReachable {
let error = WSError()
error.errorTitle = "Network error"
error.errorDescription = "Unable to connect, please check your internet connectivity."
reverseGeocodeHandler(false,error)
return
}
self.showNetworkActivity()
let sessionManager = AFHTTPSessionManager(baseURL: baseUrl, sessionConfiguration: URLSessionConfiguration.default)
sessionManager.requestSerializer = AFJSONRequestSerializer()
sessionManager.responseSerializer = AFJSONResponseSerializer()
let urlPath = getPath(path: "maps/api/geocode/json?latlng=\(lat),\(lang)")
sessionManager.post(urlPath, parameters: nil, progress: { progress in
}, success: { task, responseObject in
var cityName = ""
if let disc = responseObject as? [String:Any]{
cityName = self.Parse(disc: disc)
}
self.hideNetworkActivity()
reverseGeocodeHandler(true,cityName)
}, failure: { operation, err in
self.hideNetworkActivity()
let error = WSError(error: err as NSError)
reverseGeocodeHandler(false,error)
})
}
func averageForecastName(cityName:String,completionHandler:#escaping (_ status:Bool, _ responseObject:Any)->()){
if !ReachabilityManager.shared.isReachable {
let error = WSError()
error.errorTitle = "Network error"
error.errorDescription = "Unable to connect, please check your internet connectivity."
completionHandler(false,error)
return
}
self.showNetworkActivity()
let sessionManager = AFHTTPSessionManager(baseURL: baseUrl, sessionConfiguration: URLSessionConfiguration.default)
sessionManager.requestSerializer = AFJSONRequestSerializer()
sessionManager.responseSerializer = AFJSONResponseSerializer()
let urlPath = getPath(path: "data/2.5/forecast/daily?q=\(cityName)&cnt=6")
sessionManager.post(urlPath, parameters: nil, progress: { progress in
}, success: { task, responseObject in
var weatherArray = [Weather]()
if let disc = responseObject as? [String:Any]{
weatherArray.append(contentsOf: Weather.GetForecasts(rootDisc: disc))
}
self.hideNetworkActivity()
completionHandler(true,weatherArray)
}, failure: { operation, err in
self.hideNetworkActivity()
let error = WSError(error: err as NSError)
completionHandler(false,error)
})
}
resolved it by .addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)
I am updating my UILabels from an API Call. I have an API Client file which pulls the needed information and then passes it over to the DataStore and then parses through the information and then creates movie Objects. The collectionViewController accesses the information without a problem but when it passes the information to the next view controller, a problem occurs. The information does not appear on the view controller and then when I click back in the information will appear. There is some sort of delay in the information from the API Client or something which I can't seem to figure out.
//Second API call to get information for the Second View Controller (Detail View Controller)
class func getDescriptiveMovieResultsFromSearch(movieID: String, completion:(NSDictionary)-> ())
{
var descriptiveDictionary: [String: String] = [:]
let searchURL = "https://www.omdbapi.com/?i=\(movieID)&?plot=short"
let nsurl = NSURL(string: searchURL)
//convert the url into an NSURL
guard let unwrappedNSURL = nsurl else {print("ERROR OCCURRED HERE"); return}
//unwrap the nsurl using guard let
//let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: unwrappedNSURL)
//creation of the request
request.HTTPMethod = "GET"
//By Default everythiing is a GET request if you are getting information and you don't need it
//request has an HTTPMethod of type "GET" to obtain information
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
guard let unwrappedData = data else {print("Error occurred here"); return}
if let responseDictionary = try? NSJSONSerialization.JSONObjectWithData(unwrappedData, options: []) as? NSDictionary
{
let castedResponseDictionary = responseDictionary as? [String : String]
guard let unwrappedResponseDictionary = castedResponseDictionary else {print("This did not work!"); return}
descriptiveDictionary = unwrappedResponseDictionary
}
completion(descriptiveDictionary)
}
task.resume()
}
//MovieDataStore function to parse through the information
/Second API Call
func getDescriptiveMovieInformationWith(movie: Movie, Completion: (Bool) -> ())
{
guard let unwrappedimdbID = movie.imdbID else {print("AN ERROR OCCURRED HERE"); return}
OMDBAPIClient.getDescriptiveMovieResultsFromSearch(unwrappedimdbID) { (descriptiveResponseDictionary) in
let desMovieDirector = descriptiveResponseDictionary["Director"] as? String
let desMovieWriters = descriptiveResponseDictionary["Writer"] as? String
let desMovieActors = descriptiveResponseDictionary["Actors"] as? String
let desMovieShortPlot = descriptiveResponseDictionary["Plot"] as? String
let desMovieimbdRating = descriptiveResponseDictionary["imdbRating"] as? String
//unwrapping each of the of the json information
guard let
unwrappedDesMovieDirector = desMovieDirector,
unwrappedDesMovieWriters = desMovieWriters,
unwrappedDesMovieActors = desMovieActors,
unwrappedDesMovieShortPlot = desMovieShortPlot,
unwrappedDesMovieimbdRating = desMovieimbdRating
else {print("AN ERROR OCCURRED HERE!"); return}
movie.director = unwrappedDesMovieDirector
movie.writers = unwrappedDesMovieWriters
movie.actors = unwrappedDesMovieActors
movie.shortPlot = unwrappedDesMovieShortPlot
movie.imdbRating = unwrappedDesMovieimbdRating
print("******************************************")
print("Movie Director: \(movie.director)")
print("Movie writers: \(movie.writers)")
print("Movie actors: \(movie.actors)")
print("Movie shortPlot: \(movie.shortPlot)")
print("Movie imdbRating: \(movie.imdbRating)")
print("******************************************")
//Completion(true)
Completion(true)
}
}
//Detail View Controller
/Second API Call
func getDescriptiveMovieInformationWith(movie: Movie, Completion: (Bool) -> ())
{
guard let unwrappedimdbID = movie.imdbID else {print("AN ERROR OCCURRED HERE"); return}
OMDBAPIClient.getDescriptiveMovieResultsFromSearch(unwrappedimdbID) { (descriptiveResponseDictionary) in
let desMovieDirector = descriptiveResponseDictionary["Director"] as? String
let desMovieWriters = descriptiveResponseDictionary["Writer"] as? String
let desMovieActors = descriptiveResponseDictionary["Actors"] as? String
let desMovieShortPlot = descriptiveResponseDictionary["Plot"] as? String
let desMovieimbdRating = descriptiveResponseDictionary["imdbRating"] as? String
//unwrapping each of the of the json information
guard let
unwrappedDesMovieDirector = desMovieDirector,
unwrappedDesMovieWriters = desMovieWriters,
unwrappedDesMovieActors = desMovieActors,
unwrappedDesMovieShortPlot = desMovieShortPlot,
unwrappedDesMovieimbdRating = desMovieimbdRating
else {print("AN ERROR OCCURRED HERE!"); return}
movie.director = unwrappedDesMovieDirector
movie.writers = unwrappedDesMovieWriters
movie.actors = unwrappedDesMovieActors
movie.shortPlot = unwrappedDesMovieShortPlot
movie.imdbRating = unwrappedDesMovieimbdRating
print("******************************************")
print("Movie Director: \(movie.director)")
print("Movie writers: \(movie.writers)")
print("Movie actors: \(movie.actors)")
print("Movie shortPlot: \(movie.shortPlot)")
print("Movie imdbRating: \(movie.imdbRating)")
print("******************************************")
//Completion(true)
Completion(true)
}
}
//detail view Controller
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blackColor()
self.titleLabel.textColor = UIColor.yellowColor()
self.yearLabel.textColor = UIColor.yellowColor()
self.directorLabel.textColor = UIColor.yellowColor()
self.writersLabel.textColor = UIColor.yellowColor()
self.actorsLabel.textColor = UIColor.yellowColor()
self.shortPlotLabel.textColor = UIColor.yellowColor()
self.imdbIDLabel.textColor = UIColor.yellowColor()
self.typeLabel.textColor = UIColor.yellowColor()
self.imdbRating.textColor = UIColor.yellowColor()
stackViewLabel.translatesAutoresizingMaskIntoConstraints = false
stackViewLabel.topAnchor.constraintEqualToAnchor(self.topImage.bottomAnchor, constant: 5).active = true
stackViewLabel.widthAnchor.constraintEqualToAnchor(self.view.widthAnchor, multiplier: 1.00).active = true
stackViewLabel.heightAnchor.constraintEqualToAnchor(self.view.heightAnchor, multiplier: 0.50).active = true
stackViewLabel.leftAnchor.constraintEqualToAnchor(self.view.leftAnchor).active = true
//unwrapped Movie Object
guard let unwrappedMovieObject = movieObject else {print("AN ERROR OCCURRED HERE!"); return}
self.store.getDescriptiveMovieInformationWith(unwrappedMovieObject) { (isWorking) in
if isWorking {
dispatch_async(dispatch_get_main_queue()){
guard let unwrappedPosterURL = unwrappedMovieObject.posterURL else {print("AN ERROR OCCURRED HERE"); return}
if unwrappedPosterURL == "N/A"{
self.topImage.image = UIImage.init(named: "star_PNG1592")
}
else {
if let url = NSURL(string: unwrappedPosterURL){
if let data = NSData(contentsOfURL: url){
//print("I have an image to display")
self.topImage.image = UIImage.init(data: data)
}
}
}
self.titleLabel.text = unwrappedMovieObject.title
self.yearLabel.text = unwrappedMovieObject.year
self.imdbIDLabel.text = unwrappedMovieObject.imdbID
self.typeLabel.text = unwrappedMovieObject.type
guard let
unwrappedDirector = unwrappedMovieObject.director,
unwrappedWriters = unwrappedMovieObject.writers,
unwrappedActors = unwrappedMovieObject.actors,
unwrappedShortPlot = unwrappedMovieObject.shortPlot,
unwrappedRating = unwrappedMovieObject.imdbRating
else {print("PROPERTIES WERE UNWRAPPED"); return}
self.directorLabel.text = unwrappedDirector
self.writersLabel.text = unwrappedWriters
self.actorsLabel.text = unwrappedActors
self.shortPlotLabel.text = unwrappedShortPlot
self.imdbRating.text = unwrappedRating
}
}
else{
print("AN ERROR OCCURRED HERE")
}
}
}
NSURLSession.sharedSession().dataTaskWithRequest(request)
I'm not sure what callback queue the sharedSession uses, If its not the main thread you will need to
DispatchQueue.main.async {
completion(descriptiveDictionary)
}
I've been trying to find out what causes memory leaks, but in Instruments, I am being told that the memory leak happens at seriesDownloadingQueue.addOperation(downloadOperation) and in the class that calls the method getSeries(), which starts the updating process.
I'm completely new to asynchronous programming and memory leaks. I've read some posts on stack overflow about finding and fixing the leaks. I've also read an article from http://www.raywenderlich.com on how to use Instruments. This app is a database preloader. It downloads and processes information. The .sqlite file will be used in a mobile app.
Below is the code which allegedly causes the memory leak. If you need more information, I'll provide it.
import Foundation
import CoreData
class SerieFetcher: NSObject{
dynamic var didGetSeries: Bool = false
static var doneSeries: Int = 0
func getSeries(){
var seriesDownloadingQueue: NSOperationQueue{
let val = NSOperationQueue()
val.maxConcurrentOperationCount = 32
val.name = "Serie Downloading & Processing Queue"
return val
}
var defaultSessionConfiguration:NSURLSessionConfiguration{
let val = NSURLSessionConfiguration.defaultSessionConfiguration()
val.HTTPMaximumConnectionsPerHost = 20
return val
}
let defaultSession: NSURLSession = NSURLSession(configuration: defaultSessionConfiguration,delegate: nil, delegateQueue: seriesDownloadingQueue)
if let countries = fetchCountries(){
for country in countries{
if let url = NSURL(string:(BASE_URL + "series/"+CAT_STAMPS+"producer/\(country.0)")){
let downloadOperation = downloadSeriesOperation(downloadURL: url, countryObjectID: country.1, countryCount: countries.count, defaultSession: defaultSession , completionHandler: { [weak self](didGetSeries) in
if(didGetSeries == true){
self!.didGetSeries = didGetSeries
print("Finished Downloading Series")
}
})
downloadOperation.completionBlock = nil
seriesDownloadingQueue.addOperation(downloadOperation)
}
}
}
}
func fetchCountries() -> [Int: NSManagedObjectID]?{
let fetchRequest = NSFetchRequest(entityName: "Country")
fetchRequest.resultType = .DictionaryResultType
let objectIDDesc = NSExpressionDescription()
objectIDDesc.name = "objectID"
objectIDDesc.expression = NSExpression.expressionForEvaluatedObject()
objectIDDesc.expressionResultType = .ObjectIDAttributeType
fetchRequest.propertiesToFetch = ["countryID",objectIDDesc]
fetchRequest.returnsDistinctResults = true
do{
let results = try managedContext.executeFetchRequest(fetchRequest) as! [NSDictionary]
var countryIDs: [Int: NSManagedObjectID] = [:]
for result in results{
let countryID: Int = result.valueForKey("countryID") as! Int
let objectID: NSManagedObjectID = result.valueForKey("objectID") as! NSManagedObjectID
countryIDs.updateValue(objectID, forKey: countryID)
}
return countryIDs
}catch let error as NSError{
print(error.localizedDescription)
}
return nil
}
}
class downloadSeriesOperation: NSOperation{
let countryObjectID:NSManagedObjectID
let downloadURL:NSURL
let countryCount:Int
let defaultSession:NSURLSession
let completionHandler: (didGetSeries: Bool) -> Void
init(downloadURL:NSURL, countryObjectID: NSManagedObjectID,countryCount: Int, defaultSession:NSURLSession, completionHandler: (didGetSeries:Bool) -> Void){
self.downloadURL = downloadURL
self.countryObjectID = countryObjectID
self.countryCount = countryCount
self.defaultSession = defaultSession
self.completionHandler = completionHandler
}
override func main() {
let dataTask = defaultSession.dataTaskWithURL(downloadURL, completionHandler: { (data, response, error) in
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.persistentStoreCoordinator = managedContext.persistentStoreCoordinator
privateMOC.undoManager = nil
var parsedData: NSArray?
do{
parsedData = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as? NSArray
}catch let error as NSError{
print(error.localizedDescription)
}
for val in parsedData!{
if let serieID = Int(val[0] as! NSString as String){
if let serieName = val[1] as? NSString as? String{
if serieID == 0{
continue
}
let serie = NSEntityDescription.insertNewObjectForEntityForName("Serie", inManagedObjectContext: privateMOC) as! Serie
serie.country = privateMOC.objectWithID(self.countryObjectID) as? Country
serie.serieID = serieID
serie.serieName = serieName
}
}
}
privateMOC.performBlock({
do{
try privateMOC.save()
privateMOC.reset()
}catch let error as NSError{
print(error.localizedDescription)
}
})
SerieFetcher.doneSeries += 1
print(self.countryCount,"/",SerieFetcher.doneSeries)
if(SerieFetcher.doneSeries == self.countryCount){
self.completionHandler(didGetSeries: true)
}
})
dataTask.resume() //Start the Download
}
}
1) I am trying to access twitter profile photo and upload it to the parse user object
2) Below is the code I am using.
if PFTwitterUtils.isLinkedWithUser(user){
//copy data to parse user
let screenName = PFTwitterUtils.twitter()?.screenName!
let requestString = ("https://api.twitter.com/1.1/users/show.json?screen_name=" + screenName!)
let verify: NSURL = NSURL(string: requestString)!
let request: NSMutableURLRequest = NSMutableURLRequest(URL: verify)
PFTwitterUtils.twitter()?.signRequest(request)
var response: NSURLResponse?
var error: NSError?
let data: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)!
if error == nil {
let result: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &error)
//let names: String! = result?.objectForKey("name") as! String
//let separatedNames: [String] = names.componentsSeparatedByString(" ")
//var firstName = separatedNames.first!
//var lastName = separatedNames.last!
let urlString = result?.objectForKey("profile_image_url_https") as! String
let hiResUrlString = urlString.stringByReplacingOccurrencesOfString("_normal", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
let twitterPhotoUrl = NSURL(string: hiResUrlString)
let imageData = NSData(contentsOfURL: twitterPhotoUrl!)
if(imageData != nil) {
let profileFileObject = PFFile(data:imageData!)
user.setObject(profileFileObject, forKey: "profilePicture")
}
user.saveInBackgroundWithBlock({ (success:Bool, error:NSError?) -> Void in
if(success) {
//println("User details are now updated")
user.pinInBackgroundWithBlock({ (pinUserSuccess:Bool, pinUserError:NSError?) -> Void in
if (pinUserSuccess){
println("User successfully pinned in twitter")
}else {
println("Error in pining the user")
}
})
}
})
} else {
println(error?.description)
}
3) I am using Parse User Interface to sign in using twitter. That is working. I am able to access the screen name
4) I am testing this on a simulator
Question 1 -
In the above code I am getting an error for the below code. Please help!
let data: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)!
Error Domain=NSURLErrorDomain Code=-1012 \"The operation couldn’t be completed. (NSURLErrorDomain error -1012.)\" UserInfo=0x7fd11aab87a0 {NSErrorFailingURLStringKey=https://api.twitter.com/1.1/users/show.json?screen_name=jayskapadia, NSUnderlyingError=0x7fd11aab51b0 \"The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)\", NSErrorFailingURLKey=https://api.twitter.com/1.1/users/show.json?screen_name=jayskapadia}
Question 2 - I also want to access the email id from the twitter profile. How do I do that?
the photo part now works with the below code
if PFTwitterUtils.isLinkedWithUser(user){
//copy data to parse user.
let screenName = PFTwitterUtils.twitter()?.screenName!
let verify = NSURL(string: "https://api.twitter.com/1.1/account/verify_credentials.json")
var request = NSMutableURLRequest(URL: verify!)
PFTwitterUtils.twitter()!.signRequest(request)
var response: NSURLResponse?
var error: NSError?
var data:NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)!
if error == nil {
let result: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: &error)
//let names: String! = result?.objectForKey("name") as! String
//let separatedNames: [String] = names.componentsSeparatedByString(" ")
//var firstName = separatedNames.first!
//var lastName = separatedNames.last!
let urlString = result?.objectForKey("profile_image_url_https") as! String
let hiResUrlString = urlString.stringByReplacingOccurrencesOfString("_normal", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
let twitterPhotoUrl = NSURL(string: hiResUrlString)
let imageData = NSData(contentsOfURL: twitterPhotoUrl!)
if (screenName != nil){
user.setObject(screenName!, forKey: "username")
}
if(imageData != nil) {
let profileFileObject = PFFile(data:imageData!)
user.setObject(profileFileObject, forKey: "profilePicture")
}
user.saveInBackgroundWithBlock({ (success:Bool, error:NSError?) -> Void in
if(success) {
//println("User details are now updated")
user.pinInBackgroundWithBlock({ (pinUserSuccess:Bool, pinUserError:NSError?) -> Void in
if (pinUserSuccess){
println("User successfully pinned in twitter")
}else {
println("Error in pining the user")
}
})
}
})
} else {
println(error?.description)
}
}
I have a database created in Cloudant and I am trying to parse that data in my Swift project. I have imported the Cloudant libraries, but I am not able to parse the data.
Here is the code that I Have been using till now
var url = "https://username:password#cloudant.com/dashboard.html#/database/db_2/login_details"
var request = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if jsonResult != nil {
if let item = json[0] {
if let student_name = item["Student_name"] {
if let pasword = student_name["password"] {
println("Login Successfull")
}
}
}
}
}
Can somebody tell me where am I going wrong?
You should use stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) to convert any special characters your link may have. Also NSURL may return nil so you need to use if let to handle it as follow :
if let link = "https://username:password#cloudant.com/dashboard.html#/database/db_2/login_details".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
if let checkedUrl = NSURL(string: link) {
println("valid Url")
// your code
} else {
println("invalid Url")
}
}