Change of scene class causes error, Xcode / Swift - xcode

I am trying to make a small iPad application which features an 'About' page. I have run into an issue when I try to change the class of the about page scene which is displayed modally, as the application crashes when the user tries to access this page. I wish to change its class to "ViewController", which is the same class as my main window (map view), to create actions from buttons on the 'About' page.
Currently I am unable to ctrl+drag to the .Swift file from the About page unless I change its class. Not sure why this is happening :(
The error printed to the console is as follows:
fatal error: unexpectedly found nil while unwrapping an Optional value
0 specialised_fatalErrorMessage(StaticString, StaticString, StaticString, Uint) -> () –
Here is my storyboard with scenes:
Here is the full ViewController.Swift code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate {
var location: CLLocation!
let locationManager = CLLocationManager()
// Map variables
var searchController:UISearchController!
var annotation:MKAnnotation!
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var error:NSError!
var pointAnnotation:MKPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var showSearchBar: UIBarButtonItem!
#IBOutlet weak var addButton: UIBarButtonItem!
#IBOutlet weak var moreStuff: UIBarButtonItem!
#IBAction func addButton(sender: AnyObject) {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: self.mapView.userLocation.coordinate.latitude, longitude: self.mapView.userLocation.coordinate.longitude)
self.mapView.addAnnotation(annotation)
self.locationManager.startUpdatingLocation()
}
#IBAction func showSearchBar(sender: UIBarButtonItem!) {
searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.delegate = self
presentViewController(searchController, animated: true, completion: nil)
}
#IBAction func moreStuff(sender: AnyObject) {
self.performSegueWithIdentifier("showMoreStuff", sender:self)
}
#IBAction func refresh(sender: AnyObject) {
self.locationManager.startUpdatingLocation()
}
#IBAction func segmentedControl(sender: UISegmentedControl!) {
if sender.selectedSegmentIndex == 0{
mapView.mapType = MKMapType.Standard
}
else if sender.selectedSegmentIndex == 1{
mapView.mapType = MKMapType.Satellite
}
else if sender.selectedSegmentIndex == 2{
mapView.mapType = MKMapType.Hybrid
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// location delegate methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Error code: " + error.localizedDescription)
}
func searchBarSearchButtonClicked(searchBar: UISearchBar){
searchBar.resignFirstResponder()
dismissViewControllerAnimated(true, completion: nil)
if self.mapView.annotations.count != 0{
annotation = self.mapView.annotations[0]
self.mapView.removeAnnotation(annotation)
}
localSearchRequest = MKLocalSearchRequest()
localSearchRequest.naturalLanguageQuery = searchBar.text
localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.startWithCompletionHandler { (localSearchResponse, error) -> Void in
if localSearchResponse == nil{
let alertController = UIAlertController(title: nil, message: "No Such Place", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
return
}
self.pointAnnotation = MKPointAnnotation()
self.pointAnnotation.title = searchBar.text
self.pointAnnotation.coordinate = CLLocationCoordinate2D(latitude: localSearchResponse!.boundingRegion.center.latitude, longitude: localSearchResponse!.boundingRegion.center.longitude)
self.pinAnnotationView = MKPinAnnotationView(annotation: self.pointAnnotation, reuseIdentifier: nil)
self.mapView.centerCoordinate = self.pointAnnotation.coordinate
}
}
}
I am new to Swift so any help is really appreciated. Thanks!
Edit:
This is the error screen presented to me once the app crashes:

I haven't used mapKit but I still try.
Looking at your error your getting a nil crash, which indicates one of your properties is nil yet you try to use it.
Having a quick read through your code it seams you haven't initialised
var localSearchResponse....
Again i don't know the MK API very well so I am not 100 sure what I'm saying is relevant.
Have you checked that all your IBOutlets are properly connected?
On which line do you get the crash when this happens? Do you get the crash before or after changing to the abouts page?

Related

Using Xcode and getting error "Cannot assign to property: 'image' is a method

I'm new to coding and would really appreciate some help on this. I've searched everywhere for a fix to my issue, but can't find one that makes sense to me. Here's my code (error location noted). Thanks in advance!
import UIKit
import Firebase
class UserVC: UIViewController, UIImagePickerControllerDelegate,
UINavigationControllerDelegate {
#IBOutlet weak var userImagePicker: UIButton!
#IBOutlet weak var completeSignUpBtn: UIButton!
var userUid: String!
var emailField: String!
var passwordField: String!
var imagePicker: UIImagePickerController!
var imageSelected = false
override func viewDidLoad() {
super.viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
userImagePicker.image = image **//error here**
imageSelected = true
}else {
print("image wasn't selected")
}
imagePicker.dismiss(animated: true, completion: nil)
}
#IBAction func completeAccount (_ sender: Any){
Auth.auth().createUser(withEmail: emailField, password: passwordField, completion:
{(user, error) in
if error != nil {
print(error)
}else{
if let user = user {
self.userUid = user.uid
}
}
})
}
#IBAction func selectedImagePicker(_ sender: Any){
present (imagePicker, animated: true, completion: nil)
}
#IBAction func cancel (_ sender: AnyObject){
dismiss (animated: true, completion: nil)
}
}
You cannot directly assign image to UIButton. Button has different method to set images. Here is swift 3 sample code to set button image.
let playButton = UIButton(type: .custom)
playButton.setImage(UIImage(named: "play.png"), for: .normal)
So try this
userImagePicker.setImage(image,for:.normal)

Swift Error: EXE_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

I'm trying to make this posting app similar to instagram but I am getting stuck on a issue once i press my compose button. This button is suppose to post the image but instead its crashing. I'm having an error after I try to upload a caption\image with my app here:
let imageData = UIImagePNGRepresentation(imageToBeUploaded!)!
It is giving me this error:EXE_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Please help!
#IBOutlet weak var captionTextView: UITextView!
#IBOutlet weak var previewImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
captionTextView.delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addImageTapped(sender: AnyObject) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypesForSourceType(.PhotoLibrary)!
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.previewImage.image = image
self.dismissViewControllerAnimated(true, completion: nil)
}
func textViewShouldEndEditing(textView: UITextView) -> Bool {
captionTextView.resignFirstResponder()
return true;
}
#IBAction func composeTapped(sender: AnyObject) {
let date = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
let localDate = dateFormatter.stringFromDate(date)
let imageToBeUploaded = self.previewImage.image
let imageData = UIImagePNGRepresentation(imageToBeUploaded!)!
let file: PFFile = PFFile(data: imageData)!
let fileCaption: String = self.captionTextView.text
let photoToUpload = PFObject(className: "Posts")
photoToUpload["Image"] = file
photoToUpload["Caption"] = fileCaption
photoToUpload["addedBy"] = PFUser.currentUser()?.username
photoToUpload["data"] = localDate
//Get bytes size of image
/* var imageSize = Float(imageData!.length)
//Transform into Megabytes
imageSize = imageSize/(1024*1024)
print("Image size is \(imageSize)Mb")
*/
do{
try photoToUpload.save()
} catch _ {
}
print("Successfully Posted.")
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("postController")
self.presentViewController(vc! as UIViewController, animated: true, completion: nil)
}
It seems that you are unwraping an optional value without actualy checking if it is nil.
Probably the issue is from let file: PFFile = PFFile(data: imageData)!. You must check for nil before you unwrap a variable.

How to update label in Second ViewController with information from First ViewController every second

I have an app that has two ViewControllers. On the first there is a count of current speed in realtime through CLLocationManager. Also there is a label that shows current speed with update by timer (NSTimer). In second ViewController there is another Label, where this current speed has to be shown too. It shows it, but don't update. I tried to set second timer (different ways: in first VC, in second VC - there is always was an error or just nothing).
Will be grateful for help, thanks!
First VC
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var currentSpeedLabel: UILabel!
var manager = CLLocationManager()
var currentSpeed: CLLocationSpeed = CLLocationSpeed()
var timer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
mapView.mapType = MKMapType.Hybrid
trackingMe()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func HUDMapView(sender: AnyObject) {
speedCount()
}
#IBAction func findMe(sender: AnyObject) {
trackingMe()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation: CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
mapView.setRegion(region, animated: true)
}
func trackingMe() {
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
mapView.showsUserLocation = true
currentSpeedUpdate()
}
func currentSpeedUpdate() {
timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("speedCount"), userInfo: nil, repeats: true)
}
func speedCount() {
currentSpeed = manager.location!.speed
currentSpeedLabel.text = String(format: "%.0f km/h", currentSpeed * 3.6)
}
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) {
let speedController = segue.destinationViewController as! speedViewController
currentSpeed = manager.location!.speed
speedController.showSpeed = currentSpeedLabel.text
}
}
Second VC
import UIKit
class speedViewController: UIViewController {
#IBOutlet weak var secondSpeedLabel: UILabel!
var showSpeed: String!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
secondSpeedLabel.text = showSpeed
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func back(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Project Link
You could use a Singleton to hold the LocationManager. Then you can access it from all over your app. When you move to a second VC you can either change the delegate to the second VC or just get the needed data manually.
Remember that a delegate can only point to one "receiver". Changing the delegate will stop updates in the first VC. but since it is now a Singleton you can also store information in there about past locations / speeds. When dismissing the second VC get the stored data and update.
This will keep running until you call stop()
The code was simplified a bit to illustrate the idea.
VC Code:
import UIKit
import CoreLocation
class ViewController: UIViewController, TrackerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
Tracker.shared.delegate = self
Tracker.shared.start()
}
func speedUpdate(speed: CLLocationSpeed) {
print(speed)
}
}
Singleton Code:
import UIKit
import MapKit
import CoreLocation
class Tracker: NSObject, CLLocationManagerDelegate {
static var shared = Tracker()
private var manager = CLLocationManager()
private var timer = NSTimer()
var region : MKCoordinateRegion?
var currentSpeed: CLLocationSpeed = CLLocationSpeed()
weak var delegate : TrackerDelegate?
private override init() {
super.init()
manager.delegate = self
manager.requestWhenInUseAuthorization()
}
internal func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
let userLocation: CLLocation = locations[0] as CLLocation
let coordinates2D = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.05, 0.05)
region = MKCoordinateRegion(center: coordinates2D, span: span)
currentSpeed = userLocation.speed
guard let del = delegate else {
return
}
del.speedUpdate(currentSpeed)
}
func start() {
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.startUpdatingLocation()
timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("loopUpdate"), userInfo: nil, repeats: true)
}
func stop() {
timer.invalidate()
}
internal func loopUpdate() {
// restart updating
manager.startUpdatingLocation()
}
}
Delegate for the Singleton:
Add more functions, or more values to the current function to get more feedback.
protocol TrackerDelegate : class {
func speedUpdate(speed:CLLocationSpeed)
}

Trying to unhide UITextView from behind keyboard

I am using the code below to unhide UITextFields. It works great until I try to unhide a UITextView. It crashes with an error of trying to unwrap a nil value. My question is what do I need to implement to make the UITextView unhide like the UITextFields? Or do I need to use something beside a UITextView to allow a paragraph style input?
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var notesInput: UITextView!
#IBOutlet weak var scrollView: UIScrollView!
var activeTextField: UITextField!
// MARK: - View
override func viewDidLoad() {
super.viewDidLoad()
self.textField1.delegate = self
self.textField2.delegate = self
// self.textField3.delegate = self
// self.textField4.delegate = self
// self.textField5.delegate = self
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.registerForKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.unregisterFromKeyboardNotifications()
}
// MARK: - Keyboard
// Call this method somewhere in your view controller setup code.
func registerForKeyboardNotifications() {
let center: NSNotificationCenter = NSNotificationCenter.defaultCenter()
center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func unregisterFromKeyboardNotifications () {
let center: NSNotificationCenter = NSNotificationCenter.defaultCenter()
center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
// Called when the UIKeyboardDidShowNotification is sent.
func keyboardWasShown (notification: NSNotification) {
let info : NSDictionary = notification.userInfo!
let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
var aRect = self.view.frame
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
}
}
// Called when the UIKeyboardWillHideNotification is sent
func keyboardWillBeHidden (notification: NSNotification) {
let contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
// MARK: - Text Field
func textFieldDidBeginEditing(textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
self.activeTextField = nil
}

How do I fix this crash? Xcode 6 Swift

I am only coding in two features. MailComposer and WebView. But when I run my app and go to the email interface tab it crashes "fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)". When I go to the tab that displays the webview, it works fine. The Webview.loadRequest(request) is messing something up with the mail coding. But I don't know where I can put it to make both features work.
If anyone has any clue how to fix this, please let me know. Thanks.
Here is the coding for the View.Controller.Swift file...
import UIKit
import MessageUI
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var Webview: UIWebView!
#IBOutlet weak var Subject: UITextField!
#IBOutlet weak var Body: UITextView!
var URLPath = "http://google.com"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
loadAddressURL()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func SendEmail(sender: AnyObject) {
var SubjectText = "Inquiry:"
SubjectText += Subject.text
var MessageBody = Body
var toRecipients = ["phillip.lebsack1#gmail.com"]
var mc: MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(SubjectText)
mc.setMessageBody(MessageBody.text, isHTML: false)
mc.setToRecipients(toRecipients)
self.presentViewController(mc, animated: true, completion: nil)
}
func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
switch result.value{
case MFMailComposeResultCancelled.value:
NSLog("Mail Cancelled")
case MFMailComposeResultSaved.value:
NSLog("Mail Saved")
case MFMailComposeResultSent.value:
NSLog("Mail Sent")
case MFMailComposeResultFailed.value:
NSLog("Mail Sent Failure: %#",[error.localizedDescription])
default:
break
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func loadAddressURL(){
let requestURL = NSURL(string:URLPath)
let request = NSURLRequest(URL: requestURL!)
Webview.loadRequest(request)
}
}
Make sure no warning message and bind all #IBOutlet in your ViewController.

Resources