Extension | Source Type |
---|---|
.h | Header files. Header files contain class, type, function, and constant declarations. |
.m | Source files. This is the typical extension used for source files and can contain both Objective-C and C code. |
.mm | Source files. A source file with this extension can contain C++ code in addition to Objective-C and C code. This extension should be used only if you actually refer to C++ classes or features from your Objective-C code. |
@interface MyClass : NSObject
{
int count;
id data;
NSString* name;
}
- (id)initWithString:(NSString*)aName;
+ (MyClass*)createMyClassWithString:(NSString*)aName //Class method;
@end
@implementation MyClass
- (id)initWithString:(NSString *)aName
{
self = [super init];
if (self) {
name = [aName copy];
}
return self;
}
+ (MyClass *)createMyClassWithString: (NSString *)aName
{
return [[self alloc] initWithString:aName] ;
}
@end
//create an Object of SomeClass:
id anObject = [[SomeClass alloc] init];
//Example init method implementation in NSObject:
- (id)init {
self = [super init];
if (self) {
//initialisation of Object
}
return self;
}
NSString* text1 = [[NSString alloc] initWithCString: "Hello World!" encoding: NSUTF8StringEncoding];
NSString* text2 = @"Hello World!"; //short for upper statement
NSLog(@"text 1 = %@", text1); //%@ placeholder for objects
NSLog(@"text 2 = %@", text2);
NSLog(@"text2.length = %ld", text2.length);
[myArray insertObject:anObject atIndex:0];
[[myAppObject theArray] insertObject: [myAppObject objectToInsert] atIndex: 0];
// message without argument
[receiver message];
// message with single argument
[receiver message: argument];
// message with multiple arguments
[receiver message: arg1 argument2: arg2];
// receiving a return value
int status = [receiver message];
// message with a variable number of arguments
[receiver makeGroup: group, memberOne, memberTwo, memberThree];
// nil is essentially the same as NULL
NSMutableArray *myArray = nil;
// Create a new array and assign it to the myArray variable.
myArray = [NSMutableArray array];
Person* myPerson; // Strong typing
id myObject; // Weak typing
//Dynamic binding example
@interface ClassA : NSObject {…}
- (void) doSomething;
@end
@interface ClassB : NSObject { …}
- (void) doSomething;
@end
// anywhere
id object = … // An object of an arbitrary class
[object doSomething]; // polymorph between ClassA und ClassB
Please open the terminal and create your first Objective-C project.
Objective-C:
NSString *helloWorld = @"Hello World";
NSLog(@"%@", helloWorld);
Swift:
var str = "Hello World"
print(str)
More background information: Swift Language History
Learn Swift: Swift Language Guide
var myvariable = 0
var myvariable: Int = 0
var name = "Name" // Type is inferred as String
var age = 38 // Type is inferred as Int
var weight = 90.5 // Type is inferred as Double
var myvariable: Int // Type annotation defining type Int
var myName: String = "HdM"
let myconstant = 10
var myvariable = 0, yourvar = 1, anothervar = 3
var rabbit: String? //declares optional String
... //rabbit = "running"
if (rabbit != nil){
print("Rabbit is \(rabbit!)") //unwraps Optional
} else {
print("Rabbit is nil")
}
var smallInt: UInt8 = 5
var largertInt: Int16 = 10
var evenLargerInt: Int32 = 100
var biggestInt: UInt64 = 1000
UInt8.min //0
UInt8.max //255
Int16.min // -32768
Int16.max // 32768
var mySmallFloat: Float = 2.34352
var myBigFloat: Double = 3.42323
let pi = 3 + 0.14159
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
let hdmIsGreat = true
let swiftIsBoring = false
let i = 1
if i {
//will not compile and report an error
}
let i = 1
if i==1 {
//this works
}
A Range or CountableRange (since Swift 3.0) is a type in Swift that defines a number of elements that can be iterated over, e.g. a number of integer values or String.Index values
The Range can be created using the range operator:
ClosedRange operator: ...
Range operator: ..<
let myFromZeroTo5Range = 0...5 //CountableClosedRange(0...5)
let myFromZeroToSmallerSixRange = 0..<6 //CountableRange(0..<6))
Since Swift 3.0 ClosedRange (...
) and Range (..<
) are two different types which can not be converted into each other.
Swift Strings and Characters are value types, Unicode compliant and easy to use
let emptyImmutableString = ""
var emptyMutableString = ""
var emptyString = String()
let sparklingHeart = "\u{1F496}"
String values can be constructed by passing an array of Characters
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
Concatenation of Strings and Characters is simple
let string1 = "Hello "
let string2 = "HdM"
let char1: Character = "!"
var concatenatedString = string1 + string2 //"Hello HdM"
concatenatedString.append(char1) // "Hello HdM!"
String interpolation allows to create a new String from multiple variables or literals
let multiplier = 3
let message = "\(multiplier) times 2 is \(multiplier*2)" //„3 times 2 is 6“
Expressions in the parentheses cannot contain double quotes, backslashes, a carriage return or line feed You can call functions within the parentheses
func getHint() -> String {
return "special hint"
}
let newmessage = "New hint: \(getHint())" //„New hint: special hint“
The property „characters“ allows you to iterate over all characters in a String
for letter in string {
print("\(letter)")
}
Use count() to count Chars
string.count // 19
Use can create a range to access Characters of a part of a String
let range = string.index(string.startIndex, offsetBy: 5)..<string.index(before: string.endIndex)
for mindex in string.indices[range] {
print("\(string[mindex])",terminator: "1")
}
To modify strings, you can use insert(), remove() and removeSubrange()
var myString = "Hello HdM"
var idx = myString.index(myString.endIndex, offsetBy: -2) //7
myString.remove(at: idx) // „Hello HM“
let r = myString.index(myString.startIndex, offsetBy: 5)..<myString.endIndex
myString.removeSubrange(r) // „Hello“
myString.insert("!", at: myString.endIndex) //"Hello HM!"
String and Character equality is checked using the „equal to“ operator (==) Strings are equal if they have the same linguistic meaning and appearance, even if they are composed from different Unicode scalars
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
print("\(eAcuteQuestion) and \(combinedEAcuteQuestion) are considered equal")
}
// "Voulez-vous un café? and Voulez-vous un café? are considered equal"
Further you can use fully unicode.
let β = 3 * t - r * sin(φ) * cos(θ)
You can check the prefix or suffix of a String using hasPrefix() and hasSuffix()
let stringArray = ["1st String of 2","2nd String of 2"]
for string in stringArray {
if string.hasPrefix("1st") {
print("String starting with 1st: \(string)")
}
if string.hasSuffix("2") {
print("String ending with 2: \(string)")
}
}
enum GraphicalObjects {
case Circle
case Rectangle
case Polygon
}
var go = GraphicalObjects.Circle
if go == GraphicalObjects.Circle {
print("is a Circle")
} else if go == .Rectangle {
print("is a Rectangle")
} else {
print("is a Polygon")
}
Arrays are next to sets and dictionaries the mostly used collections in swift To create a mutable array, assign it to a variable (e.g. var myArray)
var shoppingList = [String]()
Initialize directly by writing:
var shoppingList = ["Apples", "Pears", "Bread", "Milk"]
Appending items to an Array
shoppingList.append("Soap")
//or
shoppingList += ["Juice"]
Adding Arrays and creating new ones
var familyList = shoppingList + ["Cornflakes","Ice Cream"]
Removing items from an Array
shoppingList.remove(at: 2)
shoppingList.removeLast()
shoppingList.removeAll(keepingCapacity: true)
Check if an Array is empty
if shoppingList.isEmpty {
...
}
Retrieve a certain item or a part of the Array
shoppingList[5] //-> "Cornflakes"
shoppingList[1...3] //["Pears", "Bread", "Milk"]
Tuples group multiple values into a single compound value
let httpStatus = (404, "Not Found")
Each single value is accessible by a number, e.g.:
httpStatus.0 // 404
httpStatus.1 // "Not Found"
Tuples can be decomposed into their separate values
let (statusCode, description) = httpStatus
print("Statuscode: \(statusCode) means: \(description)")
You can name the elements in a tuple and access them using the names
let newHttpStatus = (code: 200, description: "OK")
print("code: \(newHttpStatus.code)")
print("description: \(newHttpStatus.description)")
Iterating over an Array
var familyList = ["Milk", "Bread","Soap","Juice"]
for item in familyList {
print(item)
}
Iterating with index and value
for (index,value) in familyList.enumerated() {
print("item nbr. \(index + 1) is: \(value)")
}
Since Swift 3.0 for-loops look like this:
for index in 0 ..< 3 {
print("index is \(index)")
}
C-style loops are not supported anymore
Use the while loop to iterate while a condition is true
var shoppingList = ["Apples","Pears","Bread","Milk"]
while !shoppingList.isEmpty {
print("remove one item from list")
shoppingList.removeLast()
}
Use do-while to test the condition after executing the statements
shoppingList = ["Apples","Pears","Bread","Milk"]
repeat {
shoppingList.removeLast()
} while !shoppingList.isEmpty
Test a condition using if The else-if and final else clause is optional
var temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
} else {
print("It's not that cold. Wear a t-shirt.")
}
// prints "It's really warm. Don't forget to wear sunscreen."
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// prints "(1, -1) is on the line x == -y"
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet(name: "Bob", day: "Tuesday")
func greet(name: String, day d: String) -> String {
return "Hello \(name), today is \(d)."
}
greet(name: “Bob", day: "Tuesday")
It is possible to return multiple values from a function using Tuples
func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
getGasPrices()
Functions can take a variable number of arguments
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(numbers: 42, 597, 12)
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers,condition: lessThanTen)
var numbers = [20, 19, 7, 12]
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
struct Resolution {
var width = 0
var height = 0
}
// create an instance
let someResolution = Resolution()
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
let myShape = Shape()
myShape.numberOfSides = 10
myShape.simpleDescription()
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
let s = NamedShape(name: "MyShape")
protocol SomeProtocol {
// protocol definition goes here
}
class SomeClass: SomeSuperClass, FirstProtocol, SomeProtocol {
// class definition goes here
}
protocol SomeProtocol {
// a settable Property must be implemented using
// var in the implementing class
var mustBeSettable: Int { get set }
// a only gettable Property should be implented using let
var doesNotNeedToBeSettable: Int { get }
}
protocol RandomNumberGenerator {
func random() -> Double
}
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not >= 0
class FatherChristmas {
enum DeliveryError : Error {
case NoPresentsRemaining
}
var numberOfPresents = 0
func deliverPresents() throws {
guard numberOfPresents > 0 else {
throw DeliveryError.NoPresentsRemaining
}
print("Presents delivered")
}
func itIsChristmasEve(){
do {
try deliverPresents()
} catch DeliveryError.NoPresentsRemaining{
print("Could not deliver presents!")
} catch {
print("Unknown error")
}
}
}
let fatherChristmas = FatherChristmas()
fatherChristmas.itIsChristmasEve()
//this protocol defines the "description" method used by many classes
extension CustomStringConvertible {
var shoutyDescription: String {
return "\(self.description.uppercased())!!!"
}
}
let greetings = ["Hello", "Hi", "Yo yo yo"]
print("\(greetings.description)")
// prints "["HELLO", "HI", "YO YO YO“]!!!\n"
print("\(greetings.shoutyDescription)")
More information on asynchronous functions can be found here