Sunday, September 24, 2017

The UIButton is not responsive

I'm new to swift. My view controller has only one button. I added a target for it to handle the TouchUpInside event. It worked at first, but it became unresponsive after I made some changes to the UI. It was just like a UILabel. No matter how many times i clicked on it, nothing happened.

Then, i figured out that it was just my silly mistake. I changed its height to zero by accident, but the button still appeared in both Interface Builder and simulator. This is why I got confused. Unlike UIButton, UILablel does not appear in the simulator if its height is zero.

[LayoutConstraints] Unable to simultaneously satisfy constraints

I'm learning Swift 3 by using Xcode 8 on MacOS Sierra. My view controller has a simple button, and I created two constraints for the top space and bottom space of the button. When I launch the app in Xcode, I got the following log message.

2017-09-24 16:40:23.780953+0700 Learn Swift[31177:1017369] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
    "<_UILayoutSupportConstraint:0x600000090770 _UILayoutGuide:0x7ff359716960.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x60000008eb00 V:|-(0)-[_UILayoutGuide:0x7ff359716960]   (active, names: '|':UIView:0x7ff359715f40 )>",
    "<_UILayoutSupportConstraint:0x6000000906d0 _UILayoutGuide:0x7ff359716b20.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x600000090720 _UILayoutGuide:0x7ff359716b20.bottom == UIView:0x7ff359715f40.bottom   (active)>",
    "<NSLayoutConstraint:0x600000090950 V:[_UILayoutGuide:0x7ff359716960]-(113)-[NextButton]   (active, names: NextButton:0x7ff359716370 )>",
    "<NSLayoutConstraint:0x6000000909a0 V:[NextButton]-(465)-[_UILayoutGuide:0x7ff359716b20]   (active, names: NextButton:0x7ff359716370 )>",
    "<NSLayoutConstraint:0x60800008d430 'UIView-Encapsulated-Layout-Height' UIView:0x7ff359715f40.height == 568   (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000000909a0 V:[NextButton]-(465)-[_UILayoutGuide:0x7ff359716b20]   (active, names: NextButton:0x7ff359716370 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
There is a conflict between the constraints i created and the constraint the system created by default for the button. The height of the view controller's view is only 568 points, which is less than the sum of the button's height (29 points), top space (113 points), and bottom space (465 points). 

According to this page, we should lower the priority of the bottom space constraint (465 points) to 999 so the system will provide the selected bottom space, which is as close as it can while still satisfying the other constraints. 




Tuesday, September 19, 2017

Unable to comment a line of code in Xcode

I'm using Xcode 8.3.3 on MacOS Sierra. I installed accidentally Xcode in ~/Downloads folder, not the Applications folder. I have been using it for a few weeks without any problems. Today, I couldn't comment a line of code. Neither using the shortcut key (command + /) nor opening Editor menu then select Cold Folder and Fold Comment Blocks worked.

I then reinstall Xcode in Applications folder and it worked.

Saturday, September 16, 2017

xcode-select: error: tool 'genstrings' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

I'm using Xcode 8 on MacOS Sierra to develop an iOS application just for learning purpose. I run the command below to create a strings table file for a view controller class but got the error.


genstrings MapViewController.swift

I can't find Xcode in Applications directory. I don't know why as i'm new to it, and I don't want to find out now. However, I accidentally fixed it myself.

1. Open Xcode and go to Xcode preferences by pressing command + ,
2. Select Locations tab and select "Xcode 8.3.3 (8E3004b)" from the "Command Line Tools" combo box.

Thursday, September 14, 2017

My eyes got swollen after staring at Windows 8 on Macbook Pro for a few hours

I'm using Macbook Pro 13'' late 2011. I installed Windows 8 on it several months ago. I hadn't had any problems with my eyes. 

However a few days ago, I watched a movie for a few hours at night and then i went to sleep. When I woke up in the morning, my eyes got swollen. At first, i didn't think staring at my laptop long was the culprit because my eyes had been fine for months. Then, I realized that I accidentally modified the Display profile Color Management settings. 

The cause of the problem is I changed the Device Profile under Windows Color System Defaults section to Apple RGB. Switching it back to sRGB61966-2.1 solved the issue. I couldn't see the difference between those two profiles, but Apple RGB profile did hurt my eyes.





Tuesday, September 12, 2017

My iOS app does not load the UI completely

I'm developing an iOS application using Swift 3 and Xcode 8 on MacOS Sierra. I have one UITabBarController referencing 4 view controller. Here how it looks like in Interface Builder:


The first view controller below is supposed to be loaded as home screen.


But when run the project, it looked like in the image below:


And then, I looked at the Console and saw this message:

2017-09-12 16:07:40.740 Learn Swift[15358:519952] Could not load the "ConvertIcon" image referenced from a nib in the bundle with identifier "com.vathanakmao.iosapp.Learn-Swift"


Solution

It's because I don't have the "ConvertIcon" image so I remove unset the icon for the bar item of that view controller and the view controller's view loaded completely. To unset the icon, open Interface Builder and click on the bar item at the bottom of the controller. Then, open Attributes Inspector and remove the image from the Image textbox under Bar Item section.






Sunday, September 10, 2017

Highlight or annotate your favorite places on the map view using Swift 3

My demo application is for showing how to use annotations on the map view using Swift 3 (and Xcode 8). It's very simple. When you launch the app, it will show a map and the button "My Annotations". When you tap on the button, the map will navigate to your birth place. Tap on it again, it will show my favorite place called "RUPP". The image below shows how the app looks like when your launch it.


Related classes:

- MKMapView: the map view to be shown on the screen
- MKAnnotation: the info about your location such as coordinate and title
- MKAnnotationView: use it to define how the annotation (your location) looks on the map

1. Create a single application in Xcode 


Suppose you already created the application in Xcode. There should be one View Controller in Interface Builder by default.

2. Update ViewController class as following:


import UIKit
import MapKit

class MapViewAnnotationDemoController: UIViewController, MKMapViewDelegate {
    var mapView: MKMapView!
    var myAnnotationsButton: UIButton!
    private var myAnnotations = [MKAnnotation]()
    private var currentAnnotationIndex: Int = 0
    
    override func loadView() {
        mapView = MKMapView()
        mapView.delegate = self
        view = mapView
    }
    
    override func viewDidLoad() {
        initMyAnnotationsButton()
        initMyAnnotations()
    }
    
    private func initMyAnnotationsButton() {
        myAnnotationsButton = UIButton(frame: CGRect(x: 8, y:40, width: 140, height: 20))
        myAnnotationsButton.setTitle("My Annotations", for: UIControlState.normal)
        myAnnotationsButton.backgroundColor = UIColor.green
        myAnnotationsButton.addTarget(self, action: #selector(showMyAnnotations(_:)), for: UIControlEvents.touchUpInside)
        view.addSubview(myAnnotationsButton)
    }
    
    private func initMyAnnotations() {
        let myBirthPlaceAnnotation = MKPointAnnotation()
        myBirthPlaceAnnotation.title = "My Birth Place (title)"
        myBirthPlaceAnnotation.subtitle = "My Birth Place (subtitle)"
        myBirthPlaceAnnotation.coordinate.latitude = 11.5564
        myBirthPlaceAnnotation.coordinate.longitude = 104.9282
        myAnnotations.append(myBirthPlaceAnnotation)
        
        let ruppAnnotation = MKPointAnnotation()
        ruppAnnotation.title = "RUPP (title)"
        ruppAnnotation.subtitle = "RUPP (subtitle)"
        ruppAnnotation.coordinate.latitude = 11.5690
        ruppAnnotation.coordinate.longitude = 104.8907
        myAnnotations.append(ruppAnnotation)
        
        mapView.addAnnotations(myAnnotations)
    }
    
    func showMyAnnotations(_ sender: UIButton) {
        print("\nshowMyAnnotations() called")
        
        if currentAnnotationIndex == myAnnotations.count - 1 {
            currentAnnotationIndex = 0
        } else {
            currentAnnotationIndex += 1
        }
        
        mapView.showAnnotations([myAnnotations[currentAnnotationIndex]], animated: true)
    }
    
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        print("\nmapView(viewFor) called")
        
        let pinAnnotationView = MKPinAnnotationView()
        pinAnnotationView.annotation = annotation
        pinAnnotationView.animatesDrop = true
        return pinAnnotationView
    }

}


In initMyAnnotations() method,  we called mapView.addAnnotations(myAnnotations) method. And the addAnnotations() method calls the mapView(_:MKMapView, viewFor: MKAnnotation) method of the map view's delegate to get the instance of MKAnnotationView so the map view will know how to display the annotation. The delegate is the ViewController class in this case cause it extends MKMapViewDelegate and we set mapView.delegate to self.