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
Related
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
OBJ-C ONLY...
That is,
An ObjC app imports ObjC static lib A.
Static lib A imports static lib B.
Static lib A has functions that call functions within lib B.
The app only calls functions in lib A and does not call functions in lib B.
Can I assume that lib A or B can be either Obj-C or Swift?
IE. Can an ObjC app import an ObjC-or-Swift static lib A that itself imports a second ObjC-or-Swift static lib B? (yes, 4 use case permutations)
the git repository https://github.com/CombineCppSwiftObjcInStaticLib i created for you is showing this..
your initial #objc func run_central() in BLE_central.swift is exposed, which triggers the precompiler to generate objc compatible headers (bridge) which then again makes it possible to call the function from a method inside .mm(objc++) or .m(objc) when this generated header is imported.
In fact Hub_lib inside the repo is a static ObjC++ lib mixed with Swift. It would work the other way around also. The headers are the key for success here. If you can provide some objc or c or c++ header to swift functions it becomes compatible and wise versa. I mean in general, thats the idea of headers. If you don't have headers, that does not mean you can not call some external stuff, it just means you would call it blind. A proper IDE will complain before you even try to do this evil stuff, unknown entry points aka unknown symbols etc.. So you go for a proper header - always.
To properly combine swift with other languages its good to know there are always two ways of bridging.
In case of Objective-C (and also Objective-C++) it is
Bridging into Swift (projectname-Bridging-Header.h),
and Bridging out of Swift (expose with #objc to trigger automatically internal generation of projectname-Swift.h file. So this header is "invisible" in the file browser on the left side. Nor will you find it in the repo as file, it is named by modulename which is the project-name). The last mentioned header you could even write manually yourself, with lots of troublesome back-draws.
Hint: Executable code is executable code. No matter what language, as far it is compiled for the right device architecture and has symbols to call and you know what to do with the data returned.
Another Hint: there is a way to handle C pointers in swift see docu which become swift datatypes which you can use to go the other way and declare functions to return those from swift.
And direct use of C in Swift is also possible. The compiler considers if you explicit mark some code as C. extern "C" { /* code */ } will cause the C++ compiler to remember, this is still C++ code to compile the function in such a way, it can be called from C (and Swift)
//Example.hpp //no target membership
#ifdef __cplusplus
#include <stdio.h>
class Example {
private:
const char * _name;
public:
Example(const char *name);
~Example(void);
int getLen(void);
};
#endif
There should be an Example.cpp and don't forget to tell Xcode you deal with c++ #ifdef __cplusplus + #endif
//Example.cpp //has target membership
#include "Example.hpp"
#ifdef __cplusplus
#include <stdio.h>
#include <string>
//code implementation according to example.hpp
Example::Example(const char *name) {
_name = name;
}
int Example::getLen() {
return (int)strlen(_name);
}
#endif
//ExampleWrapper.cpp //has target membership
#include "Example.hpp" //c++ header file
extern "C" int myCppFunction(const char *s)
{
// Create an instance of Example, defined in the library
// and call getLen() on it, return result.
return Example(s).getLen();
}
So this function needs to be declared in the bridging header to make use of it.
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// for extern "C" functions declare them one by one here
// as implemented in ExampleWrapper.cpp
// becomes "func myCppFunction(_ s: UnsafePointer<Int8>!) -> Int32" in swift
int myCppFunction(const char * s);
and then call from swift..
os_log("The result from C++ is %u", myCppFunction("12345"))
So in fact, yes. Integrating a static lib A that calls static lib B in App is possible. Happy compiling as long you offer some header for each part that needs to know what is inside the head of the other lib. That is true for Apps as it is true for libs and frameworks under each other.
Edit here some important stuff to read about Swift Package Manager C support https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md
As long as the libraries export Objective-C compatible symbols, it doesn't matter if they're written in Objective-C, or Swift, or C++, or any other compiled language.
And we know that the Swift compiler exports Objective-C compatible symbols for all declarations that are marked with #objc (either explicitly or implicitly).
From a consumer perspective it doesn't matter which language generated the libraries, as long as the Objective-C compiler/linker can consume the symbols exported by those libraries.
As a newcomer to iOS Development i want to understand the relationship between Swift 2 and Foundation Framework
I already know that Swift is just a programming language and Foundation is a framework build on Objective-C.
What i don't understand is when i need to use Foundation classes or just stay at pure Swift.
For eg. when i have a Swift string do i always need to inherit from NSString for functionality i can't find in pure Swift strings?
Yesterday i was looking for a case-insensitive comparison between two Swift string. One of the solutions i found was that:
var a : String = "Cash"
var b : String = "cash"
if(a.caseInsensitiveCompare(b) == NSComparisonResult.OrderedSame){
println("voila")
}
This bring me a lot of frustration. How can a Swift string has a function(caseInsensitiveCompare) that doesn't exist in pure Swift?
Did the string inherit it from somewhere and how?
Please give me an overall explanation for when i need the foundation as a superset of Swift. Which part of foundation are no longer needed by me as a developer who skip Objective-C for Swift?
How can a Swift string has
a function(caseInsensitiveCompare) that doesn't exist in pure Swift?
It's because you imported Foundation (or UIKit, which includes Foundation) and because Swift String is bridged to Foundation NSString. This causes many (but not all) NSString methods to spring to life for String.
If you had not imported Foundation, you would not have been able to do what you did: caseInsensitiveCompare would not have been present.
The Foundation framework has its roots in NeXTSTEP, from the early days of Objective C. It's a great framework, but admittedly it's dated and lacks a lot of modern programming principles, and doesn't take advantage of many of Swift's new shiny toys. Apple is working on revitalizing Foundation for Swift 3.
I would steer clear of using Foundation anytime a pure Swift solution is available.
In your case, you can do case-insensitive comparison by converting both strings to lower case and comparing them:
if a.lowercaseString == b.lowercaseString {
//Strings match
}
I would actually roll it into an extension of String:
extension String {
func equalsIgnoringCase() -> Bool {
return a.lowercaseString == b.lowercaseString
}
}
//then:
if a.equalsIgnoringCase(b) {
//Strings match
}
I am trying to learn ReactiveCocoa and have a hard time getting started. I keep hitting minor bumps as API and tutorials seems to be outdated quickly. Maybe I have the wrong impression.
Just trying to follow this I do not seem to have NoError.
It should be imported correctly, since I have access to Signal, rac_textSignal etc. but I don't know why NoError is not available.
Their documentation mentions NoError as well but that leads to a 404.
This transition to RAC4 mentions NoError as well. Why is NoError undeclared? I am using ReactiveCocoa 4.0.1.
Edit: I just added public enum NoError : ErrorType {} to the top of the file and it works now. I am not sure if this is a proper solution to the problem though. It is not mentioned in guides and tutorials that I should extend ErrorType myself.
The reactive cocoa native NoError was removed in 4.0.1 in favour of antitypicals implementation in Result (adds NoError to Result, see this). See e.g. issue #2704
https://github.com/ReactiveCocoa/ReactiveCocoa/issues/2704
We can see this explicitly used in the source files, e.g.
import enum Result.NoError in Property.swift.
Hence, you probably need to include (antitypicals) Result whenever you intend to use NoError. One suggested fix in the issue thread is
public typealias NoError = Result.NoError
If you are seeing this now with ReactiveSwift 6.0, they removed the dependency on Result, which removes NoError.
Per their release notes here, the solution is to now use Never.
If you have used Result only as dependency of ReactiveSwift, remove
all instances of import Result, import enum Result.NoError or import
struct Result.AnyError and remove the Result Framework from your
project.
Replace all cases where NoError was used in a Signal or
SignalProducer with Never
The following example code shows how this should look now:
import ReactiveSwift
func example() -> SignalProducer<Void, Never> {
return SignalProducer(value: ())
}
If you add "import Results" to the top of the page above your class, NoError will no longer be an undeclared type!
I am in the process of migrating my streaming audio engine to swift. i am finding it difficult to use the C Audio API in swift.
I have a problem with AudioFileStreamOpen api where it takes 2 C functions as a parameter. I don't know how to use this API is swift.
AudioFileStreamOpen(self as UnsafePointer<()>, propertyProc, packetProc, kAudioFileMP3Type, audioStreamId)
I have defined the callback method as below for this API. But i am getting the compilation error.
func propertyProc(inClientData: UnsafePointer<()>,inFileStreamId: AudioFileStreamID,inPropertyId: AudioFileStreamPropertyID,ioFlags: UnsafePointer<UInt32>) -> Void {
.....
}
func packetProc(inClientData: UnsafePointer<()>,inNumberOfBytes: UInt32,inNumberOfPackets: UInt32, ConstUnsafePointer<()>, inPacketDescriptions: UnsafePointer<AudioStreamPacketDescription>) -> Void {
.....
}
Any help is appreciated to correctly define this C API in swift
You can't (currently) use an API requiring a C callback pointer from pure Swift code. Calling Swift functions or methods using a C function pointer is not supported by the current beta 4 language implementation, according to replies in the Swift forum at devforums.apple.com
UPDATE: The above answer is obsolete as of Swift 2.0
One alternative is to put some small trampoline C callback functions in an Objective C file, which can interoperate with Swift, and have those C functions in turn call a block or closure, which can be in Swift code. Configure the C callbacks with your Swift closures, and then pass those C callbacks to the CoreAudio functions.
I don't know much about Audio API, however, you should replace UnsafePointer by a pointer to an Object. for example:
var clientData : AnyObject?
var listenerProc : AudioFileStream_PropertyListenerProc = AudioFileStream_PropertyListenerProc.convertFromNilLiteral()
var packetsProc : AudioFileStream_PacketsProc = AudioFileStream_PacketsProc.convertFromNilLiteral()
var audioFileTypyeId : AudioFileTypeID = 0
AudioFileStreamOpen(&clientData, listenerProc, packetsProc, audioFileTypyeId, &streamId)
the initialization code for listenerProc, packetsProc or other variables is just to by-pass the compiler error.
To your situation, try to replace 'self as UnsafePointer<>' by '&self'. However 'self' must be something that can be converted to compatible data type.
https://developer.apple.com/library/prerelease/ios/documentation/MusicAudio/Reference/AudioStreamReference/index.html#//apple_ref/c/func/AudioFileStreamOpen