Documenting In Xcode

Using Xcode’s comment indicators and inline documentation feature has some wonderful benefits to every Apple developer. So, I created a presentation to do a talk on it. Even if you did not make the event, the slides have samples and details that are easy to reference.

I’m posting the Keynote presentation for our Cocoaheads meeting. Thanks for coming!

Posted in Uncategorized

iOS Remote Notifications – What is Error 400 Topic Disallowed?

In setting up remote (push) notifications for iOS today, our manual server post to APNs was an error 400 Topic Disallowed, explained as “Pushing to this topic is not allowed.” in the Apple docs. NOT helpful. What is the topic? It’s the AppID!

The Apple Developer Portal stuff was fine, even though it said configurable. We were NOT using the old SSL method in iOS 9.

In our case, we had two App IDs, demo.baconinc (demo app), and another with was com.baconinc.bacon (production). In the Xcode project, it was still using demo, instead of the official App ID. Switched it, ran the app again, because you need to register again, and we got a good authorization token for the server to use.

So, if you have this error, take a look at your project App ID. That might be your topic error.

Posted in Uncategorized

Data Design In Core Data

For those who wanted the slides from my presentation at Cocoaheads, the slide deck is in Keynote format, and is available here.

I added some additional clarifications based on feedback from the attendees. Thanks for coming!

Posted in Uncategorized

Formatting a Samsung T5 SSD to APFS

When buying an SSD, the last thing I want to do is use FAT32, I want to just use APFS, because I’m only using Apple devices. I’ve done this twice now, and it works fine, but it’s not as straightforward as many web postings make it out to be. So, I’m posting this as a step-by-step.

Open Disk Utility. Make sure in the upper left, the View button, choose Show All Devices. Now you can see to erase the default drive. Feel free. Notice you don’t have any APFS choices. How do we get those?

Next, you need to use Terminal. This is the hard part, but well worth it. It’s not too bad.

Type:

diskutil list

This will give you a list, like this:

/dev/disk0 (internal):

   #:                       TYPE NAME                    SIZE       IDENTIFIER

   0:      GUID_partition_scheme                         1.0 TB     disk0

   1:                        EFI EFI                     314.6 MB   disk0s1

   2:                 Apple_APFS Container disk1         1.0 TB     disk0s2

/dev/disk1 (synthesized):

   #:                       TYPE NAME                    SIZE       IDENTIFIER

   0:      APFS Container Scheme –                      +1.0 TB     disk1

                                 Physical Store disk0s2

   1:                APFS Volume Cambeo                  197.4 GB   disk1s1

   2:                APFS Volume Preboot                 19.0 MB    disk1s2

   3:                APFS Volume Recovery                517.8 MB   disk1s3

   4:                APFS Volume VM                      1.1 GB     disk1s4

/dev/disk2 (external, physical):

   #:                       TYPE NAME                    SIZE       IDENTIFIER

   0:     FDisk_partition_scheme                        *1.0 TB     disk2

   1:                  Apple_HFS MyT5                1.0 TB     disk2s1

 

Notice the last one is my external, and that’s the T5. In this case, it’s disk2. Note which disk number it is. I recommend you disconnect any other external drives to avoid confusion. Once you do this, it can’t be undone, so be careful.

Now type, replacing the “#” with your disk number, like “disk2”, like so:

diskutil partitionDisk /dev/disk# GPT JHFS+ New 0b

It will do it’s magic. Should only be a few seconds, maybe ten.

When that’s done, you can go into Disk Utility, and select the new device. It will say it’s a Container Disk, with a number. If you select it, you can now see the SSD is APFS. Now when you choose erase, the drop-down choice includes all the APFS options you didn’t have before. That’s it!

Posted in Uncategorized

Animating Polygon Shape Changes With CAShapeLayer in Swift and iOS

I am working on a project that will be animating polygon vector shapes. No raster images on a CAShapeLayer. In general, most of the references and examples related to CAShapeLayer are concentrated on animating stroke end points. That’s great for progress shapes where you are animating out the stroke, but what about simply going from one shape to another? How about in Swift?

Project and storyboard

Create a simple swift project. Place a view and a button on it. Set an IBOutlet for the view as shapeView, and an IBAction for the button. If you are impatient, you can download the demo project.

Create the objects

var shape1: UIBezierPath?
var shape2: UIBezierPath?
var isOpen: Bool = false
var shapeLayer = CAShapeLayer()

We’re going to animate from shape1 (a small polygon) to shape2 (a larger polygon), where the shapes are not the same.  The state between larger and smaller is kept by isOpen.

Start drawing

Let’s do some polygon shapes, and return a path.


func smallOpening() -> UIBezierPath {
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 35.5, y: 49.5))
bezierPath.addLine(to: CGPoint(x: 41.5, y: 42.5))
bezierPath.addLine(to: CGPoint(x: 47.5, y: 42.5))
bezierPath.addLine(to: CGPoint(x: 47.5, y: 42.5))
bezierPath.addLine(to: CGPoint(x: 59.5, y: 49.5))
bezierPath.addLine(to: CGPoint(x: 66.5, y: 57.5))
bezierPath.addLine(to: CGPoint(x: 59.5, y: 57.5))
bezierPath.addLine(to: CGPoint(x: 47.5, y: 63.5))
bezierPath.addLine(to: CGPoint(x: 35.5, y: 57.5))
bezierPath.addLine(to: CGPoint(x: 35.5, y: 49.5))
bezierPath.addLine(to: CGPoint(x: 35.5, y: 49.5))
bezierPath.close()
UIColor.gray.setFill()
bezierPath.fill()
UIColor.black.setStroke()
bezierPath.lineWidth = 1
bezierPath.stroke()
return bezierPath
}



func largeOpening() -> UIBezierPath {
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 8.5, y: 82.5))
bezierPath.addLine(to: CGPoint(x: 15.5, y: 51.5))
bezierPath.addLine(to: CGPoint(x: 32.5, y: 21.5))
bezierPath.addLine(to: CGPoint(x: 51.5, y: 11.5))
bezierPath.addLine(to: CGPoint(x: 69.5, y: 21.5))
bezierPath.addLine(to: CGPoint(x: 82.5, y: 41.5))
bezierPath.addLine(to: CGPoint(x: 82.5, y: 64.5))
bezierPath.addLine(to: CGPoint(x: 87.5, y: 82.5))
bezierPath.addLine(to: CGPoint(x: 51.5, y: 91.5))
bezierPath.addLine(to: CGPoint(x: 8.5, y: 82.5))
bezierPath.addLine(to: CGPoint(x: 8.5, y: 82.5))
bezierPath.addLine(to: CGPoint(x: 8.5, y: 82.5))
bezierPath.close()
UIColor.gray.setFill()
bezierPath.fill()
UIColor.black.setStroke()
bezierPath.lineWidth = 1
bezierPath.stroke()
return bezierPath
}

Start animating

Now that we have shapes, let’s animate them from one to the other using CABasicAnimation, and changing the whole path.


func openShape() {
let contractionAnimation = CABasicAnimation(keyPath: "path" )
contractionAnimation.fromValue = shape1?.cgPath
contractionAnimation.toValue = shape2?.cgPath
contractionAnimation.duration = 5.0
contractionAnimation.fillMode = kCAFillModeForwards
contractionAnimation.isRemovedOnCompletion = false
shapeLayer.add(contractionAnimation, forKey: "path" )
isOpen = true
}



func closeShape() {
let contractionAnimation = CABasicAnimation(keyPath: "path" )
contractionAnimation.fromValue = shape2?.cgPath
contractionAnimation.toValue = shape1?.cgPath
contractionAnimation.duration = 5.0
contractionAnimation.fillMode = kCAFillModeForwards
contractionAnimation.isRemovedOnCompletion = false
shapeLayer.add(contractionAnimation, forKey: "path" )
isOpen = false
}

We are animating from one path to the other, using the path key. We can change our path using fromValue and toValue. Set a duration. We want the animation to stay in place when it’s done, which is our isRemovedOnCompletion property. Set the state, so we know if we are open (bigger) or closed (smaller).

Load them up

Here we are creating our paths. A CAShapeLayer is all about the path, so we assign the smaller path to the it. Then we add  the CAShapeLayer to the view layer (which is a CALayer).


override func viewDidLoad() {
super.viewDidLoad()
shape1 = smallOpening()
shape2 = largeOpening()
if let smallShape = shape1 {
shapeLayer.path = smallShape.cgPath
shapeLayer.fillColor = UIColor.gray.cgColor
shapeLayer.strokeColor = UIColor.black.cgColor
shapeView.layer.addSublayer(shapeLayer)
}
}

 

Connect the button

Standard iOS stuff, let’s toggle the animations based on our isOpen state.


@IBAction func toggle(_ sender: Any) {
if isOpen {
closeShape()
} else {
openShape()
}
}

Conclusion

This is a relatively small amount of code for this effect. Keep in mind that this is applied to a view. If you want to have views layered on top of one another to respect the shape edges, you’ll need to make the background color clear. Adding the sublayer will show your shape without the square of the view. Again, you can download the demo project.

Posted in iOS

Where In The World Have I Been?

I’ve really neglected my website. My choice, but I want to reverse that now. I’m going to try to start posting again. A lot of things have changed for me lately, as far as my career.

Demands On Time By Startups

The reasons for not posting are mainly related to my work, and my last two employers. The demands of a startup, and the crazy hours they often want, have some rather negative effects on things like blogs and public presentations. Both of these things which I have a lot of experience in, have become very rare. Given that I also like to take a lot of time to prepare a really good presentation, it becomes a time crunch. I had to pay the bills. Fortunately, that’s not an issue with my current employer, which is great!

Adobe

First, I am no longer an Adobe User Group Manager. I turned those reigns over to someone else. Unfortunately, the group did not survive a year after. I was able to stay as an Adobe Community Professional for a while. I did two presentations I think, early on, but my time got heavily compromised, so I’m no longer officially affiliated with Adobe. I still love Adobe, but I just couldn’t set aside the time to meet my commitments. Having the content of my presentation materials online was a major reason for my blogging activity, so when that went away, so did the entries.

The Pleasure And Pain Of A Blog

I enjoy it when I’ve helped someone learn something, made a bunch of samples available, or published a fix to something truly obscure. I like giving back to the community. It’s fun to be quoted elsewhere. But…

I had a colleague of mine, who recently was let go from his job for criticizing Agile programming online. He didn’t mention any names or companies or people. He referenced other blog articles, and got fired. Naturally, this would have a chilling effect on what I’m going to say here, as historical record. While I have no doubt my current employer doesn’t care what I post, I can’t get it out of my head that someone would gladly disqualify me over a stupid blog post from the past. It’s a real thing.

What Did I Learn?

I have learned that I can get a job just fine. iOS is in demand, and that’s not changing anytime soon. I have a  better understanding of how I will fit or not fit, or how happy I would be, or how well I’d be utilized, better than I every have. This last time I made myself quietly available by word of mouth, and had two or three interviews (on phone or in person) every day for the next six days. That was exhausting. Things worked out great for me.

There’s a lot more, but, remember that part above about the pain?

What’s Next?

Predictions, advice, product reviews, and technical material. I have been pretty good at predicting what will stick and what won’t. There are some things I love, but recognize they are not ready yet. I’ve been helping many juniors try to get that first or second job. I need to do more to promote the products I love, and why I love them. And I’ll start posting presentations again, as I start doing those with more regularity.

Posted in Personal

Winter Effects in Photoshop CC

CC_PhotoshopA year ago, I presented on making it snow in a Photoshop video. I’ve found the original keynote and PDF for downloading. Enjoy!

Posted in Uncategorized

Let It Snow In Adobe After Effects CC

Adobe-After-Effects-CC-2014I’ll be presenting at the SLC Adobe Video Users Group in Draper on Wednesday, February 18th, at The Art Institute of Salt Lake City located at 121 W. Election Road Draper Utah. We’ll start at 6:30PM.

Feel free to download the source files and the keynote or you can download the PDF.

Posted in Uncategorized

iOS Tutorial: Selections in TableViews

This tutorial picks up where our last tutorial on TableView Basics left off. Now that we have one, it’s time to start editing, deleting and moving things around. Again, we’ll have our starter project and our completed project downloads.

First off, we can lose the button off the cell. Go to the storyboard and delete it. Delete the button code we had in the delegate method in RootViewController.m:

– (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPathSmilie: :(NSIndexPath *)indexPath

{

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@”tvcItems”];

UILabel *lblName = (UILabel *)[cell viewWithTag:100];

[lblName setText:[maTheData objectAtIndex: [indexPath row]]];

return cell;

}

Table View Styles

We’re going to go into our storyboard and play with some attributes to explore what we can make the UITableView look like, and act. First, select the table view, and go to the Attributes Inspector. Change the table view style to Grouped. Run the project again. This looks a lot like Apple’s Settings app.

Apple’s documentation has some guides to read more about tables, including styles making indexed lists and creating sections. This is also available from Xcode->Organizer-Documentation.

Selecting Cells

In order to edit a cell, you first must be able to select a row and have it mean something. When we run our project and click a cell, it simply turns blue and stays that way. Change the selection attribute to Multiple Selection, and run again. Now as you select, they all go blue. This is certainly okay, but a lot of people prefer checkboxes to indicate selections, without anything going blue. To do this, we change the cell style, and deselect the cell. Really, no kidding.

For this we have another UITableView delegate method called didSelectRowAtIndexPath:

– (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {

UITableViewCell *tvc = [tableView cellForRowAtIndexPath:indexPath];

if ([tvc accessoryType] == UITableViewCellAccessoryCheckmark) {

[tvc setAccessoryType:UITableViewCellAccessoryNone];

} else {

[tvc setAccessoryType:UITableViewCellAccessoryCheckmark];

}

[tvc setSelected:NO];

}

Run the project, and notice that we are toggling the checkmark, and deselecting, which turns off our blue.

Posted in Apple, iOS

What’s New in Photoshop Creative Cloud

Photoshop_CC_totem_5in_300ppiThe resource files for the SLC Adobe User Group are available for download.

We’ll cover most of the image editing enhancements, including blur gallery, smart sharpen, liquify, and up sampling. We’ll also show how to use CSS copy exports for use with Dreamweaver. We’ll cover a lot of the new light enhancements and image-based lighting (IBL) that have been added. Lastly, we’ll do some direct texture painting on a 3D model.

For information about the group and where to see the presentation, go to the site.

Posted in Adobe Tagged , ,