iOS Simulator Stuck on Launch Page after Update to XCode 7 - ios

I updated to Xcode 7 from Xcode 6 and updated my code to swift 2.0 from swift 1.2. When I run the project, there are no compile time errors, just warnings, and the build is successful. The problem I am having is that the main.storyboard does not load. By this i mean all that is shown in the simulator is the launch page and the initial view controller is never put into the hierarchy (i believe). When i updated my code to swift 2.0, i manually updated the AppDelegate which i did not expect and is why i think there may be something wrong with the file. I also get a Thread 1: EXC_BAD_ACCESS (code=2 ...) error which i understand to be a recursion error but don't understand how to resolve the issue.
Things I have tried
Reinstalling Xcode 7
Using Simulator 8.4 instead of 9.0
Updated to last swift syntax (Edit->Convert->To Latest Swift Syntax)
Here is my AppDelegate File
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
self.saveContext()
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.wt9t.BaseballsInsightVersionBeta" in the application's documents Application Support directory.
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1]
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("BaseballsInsightVersionBeta", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("BaseballsInsightVersionBeta.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
do {
try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext? = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if managedObjectContext!.hasChanges {
do {
try managedObjectContext!.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
}
Also i am including my initial view controller called MainVC
import UIKit
import CoreData
import Foundation
import SystemConfiguration
class MainVC: UIViewController {
#IBOutlet var chartCountTextView: UITextView!
let cdao = CoreDataRequests()
var chartsCompleted:Array<String> = []
override func viewDidLoad() {
super.viewDidLoad()
print("Viewdidload finished")
self.view.backgroundColor = UIColor.darkGrayColor()
let count = cdao.getChartCountInQueue()
if(count != 0)
{
chartCountTextView.text = "\(count) charts have yet to be uploaded, click Chart Queue to start the process"
}
else
{
chartCountTextView.text = ""
}
chartCountTextView.backgroundColor = UIColor.clearColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
let email = NSUserDefaults.standardUserDefaults().stringForKey("userEmail")
let password = NSUserDefaults.standardUserDefaults().stringForKey("userPassword")
if(email == nil || password == nil)
{
self.performSegueWithIdentifier("login", sender: self)
}
}
}

Related

Swift 4 error: [<UIViewController 0x7ff66ec0ef30> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key emailField

I've tried to link a couple objects in a xib file to my code for the View Controller through IBOutlets, but when I run the code I get the error
'NSUnknownKeyException', reason: '[< UIViewController 0x7f94dfc0f110>
setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key emailField.'
I've tried deleting all the outlets and reassigning them, and checking that all the connected objects only have one respective outlet each. Also, when unlinking one element, its error goes away, but the same format of the error for a different linked element appears.
import UIKit
import FirebaseAuth
import Firebase
class SignUpViewController: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func toSignUp(_ sender: Any) {
Auth.auth().createUser(withEmail: emailField.text!, password: passField.text!, completion: nil)
Firestore.firestore().collection("users").document(usernameField.text!).setData([
"name" : nameField.text!,
"username" : usernameField.text!,
"email" : emailField.text!
])
TransitionModel().transitionModel(viewControllerName: "LoginViewController", newView: LoginViewController().view!, viewControllerCurrent: self)
}
#IBAction func toLogin(_ sender: Any) {
TransitionModel().transitionModel(viewControllerName: "LoginViewController", newView: LoginViewController().view!, viewControllerCurrent: self)
}
}
import UIKit
import Firebase
class LoginViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func toLogin(_ sender: Any) {
}
}
import UIKit
import CoreData
import Firebase
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = UIViewController(nibName: "SignUpViewController", bundle: nil)
self.window?.makeKeyAndVisible()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
self.saveContext()
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "Pono_Beta")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
Thank you in advance for responses.
This happens when you just copy paste view controller.
Goto Storyboard, Select View Controller Open connection inspector and remove connections for emailField and create new Outlet

Data not persistent in Core Data when app re-launches

I am using Core Data for the first time in a project made in XCode 8, swift 3. I have used background context (calling container.performBackgroundTask block..) to save the data and main context to fetch the data. When my app re-launches, the data I saved in the private background context is deleted.
Please tell me where I went wrong !!!
Here I call CoreDataManager class save context method in applicationDidEnterBackground and applicationWillTerminate methods of AppDelegate class:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
lazy var coreDataMgrInstance = CoreDataManager.sharedInstance
func applicationDidEnterBackground(_ application: UIApplication) {
coreDataMgrInstance.saveContext()
}
func applicationWillTerminate(_ application: UIApplication) {
coreDataMgrInstance.saveContext()
}}
Here is my Singleton class CoreDataManager to initiate NSpersistentContainer
class CoreDataManager: NSObject {
class var sharedInstance: CoreDataManager {
struct Singleton {
static let instance = CoreDataManager()
}
return Singleton.instance
}
private override init() {
super.init()
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "E_CareV2")
let description = NSPersistentStoreDescription() // enable auto lightweight migratn
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
return container
}()
func saveContext(){
print("saveContext")
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Failure to save main context \(nserror), \(nserror.userInfo)")
}
}}
Now this is the class where I save and fetch the data from Core Data
class SenderViewController: UIViewController {
var persistentContainer: NSPersistentContainer!
override func viewDidLoad() {
super.viewDidLoad()
persistentContainer = CoreDataManager.sharedInstance.persistentContainer
let results = self.fetchPersistentData(entityName: "School", withPredicate: nil)
print("results \n \(results)")
}
#IBAction func enterPressed(_ sender: Any) {
self.persistentContainer.performBackgroundTask({ (backgroundContext) in
backgroundContext.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump
let schoolentity = NSEntityDescription.insertNewObject(forEntityName: "School", into: backgroundContext) as! School
schoolentity.schoolName = "ABC"
schoolentity.schoolWebSite = "http://anywebsite.com/"
do {
try backgroundContext.save()
} catch {
fatalError("Failure to save background context: \(error)")
}
})
}
func fetchPersistentData(entityName: String?, withPredicate: NSPredicate?) -> [NSManagedObject]{
let context = self.persistentContainer.viewContext
let request: NSFetchRequest<School> = School.fetchRequest()
let newentity = NSEntityDescription.entity(forEntityName: entityName!, in: context)
request.entity = newentity
request.returnsObjectsAsFaults = false
do {
let searchResults = try context.fetch(request) as [NSManagedObject]
return searchResults
} catch {
print("Error with request: \(error)")
}
return []
}
Actually the lightweight migrations are enabled by default as you can see on the screenshot
So you can safely delete these lines:
let description = NSPersistentStoreDescription() // enable auto lightweight migratn
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
After that everything should work.
There are two ways to use NSPersistentContainer - the simple way and the correct way. You are mixing them which is leading to problems. Apple is a little inconsistent on this in its documentation so it is understandable that you are confused.
The Simple Way - The simple way is only use the viewContext both for reading and for writing and only from the main thread. There are never any conflicts because core-data is assessed via a single thread. The problem with this approach is that you can't run anything in a background thread. So if you are importing a lot of data the UI will freeze. If you have a super simple app (a small task list?) this will work OK, but not something that I would ever recommend for a serious app. It is OK for a testing app for a beginner to learn core-data.
The Correct Way - the correct way is to NEVER write to the viewContext EVER. Apple documents this in NSPersistentContainer documentation (but also in its template creates a save method for the viewContext?!). In this setup all writes to core data MUST go through performBackgroundTask and you have to call save on that context before the end of the block. You also need an operation queue to make sure that there are no merge conflicts see NSPersistentContainer concurrency for saving to core data. This setup is a lot harder to do correctly. Objects from performBackgroundTask contexts cannot leave the block and objects from the viewContext cannot be used in the block. The complier doesn't help you with this so it is something that you always need to watch out for.
Your problem is mergePolicy. mergePolicy is evil. If you have conflicts in core-data you have already done something wrong and any merge policy will lose data. In the simple setup there are no conflicts because it is all on one thread. In the correct setup there is no conflicts because of the queue you created when using performBackgroundTask. The problem is that if you use BOTH performBackgroundTask and write the the viewContext you can get conflicts and you will lose data. Personally, I think it is better to have no mergePolicy and crash then to silently lose data.
I figured out what causes my data not to be persistent in Core Data. It was these below 4 lines of code that I put in persistentContainer definition for enabling LIGHTWEIGHT MIGRATION of models:
let description = NSPersistentStoreDescription() // enable auto lightweight migratn
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
When I deleted these lines, I became able to retain my data when the app re-launches.
I had written the above lines to enable Lightweight Migration to my model, but I did not change my model or created new version of the model, making the Core Data unable to search the destination model in NSBundle and thus unable to infer the Mapping.
I am still not sure, how that would delete my data but I will keep trying to figure this out too and comment when I get success in it... :)

iOS 9 and iOS 10 CoreData simultaneously

I have a question about Swift 3 releted with Core Data. I am developing an App in Swift with Xcode 8, and I need to support iOS 9 and iOS10. The problem is that I don't know how to get the AppDelegate and the Context (to use for store and get data from my Entities). I think my code should be something like this:
#if avaliable(iOS10,*)
{
// iOS 10 code
} else
{
// iOS 9 code
}
But I don't know what to do.
Any idea?
(A small help in correction would be appreciated)
# Code in Swift 3 for Core Data for both iOS 9 and iOS 10 #
Since you want the core data code for both iOS 9 and iOS 10 then you don't have to use NSPersistentContainer as it not supported in iOS 9, so you have to use old method instead
If at the time of project creation you haven't included core data and later you want to include it, follow the following steps :-
Step 1. Go to Build Phases -> Link Binary with Library -> click on + sign -> Add CoreData.framework
Step 2. Now got to file -> New File -> select Data Model.
Step 3. Now you need to write some code inside AppDelegate.swift to get set go :-
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
self.saveContext()
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "hacker.at.work.mTirgger" in the application's documents Application Support directory.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1] as NSURL
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
}
That's all your Core Data is ready for both iOS 9 and iOS 10 in Swift 3. Enjoy !!!
If you want to support iOS9 then the best bet is not to use any new iOS10 stuff.
Stick with the iOS9 API for now, and in the future when you eventually drop iOS9 support you can refactor your code to use the newer methods then.
edit: Just to be clear, all the iOS9 code will run fine on iOS10. You don't need to do anything special there, it is all backwards compatible.
CoreData for iOS9 and iOS10 simultaneously
For who you may need it:
This is an unmodified Master-Detail App template from the latest Xcode7 (for iOS9) release of May 2016. I have updated it with the current latest Xcode (Version 8.2.1)
With this template you can develope an application that uses CoreData compatible with iOS9 and iOS10, at least for now (May 2017)
AppDelegate.swift
//
// AppDelegate.swift
// trash
//
// Created by Markus on 22/05/17.
// Copyright © 2017 Markus. All rights reserved.
//
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let splitViewController = self.window!.rootViewController as! UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
splitViewController.delegate = self
let masterNavigationController = splitViewController.viewControllers[0] as! UINavigationController
let controller = masterNavigationController.topViewController as! MasterViewController
controller.managedObjectContext = self.managedObjectContext
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
self.saveContext()
}
// MARK: - Split view
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
if topAsDetailController.detailItem == nil {
// Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return true
}
return false
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: URL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.senbei.trash" in the application's documents Application Support directory.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1]
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = Bundle.main.url(forResource: "trash", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
}
MasterViewController.swift
//
// MasterViewController.swift
// trash
//
// Created by Markus on 22/05/17.
// Copyright © 2017 Markus. All rights reserved.
//
import UIKit
import CoreData
class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate {
var detailViewController: DetailViewController? = nil
var managedObjectContext: NSManagedObjectContext? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:)))
self.navigationItem.rightBarButtonItem = addButton
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
override func viewWillAppear(_ animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func insertNewObject(_ sender: AnyObject) {
let context = self.fetchedResultsController.managedObjectContext
let entity = self.fetchedResultsController.fetchRequest.entity!
let newManagedObject = NSEntityDescription.insertNewObject(forEntityName: entity.name!, into: context)
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
newManagedObject.setValue(Date(), forKey: "timeStamp")
// Save the context.
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//print("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
// MARK: - Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.fetchedResultsController.object(at: indexPath)
let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSections(in tableView: UITableView) -> Int {
return self.fetchedResultsController.sections?.count ?? 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionInfo = self.fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let object = self.fetchedResultsController.object(at: indexPath) as! NSManagedObject
self.configureCell(cell, withObject: object)
return cell
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let context = self.fetchedResultsController.managedObjectContext
context.delete(self.fetchedResultsController.object(at: indexPath) as! NSManagedObject)
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//print("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
}
func configureCell(_ cell: UITableViewCell, withObject object: NSManagedObject) {
//cell.textLabel!.text = object.value(forKey: "timeStamp")!.description
cell.textLabel!.text = (object.value(forKey: "timeStamp")! as AnyObject).description
}
// MARK: - Fetched results controller
//var fetchedResultsController: NSFetchedResultsController {
var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
//let fetchRequest = NSFetchRequest()
//let fetchRequest = NSFetchRequest<Event>(entityName: "Event") //another alternative
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Event")
// Edit the entity name as appropriate.
let entity = NSEntityDescription.entity(forEntityName: "Event", in: self.managedObjectContext!)
fetchRequest.entity = entity
// Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20
// Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
do {
try _fetchedResultsController!.performFetch()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//print("Unresolved error \(error), \(error.userInfo)")
abort()
}
return _fetchedResultsController!
}
//var _fetchedResultsController: NSFetchedResultsController? = nil
var _fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>?
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
switch type {
case .insert:
self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
case .delete:
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
default:
return
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .fade)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .fade)
case .update:
self.configureCell(tableView.cellForRow(at: indexPath!)!, withObject: anObject as! NSManagedObject)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.endUpdates()
}
/*
// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed.
func controllerDidChangeContent(controller: NSFetchedResultsController) {
// In the simplest, most efficient, case, reload the table view.
self.tableView.reloadData()
}
*/
}
DetailViewController.swift
//
// DetailViewController.swift
// trash
//
// Created by Markus on 22/05/17.
// Copyright © 2017 Markus. All rights reserved.
//
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var detailDescriptionLabel: UILabel!
var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let detail = self.detailItem {
if let label = self.detailDescriptionLabel {
//label.text = detail.value(forKey: "timeStamp")!.description
label.text = (detail.value(forKey: "timeStamp")! as AnyObject).description
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.configureView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Data model is the original from template, as well as storyboard. Both there are not modified.
You can use the new API and get the benefits out of it by doing something like this:
var coreDataManager: CoreDataManagerProtocol!
#if available(iOS10,*)
{
coreDataManager = CoreDataManagerNewStack()
} else
{
coreDataManager = CoreDataManagerOldStack()
}
and then you implement the new CoreData with the new stack into a class:
class CoreDataManagerNewStack: CoreDataManagerProtocol {
var container: NSPersistentContainer
// etc
}
and the old one with the code paster above with the whole code to generate the stack
class CoreDataManagerOldStack: CoreDataManagerProtocol {
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// etc
}

Integrate React-Native app to Swift 3

I have a working app in react native. iOS project files are made by react native which is based in Objective-C. I found it harder to convert Objective-C to Swift. So I decided to make a plain Project in swift 3 and then integrate the React Native to it. I followed the instruction here :
http://facebook.github.io/react-native/docs/integration-with-existing-apps.html
I did first steps, but when it comes to :
The Magic: RCTRootView Now that your React Native component is
created via index.ios.js, you need to add that component to a new or
existing ViewController. The easiest path to take is to optionally
create an event path to your component and then add that component to
an existing ViewController.
We will tie our React Native component with a new native view in the
ViewController that will actually host it called RCTRootView .
There is no example or proper explanation.
Is there any ready to go boilerplate or any complete tutorial on how to integrate react native to swift 3 project?
UPDATE:
According to this tutorial : https://gist.github.com/boopathi/27d21956fefcb5b168fe
I updated my project to look like this :
AppDelegate.swift :
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// initialize the rootView to fetch JS from the dev server
let rootView = RCTRootView()
rootView.scriptURL = NSURL(string: "http://localhost:8081/index.ios.js.includeRequire.runModule.bundle")
rootView.moduleName = "OpenCampus"
// Initialize a Controller to use view as React View
let rootViewController = ViewController()
rootViewController.view = rootView
// Set window to use rootViewController
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
if #available(iOS 10.0, *) {
self.saveContext()
} else {
// Fallback on earlier versions
}
}
// MARK: - Core Data stack
#available(iOS 10.0, *)
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "OpenCampus")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
#available(iOS 10.0, *)
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
ViewController.swift :
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Project-name-bridging-header :
#ifndef OpenCampus_Briding_Header_h
#define OpenCampus_Briding_Header_h
#endif /* OpenCampus_Briding_Header_h */
find ../../../node_modules/react-native/React -name "*.h" | awk -F'/' '{print "#import \""$NF"\""}'
and this is the result :
Well, surprisingly code push works without editing the AppDelegate.swift. I just imported codepush at Bridging header.
So make a new swift file, select to make a bridging header for Objective-C,
Then delete AppDelegate.m AppDelegate.h and main.h files,
Import following modules in Bridging header (ProjectName-Bridging-Header.h) :
#import "RCTBridgeModule.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTRootView.h"
#import "RCTUtils.h"
#import "RCTConvert.h"
#import "CodePush.h"
And AppDelegate.swift should look like this :
import Foundation
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var bridge: RCTBridge!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let jsCodeLocation = NSURL(string: "http://localhost:8081/index.ios.bundle?platform=ios&dev=true")
// jsCodeLocation = NSBundle.mainBundle().URLForResource("main", withExtension: "jsbundle")
let rootView = RCTRootView(bundleURL:jsCodeLocation, moduleName: "****ModuleName****", initialProperties: nil, launchOptions:launchOptions)
self.bridge = rootView.bridge
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window!.rootViewController = rootViewController;
self.window!.makeKeyAndVisible()
return true
}
And Replace module name with the module you register in your index.ios.js or index.android.js (App Registery)

App crash when reload button is pressed

i'm having some problems with my weather app for iOS.
I'm new in programming in xCode, so it could be a silly error.
Anyway, the problem is: I'm trying to add a refresh button in my Single Page App. The button has a IBAction function associated, so that when it is pressed it should get hidden and the activity indicator should appear.
That is the function:
#IBAction func reload() {
refreshButton.hidden = true
refreshActivityIndicator.hidden = false
refreshActivityIndicator.startAnimating()
}
and that is the declaration of the variables:
#IBOutlet weak var refreshButton: UIButton!
#IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!
when i run the app and press the refresh button, the app crash and i get this error:
#UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { <--thread 1 signal sigarbt
the console doesn't show anything else.
What could be the problem?
// APPDELEGATE.SWIFT
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
application.setStatusBarHidden(true, withAnimation: .None)
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
//VIEWCONTROLLER.SWIFT
import UIKit
import Foundation
class ViewController: UIViewController {
private let apiKey = "447073dc853014a6fa37376c43d8462b"
#IBOutlet weak var iconView: UIImageView!
#IBOutlet weak var currentTimeLabel: UILabel!
#IBOutlet weak var temperatureLabel: UILabel!
#IBOutlet weak var humidityLabel: UILabel!
#IBOutlet weak var precipitationLabel: UILabel!
#IBOutlet weak var summaryLabel: UILabel!
#IBOutlet weak var refreshButton: UIButton!
#IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
refreshActivityIndicator.hidden = true
// base URL
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
// add coordinates to base url (API syntax)
let forecastURL = NSURL(string: "44.698150,10.656846", relativeToURL: baseURL)
// NSURL SESSION
//The NSURLSession class and related classes provide an API for downloading content via HTTP. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads when your app is not running or, in iOS, while your app is suspended. With the NSURLSession API, your app creates a series of sessions, each of which coordinates a group of related data transfer tasks. For example, if you are writing a web browser, your app might create one session per tab or window. Within each session, your app adds a series of tasks, each of which represents a request for a specific URL (and for any follow-on URLs if the original URL returned an HTTP redirect).
let sharedSession = NSURLSession.sharedSession()
let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler:
{ (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
if (error == nil) {
let dataObject = NSData(contentsOfURL: location) // convert in NSData object
// serialize NSData object in Json as Dictionary
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary
// instance of Current (Current.swift) init with weatherDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
// we put the code in the main queue cause this is relative the UI, that have the first thread (concurrency)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.temperatureLabel.text = "\(currentWeather.temperature)"
self.iconView.image = currentWeather.icon!
self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
self.humidityLabel.text = "\(currentWeather.humidity)"
self.precipitationLabel.text = "\(currentWeather.precipProbability)"
self.summaryLabel.text = "\(currentWeather.summary)"
// Stop refresh animation
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask.resume() // call sharedSession.downloadTaskWithURL -> store json data in location (local temporary memory)
}
#IBAction func reload() {
println("PRESSED")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I haven't got any .h or .m file.
Is reload function even getting called? If you are using storyboard/Xib for creating the UIButton then link the reload function in Xib on touchUpInside Event or if you are creating the UIButton event in code then like below:
Create another UIButton property in .h file:
#property(nonatomic, strong) UIButton *refresh;
In .m file
-(void) viewDidLoad {
self.refresh = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.refresh addTarget:self
action:#selector(reload:) forControlEvents:UIControlEventTouchUpInside];
[self.refresh setTitle:#"Reload" forState:UIControlStateNormal];
self.refresh .frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:self.refresh];
}
-(void) reload:(UIButton*)sender
{
NSLog(#"you clicked on button %#", sender.tag);
if(self.refresh.hidden) {
self.refresh.hidden = false;
} else {
self.refresh.hidden = true;
}
}
Okay it works!
Please don't ask me why :)
I simply deleted the code and rewrote it. And it works. Call it magic.
Thank you all for your answers.

Resources