EzDevInfo.com

CS193P

Code from CS193P iOS Development Swift Course CS 193P iPhone Application Development

‘CGFloat’ is not convertible to ‘UInt8' and other CGFloat issues with Swift and Xcode 6 beta 4

In case this illuminates the problem, here's the original Objective-C code.

int x = (arc4random()%(int)(self.gameView.bounds.size.width*5)) - (int)self.gameView.bounds.size.width*2;
int y = self.gameView.bounds.size.height;
drop.center = CGPointMake(x, -y);

I started out with this code. Lines 2 and 3 are fine, I'm presenting them for clarity later.

let x = CGFloat(arc4random_uniform(UInt32(self.gameView.bounds.size.width * 5))) - self.gameView.bounds.size.width * 2
let y = self.gameView.bounds.size.height
dropView.center = CGPointMake(x, -y)

In Xcode 6 beta 3, it was necessary to cast the arc4random_uniform UInt32 result to CGFloat in order for the minus and multiplication to work. This doesn't work anymore and the compiler shows an error:

‘CGFloat’ is not convertible to ‘UInt8’

The release notes state:

"CGFloat is now a distinct floating-point type that wraps either a Float on 32-bit architectures or a Double on 64-bit architectures. It provide all of the same comparison and arithmetic operations of Float and Double and may be created using numeric literals. Using CGFloat insulates your code from situations where your code would be !fine for 32-bit but fail when building for 64-bit or vice versa. (17224725)"

Am I just doing something wrong with types? I don't even know how to describe this problem better to submit a bug report to Apple for beta 4. Pretty much every single Swift project I have that does any kind of point or rect manipulation got hit by this issue, so I'm looking for some sanity.


Source: (StackOverflow)

What's the difference between downloadtaskwithrequest and downloadtaskwithurl

I'm watching the Stanford CS193p lecture video. The instructor used both downloadTaskWithRequest: and downloadTaskWithURL: when downloading some photos from Flickr. I'm a bit confused.

I looked up the former in the documentation, which speaks of the NSURLRequest as "An NSURLRequest object that provides the URL, cache policy, request type, body data or body stream, and so on".

I have no idea what "body data" or "body stream" means. It would be fantastic if anyone could help a bit on that, but more important is the problem below.

It seems to me that either method would work just fine according to my experience (which isn't much). I'm intrigued to know what, if any, is the difference between the two, and on which occasions should I pick one over another.


Source: (StackOverflow)

Advertisements

Why UILabel is not initialized?

The code is from Stanford CS193p. I added a NSLog to check it out. The label seems not being initialized. Any idea?

@interface AskerViewController() <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UILabel *questionLabel;
@property (weak, nonatomic) NSString *question;
@end


@implementation AskerViewController
@synthesize questionLabel = _questionLabel;
@synthesize question = _question;


 - (void)setQuestion:(NSString *)question
{
    _question = question;
    self.questionLabel.text = question;
    NSLog(@"label is %@", self.questionLabel);
}

@end

The NSLog result is:

2012-07-31 01:56:45.177 Kitchen Sink[23931:f803] label is (null)

Source: (StackOverflow)

CS193P - Adding cancel button to iOS calculator

I recently started following the online course on iPhone development from Stanford University on iTunes U.

I'm trying to do the homework assignments now for the first couple of lectures. I followed through the walkthrough where I built a basic calculator, but now I'm trying the first assignment and I can't seem to work it out. It's a follows:

Add a “C” button that clears everything (for example, the display in your View, the operand stack in your Model, any state you maintain in your Controller, etc.). Make sure 3 7 C 5 results in 5 showing in the display. You will have to add API to your Model to support this feature.

What API do i need to add?

I tried something like this:

- (IBAction)CancelPressed {
    self.Display.text = 0;
}

I know this is wrong. I need some guidance. Thanks in advance..Sorry if the question is stupid..


Source: (StackOverflow)

iOS - How to pass information from the VIEW to the Controller?

I am fairly new to programming in general, and have been following the CS193p videos on iTunesU. I am currently doing assignment 3, and am having trouble getting a bit of information from the View sent to the View Controller.

I believe I have set up the whole delegation thing correctly, so the question really is to how to get my View Controller to see a bit of information (such as self.bounds.size.width), which is a property that only the View has. Would this involve using self.dataSource? And if so, through what means could I pass this bit of information? My end goal is to have the View Controller perform some transformation to the View's properties, and send it back to the View's drawRect so that it could be drawn.

Thanks!!

** Edit, as requested, I have posted parts of my drawRect code below

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat scale = 32;

    CGPoint midPoint;
    midPoint.x = self.bounds.origin.x + self.bounds.size.width/2;
    midPoint.y = self.bounds.origin.y + self.bounds.size.height/2;

    // ---- finding the y starting point

    float totalXsInWidth;
    totalXsInWidth = self.bounds.size.width / scale;

    float leftMostX = totalXsInWidth / -2;
    float graphResultY = sin(leftMostX); // ** in theory, I want "leftMostX" to be modifed by the equation entered (in the CONTROLLER)
    NSLog(@"The leftMostX is %f", leftMostX);

    [self.dataSource passingVariable:leftMostX]; //** Here I pass the variable from drawRect to get modifyed in the CONTROLLER

    float graphResultY1;

    graphResultY1 = 5; //this is a test, I want to see if the controller actually effect a change
    graphResultY1 = [self.dataSource calcResult:self]; //this should now be a different number than 5 or 0 (the init value)

    NSLog(@"From graphingview, the result is %f", graphResultY1); //** unfortunately = 0... :(

Source: (StackOverflow)

UIActivityIndicatorView Never Animates

I have a PhotoViewController class with an @property UIActivityIndicatorView* spinner. FlickrPhotoViewController is a subclass of PhotoViewController that downloads a photo from Flickr and tells the spinner when to start and stop animating. 'updatePhoto' is called every time the view controller is given a Flickr photo:

- (void)updatePhoto { // Download photo and set it
    NSLog("updatePhoto called");
    if (self.spinner) NSLog(@"Spinner exists in updatePhoto");
    dispatch_queue_t downloadQueue = dispatch_queue_create("downloader",
                                                           NULL);
    [self.spinner startAnimating];

    dispatch_async(downloadQueue, ^{
        // Download the photo
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.spinner stopAnimating];
            // Set the photo in the UI
            }
        });
    });
}

The above methodology is exactly what I use for displaying a spinning wheel in my table view controllers while the table contents download, and it always works there.

You will notice at the beginning of updatePhoto I print a message if the UIActivityIndicatorView exists. I put a similar statement in awakeFromNib, viewDidLoad, and viewWillAppear. When I run it, this is the exact output I get:

2013-01-31 21:30:55.211 FlickrExplorer[1878:c07] updatePhoto called
2013-01-31 21:30:55.222 FlickrExplorer[1878:c07] Spinner exists in viewDidLoad
2013-01-31 21:30:55.223 FlickrExplorer[1878:c07] Spinner exists in viewWillAppear

Why does spinner not exist in awakeFromNib? Docs indicate that "When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established." Can an IBOutlet be connected without the existence of the object it is connecting to? In this case, can the spinner IBOutlet be connected to the storyboard without spinner being allocated?

Moving beyond this, I overrode the getter for spinner so that it would instantiate if it does not exist. As a result, the printing output now looks like this:

2013-01-31 21:48:45.646 FlickrExplorer[2222:c07] Spinner exists in awakeFromNib
2013-01-31 21:48:45.647 FlickrExplorer[2222:c07] updatePhoto called
2013-01-31 21:48:45.647 FlickrExplorer[2222:c07] Spinner exists in updatePhoto
2013-01-31 21:48:45.649 FlickrExplorer[2222:c07] Spinner exists in viewDidLoad
2013-01-31 21:48:45.650 FlickrExplorer[2222:c07] Spinner exists in viewWillAppear

This is what I would have expected to see earlier. Nevertheless, I still do not get any animation.

Possible problems that I have ruled out:

All three of these possibilities are ruled out by the fact that putting [self.spinner startAnimating]; in viewWillAppear makes it successfully animate throughout the download process.

You can download this project if you like. Just go to any screen that attempts to display a large photo and you will see that the spinner does not appear. There are many problems with this project, but this is the one I am focusing on now.

Edit 1:

  • I added the project's missing dependencies on Git, so the project will now compile for you

Edit 2 (2 February 2013):

  • I am seeing this problem only on the iPhone when the updatePhoto method is called due to another view controller's prepareForSegue setting the photo in the FlickrPhotoViewController. Is it possible that this contributes to the problem?

Source: (StackOverflow)

Is there a shortcut to get to the /Resources/ folder in iPhone development?

Is there a shortcut method much like NSHomeDirectory() and NSTemporaryDirectory to get to the resources folder within your project?

Is the /resources/ folder the best place to be storing a file?


Source: (StackOverflow)

How do I align a button under a label in Xcode 6?

I'm watching Stanford's cs193p lectures with iTunes U and the first demo has been a calculator. In the second lecture, the professor aligns the buttons with the bottom edge of the display label using a black grid line that appears. How do I enable this grid line, so I know that my buttons are directly below the label?


Source: (StackOverflow)

converting Objective-C lazy instantiation with side effects to Swift

I converted the Objective-C app Dropit from the Stanford CS193P course to Swift. The original code is located at:

http://web.stanford.edu/class/cs193p/cgi-bin/drupal/

There are multiple uses of lazy instantiation that perform additional initialization or cause some other side effect. My conversion to Swift is working, but I'm not sure that it is the proper solution or whether this kind of Objective-C coding should be avoided entirely? The first examples just set some properties as part of the lazy instantiation.

- (UIGravityBehavior *)gravity
{
    if (!_gravity) {
        _gravity = [[UIGravityBehavior alloc] init];
        _gravity.magnitude = 0.9;
    }
    return _gravity;
}

- (UICollisionBehavior *)collider
{
    if (!_collider) {
        _collider = [[UICollisionBehavior alloc] init];
        _collider.translatesReferenceBoundsIntoBoundary = YES;
    }
    return _collider;
}

My Swift version:

@lazy var gravity: UIGravityBehavior = {
    var tempGravity = UIGravityBehavior()
    tempGravity.magnitude = 0.9
    return tempGravity
    }()
@lazy var collider: UICollisionBehavior = {
    var tempCollider = UICollisionBehavior()
    tempCollider.translatesReferenceBoundsIntoBoundary = true
    return tempCollider
    }()

Is there a cleaner way of doing that initialization in Swift?

The ViewController of the Objective-C for the second example is a bit more involved:

@interface DropitViewController () <UIDynamicAnimatorDelegate>
@property (weak, nonatomic) IBOutlet UIView *gameView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (strong, nonatomic) DropitBehavior *dropitBehavior;
@end

@implementation DropitViewController

static const CGSize DROP_SIZE = { 40, 40 };

- (DropitBehavior *)dropitBehavior
{
    if (!_dropitBehavior) {
        _dropitBehavior = [[DropitBehavior alloc] init];
        [self.animator addBehavior:_dropitBehavior];
    }
    return _dropitBehavior;
}

- (UIDynamicAnimator *)animator
{
    if (!_animator) {
        _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.gameView];
        _animator.delegate = self;
    }
    return _animator;
}

In Swift:

class ViewController: UIViewController, UIDynamicAnimatorDelegate {
    @IBOutlet var gameView: UIView

    let DROP_SIZE = CGSize(width: 40.0, height: 40.0)

    // lazy instantiation with closures
    @lazy var animator: UIDynamicAnimator = {
        var tempAnimator = UIDynamicAnimator(referenceView: self.gameView)
        tempAnimator.delegate = self
        return tempAnimator
    }()
    @lazy var dropitBehavior: DropitBehavior = {
        var tempBehavior = DropitBehavior()
        // side effect...
        self.animator.addBehavior(tempBehavior)
        return tempBehavior
    }()

The way the program was designed, during the lazy initialization of dropitBehavior is when animator is created for the first time and then dropitBehavior is added to the animator. This can be verified with println, in the debugger, etc.

Note that there is a related question: Lazy instantiating a UIDynamicAnimator with referenceView - Swift

However, the suggested solution appears to be avoid @lazy, use optionals and move the work into viewDidLoad which doesn't seem that great either.

There is a lot of Objective-C code out there like this to translate, so I would like to learn the proper way to do this in Swift.


Source: (StackOverflow)

NSdata writeToURL not working

i'm trying to save a NsData file into a directory. that is the code of my method:

- (void)cacheImage:(NSData *)imageData withTitle:(NSString *)title
{

    NSURL *cacheURL = (NSURL *)[[self.fileMenager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0]; //we take the URL of the cache Directory and comvert the url of the cache directory into a string
    NSURL *imageFolder = [cacheURL URLByAppendingPathComponent:PHOTO_CACHE_FOLDER];

    if ([self.fileMenager isWritableFileAtPath:[cacheURL path]]) { //check if the cache directory is writable
        if (![self.fileMenager createDirectoryAtURL:cacheURL withIntermediateDirectories:NO attributes:nil error:nil]) { //check if the directory of our image is already exist
            NSURL * fileToWrite = [[imageFolder URLByAppendingPathComponent:title isDirectory:NO] URLByAppendingPathExtension:@"jpg"]; //take the complete url of image
            if ([imageData writeToURL:fileToWrite atomically:YES]) //atomically = safe write
            {
                NSArray *debug = [self.fileMenager contentsOfDirectoryAtPath:[imageFolder path] error:nil];
                for (NSURL *url in debug)
                    NSLog(@"url prooooo : %@",url);
            }
        }
    }
}

that is an example of url (fileToWrite) where i try to write:

file://localhost/Users/MarcoMignano/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/93B0A0AC-EC13-4050-88CA-F46FBA11001E/Library/Caches/image_cache/Mozart%201.jpg

the point is simple, the method writeToURL return NO, i can't understand why, the url looks correct.

somebody can help my' thank you.


Source: (StackOverflow)

Passing object from controller to a view

I'm following iPhone dev courses from Stanford Open-University, and I've been blocked for 2 days on assignment3, maybe someone can help me here?

The tasks are:

  1. Create a custom UIView subclass that will display your PolygonShape object
  2. Give your view class access to the PolygonShape object so that it can retrieve the details of the polygon as needed

The problem is: how do I give my view class access to the polygon object defined in my controller?

Here is my implementations if it can help:

CustomView.h:

#import "PolygonShape.h"

@interface CustomView : UIView {
    IBOutlet PolygonShape *polygon;
}
- (NSArray *)pointsForPolygonInRect:(CGRect)rect numberOfSides:(int)numberOfSides;

@end

Controller.h:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "PolygonShape.h"
#import "PolygonView.h"

@interface Controller : NSObject {
    IBOutlet UIButton *decreaseButton;
    IBOutlet UIButton *increaseButton;
    IBOutlet UILabel *numberOfSidesLabel;
    IBOutlet PolygonShape *polygon;
    IBOutlet PolygonView *polygonView;
}
- (IBAction)decrease;
- (IBAction)increase;
- (void)awakeFromNib;
- (void)updateInterface;
@end

Source: (StackOverflow)

EXC_BAD_ACCESS upon simple iPhone app startup

Background:

I'm trying out the "HelloPoly" assignment in the CS193P course. I've created my .xib file, and a custom Controller class.

I haven't fleshed out any methods - I've only allowed IB to write the class files into xcode.

Problem:

Every single time I startup the application, it bombs out. When I run gdb I see it's an EXC_BAD_ACCESS error. This means I'm accessing something non-existent in memory right? Thing is, all I have is the default files created by IB and the main. Nothing more.

I've checked posted code solutions to see what's different and I'm not sure what to try next. What do you guys usually check for when your app crashes every time on startup?

The stack trace reveals it's happening in main.m when creating UIApplicationMain - meaning I never make it to my application delegate.

Here's the trace:

Program received signal:  “EXC_BAD_ACCESS”.
(gdb) where
#0  0x01b70d45 in CFHash ()
#1  0x01b741cf in __CFDictionaryFindBuckets1b ()
#2  0x01b72b0a in CFDictionaryGetValue ()
#3  0x00450535 in -[UIProxyObject initWithCoder:] ()
#4  0x0133886e in UINibDecoderDecodeObjectForValue ()
#5  0x013398c2 in -[UINibDecoder decodeObjectForKey:] ()
#6  0x00450b35 in -[UIRuntimeConnection initWithCoder:] ()
#7  0x0045101c in -[UIRuntimeEventConnection initWithCoder:] ()
#8  0x0133886e in UINibDecoderDecodeObjectForValue ()
#9  0x0133820a in UINibDecoderDecodeObjectForValue ()
#10 0x013398c2 in -[UINibDecoder decodeObjectForKey:] ()
#11 0x0044feab in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:] ()
#12 0x00451fcb in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:] ()
#13 0x002910a6 in -[UIApplication _loadMainNibFile] ()
#14 0x0029a82a in -[UIApplication _runWithURL:sourceBundleID:] ()
#15 0x00297b88 in -[UIApplication handleEvent:withNewEvent:] ()
#16 0x002936d3 in -[UIApplication sendEvent:] ()
#17 0x0029a0b5 in _UIApplicationHandleEvent ()
#18 0x0239eef1 in PurpleEventCallback ()
#19 0x01bb2b80 in CFRunLoopRunSpecific ()
#20 0x01bb1c48 in CFRunLoopRunInMode ()
#21 0x00291e69 in -[UIApplication _run] ()
#22 0x0029b003 in UIApplicationMain ()
#23 0x000026a8 in main (argc=1, argv=0xbffff000) at main.m:14

I didn't see this particular problem in other threads, but please clue me in if I missed them.

Ideas?

Thanks.


Source: (StackOverflow)

prepareForDeletion being called once when I call deleteObject: and a second time when I save

edited with extra information: I am using an app based on CoreDataTableViewController from cs193p. When I delete an instance of an entity called Position, the prepareForDeletion is called immediately. But when I call saveToURL, or when the database is being autosaved, prepareForDeletion is called again.

Is this the way it should be? can I prevent it?


Source: (StackOverflow)

Stanford CS193p Assignment 2 - Entering variables into RPN calculator

I am currently teaching myself iPhone programming and working on solving assignment 2 [PDF] of this year Stanford CS193p course.

There's something I don't understand about Required Task 1. One is supposed to add variable support to RPN calculator so that it could be programmed. However, what is the presumed way for someone to use this feature? That is:

  • What sequence of calculator buttons should set a variable?
  • How should the user run a predefined calculator program with predefined values of variables?

Note that there is no "store" or "run" buttons in screenshot at page 5.


Source: (StackOverflow)

Why does this NSUserDefaults key contain a dot?

I'm watching the lesson of standford CS193P, in particular the lecture n°7. I have some doubts about NSUserDefaults. This is the part of code :

#define FAVORITES_KEY @"CalculatorGraphViewController.Favorites"

- (IBAction)addToFavorites:(id)sender
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSMutableArray *favorites = [[defaults objectForKey:FAVORITES_KEY] mutableCopy];
    if (!favorites) favorites = [NSMutableArray array];
    [favorites addObject:self.calculatorProgram];
    [defaults setObject:favorites forKey:FAVORITES_KEY];
    [defaults synchronize];
}

I read the documentation about NSUserDefaults, but I don't understand this code in particular [[defaults objectForKey:FAVORITES_KEY] mutableCopy]. FAVORITES_KEY is @"CalculatorGraphViewController.Favorites".

My question is why I should should use CalculatorGraphViewController.Favorites? I don't understand the dot! It seems to me that a structure of getter or setter but Favorites have a capital letter and then CalculatorGraphViewController.Favorites doesn't make sense.

Can You help me please?


Source: (StackOverflow)