What libraries do we need to include to use CGPoint and arc4random()? - ios

It's my first program in Swift.
The function returns two random locations (CGPoints) which are points on the perimeter of a circle of radius = variable (passed in by the calling program).
The two CGPoints must also be greater than degreesApart around the perimeter of the circle.
I have written the following code:
func returnPerimeterPoints (radius: Int, degreesApart: Int) -> (CGPoint, CGPoint) {
var perimeterPoint1 = CGPoint(x:Int(arc4random()%radius),y:Int(arc4random()%radius))
var perimeterPoint2 = CGPoint(x:Int(arc4random()%radius),y:Int(arc4random()%radius))
return (perimeterPoint1, perimeterPoint2)
}
print(returnPerimeterPoints(20, 24))
I have received the following errors:
cannot find 'CGPoint' in scope
cannot find 'arc4random' in scope
What libraries do i need to include and what can i do to get the CGPoints like i mentioned in the first paragraph?

CGPoint is defined in CoreGraphics, but will also be imported by default when importing a UI library like UIKit or SwiftUI.
arc4random in part of Darwin (the kernel) but, again, will be imported automatically when you import an Apple framework that depends on it, like Foundation or even CoreGraphics as well.
import CoreGraphics
// ... your code here

Related

How to use swift categories in objective-c project?

I got a swift category for UIImage, but I can't figure out how to make it work.
This is the swift category i'm trying to use:
import UIKit
extension UIImage {
func imageWithColor(color1: UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
color1.setFill()
let context = UIGraphicsGetCurrentContext()! as CGContextRef
CGContextTranslateCTM(context, 0, self.size.height)
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, CGBlendMode.Normal)
let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
CGContextClipToMask(context, rect, self.CGImage)
CGContextFillRect(context, rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage
UIGraphicsEndImageContext()
return newImage
}
}
In my objective C View Controller code I Tried to import:
#import "UIImage+Overlay.swift"
And xcode gives me a lot of errors, it's looks like Objective C errors. It seems it doesn't understand swift code.
Errors:
unexpected '#' in program when I declare the first property:
#property (nonatomic, strong) NSArray *contentImages;
As suggested by Leo Natan, I did try to import, but I think is because the name of my App. I did try all this kind of import, but still saying can't find it.
#import <ProductName/ProductModuleName-Swift.h>
#import <Say_Cheese_/Say_Cheese_-Swift.h>
#import <Say Cheese!/Say_Cheese_-Swift.h>
#import <Say Cheese!-Say_Cheese_-Swift.h>
#import <Say Cheese!-Bridging-Header.h>
My Product Name is "Say Cheese!"
My Product Module Name is Say_Cheese_, but behind is $(PRODUCT_NAME:c99extidentifier)
I'm afraid to change the Product Module Name, is it safe?
Do not import the Swift file. Instead, import the compiler generated "ProductModuleName-Swift.h" file.
Importing Swift into Objective-C
When you import Swift code into Objective-C, you rely on an
Xcode-generated header file to expose those files to Objective-C. This
automatically generated file is an Objective-C header that declares
the Swift interfaces in your target. It can be thought of as an
umbrella header for your Swift code. The name of this header is your
product module name followed by adding "-Swift.h". (You’ll learn more
about the product module name later, in Naming Your Product Module.)
By default, the generated header contains interfaces for Swift
declarations marked with the public modifier. It also contains those
marked with the internal modifier if your app target has an
Objective-C bridging header. Declarations marked with the private
modifier do not appear in the generated header. Private declarations
are not exposed to Objective-C unless they are explicitly marked with
#IBAction, #IBOutlet, or #objc as well. If your app target is compiled
with testing enabled, a unit test target can access any declaration
with the internal modifier as if they were declared with the public
modifier by prepending #testable to the product module import
statement.
You don’t need to do anything special to create the generated header
file—just import it to use its contents in your Objective-C code. Note
that the Swift interfaces in the generated header include references
to all of the Objective-C types used in them. If you use your own
Objective-C types in your Swift code, make sure to import the
Objective-C headers for those types before importing the Swift
generated header into the Objective-C .m file you want to access the
Swift code from.
In your project's target, find the product module name. Usually, it has the same name as the target. This will be the name of the compiler generated header file.
In your Objective C source file, import this header.
#import <ProductModuleName-Swift.h>
This header file is generated every time you build your project, so any changes to Swift files will require a compilation before being able to use in Objective C.
I got some tips at this link:
How to import Swift code to Objective-C
But to solve this, I did use "" instead <> on #import
#import "SayCheese-Swift.h"
and then I define the Product Module Name to "SayCheese" without special chars and spaces.
Thanks Leo.

How to have multiple definitions for a function in swift [duplicate]

I am starting to learn Swift, and have been following the very good Stanford University video lectures on YouTube. Here is a link if you are interested or it helps (although it isn't required to understand my problem):
Developing iOS 8 Apps with Swift - 2. More Xcode and Swift, MVC
While following the lectures I got to a point where (as far as I could tell) my code was identical to the code in the video but on my system I got a compiler error. After a lot of trial and error I have managed to reduce my code to two examples, one of which generates an error, the other or which doesn't, but I have no idea what is actually causing the error or how to resolve it.
The code which creates the error is:
import UIKit
class BugViewController: UIViewController
{
func perform(operation: (Double) -> Double) {
}
func perform(operation: (Double, Double) -> Double) {
}
}
This creates the following compiler error:
Method 'perform' with Objective-C selector 'perform: ' conflicts with previous declaration with the same Objective-C selector
By simply removing the sub-classing of UIViewController the code compiles:
import UIKit
class BugViewController
{
func perform(operation: (Double) -> Double) {
}
func perform(operation: (Double, Double) -> Double) {
}
}
Some other information which may or may not be relevant:
I have recently upgraded to Yosemite.
When I installed Xcode, I ended up with a Beta version (Version 6.3 (6D543q)) because (if I remember correctly) this was the version I needed to run on my version of OS X.
I am half hoping this is a bug in the compiler because otherwise this doesn't make any sense to me. Any help very gratefully received!
I myself am also taking the Standford course and I got stuck here for a long time too, but after some searching, I found something from here: Xcode release notes and it mentioned something below:
Swift 1.2 is strict about checking type-based overloading of #objc
methods and initializers, something not supported by Objective-C.
// Has the Objective-C selector "performOperation:".
func performOperation(op: NSOperation) { /* do something */ }
// Also has the selector "performOperation:".
func performOperation(fn: () -> Void) {
self.performOperation(NSBlockOperation(block: fn))
}
This code would work when invoked from Swift, but could easily crash
if invoked from Objective-C. To solve this problem, use a type that is
not supported by Objective-C to prevent the Swift compiler from
exposing the member to the Objective-C runtime:
If it makes sense, mark the member as private to disable inference of #objc.
Otherwise, use a dummy parameter with a default value, for
example: _ nonobjc: () = (). (19826275)
Overrides of methods exposed
to Objective-C in private subclasses are not inferred to be #objc,
causing the Swift compiler to crash. Explicitly add the #objc
attribute to any such overriding methods. (19935352)
Symbols from SDKs are not available when using Open Quickly in a
project or workspace that uses Swift. (20349540)
what i did was just adding "private" in front of the override method like this:
private func performOperation(operation: Double -> Double) {
if operandStack.count >= 1 {
displayValue = operation(operandStack.removeLast())
enter()
}
}
Objective-C does not support method overloading, you have to use a different method name. When you inherited UIViewController you inherited NSObject and made the class interopable to Obj-C. Swift on the other hand does support overloading, that's why it works when you remove the inheritance.
As it has already been answered, ObjC doesn't support method overloading (two methods with the same name) and In swift 2 under Xcode 7 there are two options to solve this kind of problems. One option is to rename the method using the attribute: #objc(newNameMethod:)
func methodOne(par1, par2) {...}
#objc(methodTwo:)
func methodOne(par1) {...}
another option to solve this problem in Xcode 7+ is by applying #nonobjc attribute to any method, subscript or initialiser
func methodOne() {...}
#nonobjc
func methodOne() {...}
The problem is UIViewController is an #objc class. When inheriting from UIViewController, BugViewController is also a #objc class.
This means it must conform to the rules of Objective-C selectors (the name of a method). The methods func perform(operation: (Double) -> Double) and func perform(operation: (Double, Double) -> Double) both have the same selector #selector(perform:). This is not allowed.
To resolve this, use different names: like func perform1(operation: (Double) -> Double) and func perform2(operation: (Double, Double) -> Double).
I think the best way to handle this is to give your perform() methods more descriptive names. What do these methods do? How do they change the state of the view controller? Look at the other UIViewController methods to get a feel for the style of method naming, or read Method Names Should Be Expressive and Unique Within a Class
From https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html under "Xcode 6.3 Release Notes" -> "Swift Language Changes" you find
Swift now detects discrepancies between overloading and overriding in the Swift type system and the effective behavior seen via the Objective-C runtime.
I got the same error due to having having two methods with the same Obj-C signature:
static func prepareForUpSyncing(obj : NSManagedObject!) -> Bool
static func prepareForUpSyncing(objs : [NSManagedObject]!) -> Bool
I didn't want to mark one of them as #nonobjc due to possibility of unforseen consequences at runtime. (Someone can correct me if there is no possibility)
Resolved it by using Swift's external parameter name feature (I made external name same as local name) to the second method, which effectively changes the Obj-c method signature:
static func prepareForUpSyncing(objs objs : [NSManagedObject]!) -> Bool {

Does AHEasing run in Swift?

I'm trying to use AHEasing in my Swift project. I've installed it via cocoapods and included this line in my bridging header:
#import <AHEasing/CAKeyframeAnimation+AHEasing.h>
I am able to access the function in CAKeyframeAnimation+AHEasing.h just fine, but when I try
var alphaAnimation = CAKeyframeAnimation.animationWithKeyPath("alpha", function: QuadraticEaseInOut, fromValue: 1.0, toValue: 0.0)
I get the error
Cannot invoke 'animationWithKeyPath' with an argument list of type '(String, function: (Double) -> Double, fromValue: Double, toValue: Double)'
After a little digging, I confirmed that QuadraticEaseInOut is indeed being converted to a (Double) -> Double closure, while the type for that parameter, AHEasingFunction, is being converted into a CFunctionPointer<((Double) -> Double)>.
Is there a way to convert between these 2 types? Has anyone successfully used AHEasing in Swift? Is there another work around that I'm not seeing?
I've heard reports from some people that this is a Swift 1.2 issue, that is no longer a problem in Swift 2.
Either way, I just worked around the problem by implementing the functionality that I needed from AHEasing entirely in Swift.

Swift Syntax Update? Classes not allowed in protocol. Can't fill SKTexture

I'm currently working on a tutorial for creating
an iOS Isometric Game. You can find this one here.
I just started coding Swift and because a lot of Syntax errors
appeared while working with tutorials a little older than 3 months
I asked my self if there were some main updates in Swift lately.
Until now, myself or XCode itself managed to fix those little issues, but
I cant help myself with this:
protocol TextureObject {
class var sharedInstance: TextureDroid {get}
var texturesIso:[[SKTexture]?] {get}
var textures2D:[[SKTexture]?] {get}
}
This is the protocol I'm trying to set (exactly like in the tutorial), but XCode won't let me define the class variable. The error code is the following:
"Class properties are only allowed within classes:
use static to declare a static property"
Both replacing "class" to "static" (which makes no logical sense to me) and
deleting the protocol (and define the class that should inherit without the use of the protocol) lead to another error in this code:
class TextureDroid: TextureObject {
class var sharedInstance: TextureDroid {
return textureDroid
}
let texturesIso:[[SKTexture]?]
let textures2D:[[SKTexture]?]
init() {
texturesIso = [[SKTexture]?](count: 2, repeatedValue: nil)
textures2D = [[SKTexture]?](count: 2, repeatedValue: nil)
//Idle
texturesIso[Action.Idle.rawValue] = [
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.N, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.NE, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.E, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.SE, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.S, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.SW, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.W, Action.Idle)),
SKTexture(imageNamed: "iso_3d_"+textureImage(Tile.Droid, Direction.NW, Action.Idle)),
]
This error appears in all the lines where I want to fill the texturesIso
Immutable value 'self.texturesIso' may not be assigned to
Here are my questions:
How can I fix the first error? Is there a new way to define classes inside a protocol?
Are those two errors connected, or is the second just appearing, because i managed to eliminate the first?
How can I fill the SKTexture in the right way? texturesIso.append won't work either.
Am I right with the Swift Update? If yes, is there an overview of all the sudden changes to Swift, because I could'n find one.
I would really appreciate anyone's help, thanks a lot in advance.
This tutorial appears to use an older version of swift. You can either use an older version of xcode that uses an earlier swift compiler or update the code. I will attempt to help you update the code.
"Protocol declarations can’t contain class, structure, enumeration, or other protocol declarations. The protocol member declarations are discussed in detail below." - Apple docs on swift protocol declaration
Just change the class var to static. This doesn't cause the second error, its just that the compiler stops after the first one so the second one isn't revealed.
Immutable value 'self.texturesIso' may not be assigned to
var texturesIso:[[SKTexture]?] {get}
defines a getter but no setter, therefore there is no way for you to set the self.texturesIso property. Change that to {get set}, and doing the same for the textures2d property might be necessary too, and change them to vars in the class.
There was a swift update yes. The new version is Swift 1.2
On top of answering this specific question, when I downloaded the tutorial code, to get it to compile, I also needed to change the touchesEnded to use Set instead of NSSet, which breaks touches.anyObject, so I used touches.first instead. Also, it was trying to change immutable tiles in gameScene, so I changed that to a var.
Note: I just downloaded the code and got it to compile and run, I'm not exactly sure how it is supposed to run, but it seemed ok to me. Also Does swift have class level static variables? has some good information on computed class variables vs static variables, although it doesn't talk about the protocol bit of the question

Where can I find the "math, strings, etc... libraries" for Swift?

I am looking at the Swift documentation, but I can't find reference to what there's in other languages...
Examples: sin(), cos(), abs() for math, uppercase(), lowercase() for strings, sort(), pop(), push() for arrays etc...
For strings I've found this in the docs:
Swift’s String type is bridged seamlessly to Foundation’s NSString
class. If you are working with the Foundation framework in Cocoa or
Cocoa Touch, the entire NSString API is available to call on any
String value you create, in addition to the String features described
in this chapter. You can also use a String value with any API that
requires an NSString instance.
Could you point me to some doc or where can I find those functions listed?
Looks like this is working...
import Foundation
var theCosOfZero: Double = Double(cos(0)) // theCosOfZero equals 1
The math functions are defined in the Darwin module, so as absolute minimum you have add this:
import Darwin
In most cases import Foundation or import Cocoa will suffice, since those modules import the Darwin module. If you need access to constants like M_PI or similar, navigate with cmd+click to the Darwin module and the to the Darwin.C. Here you would find the C API imports and the Darwin.C.math among them. This way you may examine what's available, already converted to Swift. Nevertheless, all that C API is available with import Darwin.
You cannot issue import Darwin.C.math directly, because you will see the following runtime error (or similar if you're not in the playground):
Playground execution failed: Error in auto-import:
failed to get module 'math' from AST context
Example playground code:
import Darwin
func degToRad(degrees: Double) -> Double {
// M_PI is defined in Darwin.C.math
return M_PI * 2.0 * degrees / 360.0
}
for deg in 0..<360 {
sin(degToRad(Double(deg)))
}
sin(), cos(), abs() are C methods defined in math.h https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/math.3.html
"str".uppercaseString() and "str".lowercaseString() are NSString methods.
sort() is part of the Swift Standard Library, documented at https://developer.apple.com/documentation/swift/array/1688499-sort
Array.append() and Array.removeLast() are also defined in the Swift Standard Library, documented at https://developer.apple.com/documentation/swift/array

Resources