In Swift how can I save a class object? - ios

I create an instance of a Trie object using third party library https://github.com/fpg1503/Aho-Corasick-Swift. Example code to build Trie object is like this:
let trie = Trie.builder()
.add(keyword: "hers")
.add(keyword: "his")
.add(keyword: "she")
.add(keyword: "he")
.build()
However, in my case number of keywords is around 300 thousand, which takes large amount of build this Trie object. My objective is build the trie object just once outside app and save it to use by App for inference on any text. Something like this:
let emits = trie.parse(text: "any text")
However, I am struggling to save this Trie object in swift. In Java (for android), I achieved this task so easily but in Swift it looks very hard thing to do. I am trying hard to achieve this using Codable but that requires all the classes starting from beginning to conform codable. I tried to copy all the codes of (https://github.com/fpg1503/Aho-Corasick-Swift) and change all classes to conform codable. My project now builds successfully but gives runtime error for encoding this Trie object:
Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee0005ff8)
How can I achieve this in swift?

The problem appears to be that State is recursive, so when you encode a State you get an infinite recursion until you generate a stack overflow.

Related

Swift instance members & functions calls, could someone please clarify?

I'm practicing functions in an Xcode project (not playground, if that matters) and when I set the constant's function name to the above function's name, Xcode won't let me call it.
In other functions I've done the same thing I haven't had this error, I don't know why it's being triggered. I've tried putting the "let fun" constant into it's own struct but that just throws up a different error.
Your let fun = playstation(... is code. It is an executable command. Code consisting of an executable command cannot just live anywhere. It cannot exist just free-floating the way you have it. It must live in a method. For example you could put it inside your viewDidLoad method.
I am sure you know this, but I would like to say that learning the basics/fundamentals of the Swift language is really good if you use playgrounds for that or any other online IDEs which support Swift language.
Swift Playgrounds Experience is very, very different than what an iOS dev has to do later, i.e. when it actually comes to building an app.
Of course in app making, the Swift language is used, and one uses the knowledge he practiced using playgrounds. BUT!
When it comes to storyboards, ViewControllers, etc., one has to understand that this time, it is all about OOP (classes and structs).
It is about managing views, loading them, displaying UIView objects, implementing logic, saving/loading data...
So as people mentioned above, here you are creating an instance method and trying to use it as a regular function inside that Class.
To be able to use this function as you expect, you have to create an object/instance of this class, then you can call this function.
In this picture, you may see that using a static keyword also might be a solution. static func(){} means that this function belongs to the class itself. You access that func by using the full name of the type/class.
You cannot call an instance method to initialize this same exact instance property, so you will need to convert to a lazy var like so:
lazy var fun = playStation(game: "Monsters")
This way, the playStation(game: "Monsters") call will be triggered lazily, in the exact moment when the fun property will be called for the first time. This can be very useful, especially when performing more intensive tasks. The quirk with using lazy keyword is that it can only be used with var, which means the property can be mutated or set again - we lose immutability of let constants.
But maybe you do not want to store the fun value as an instance property and only want to get it once? You could then move it into the viewDidLoad implementation, so the fun is no longer an instance property but a local one, available only within the viewDidLoad method scope.
override func viewDidLoad() {
super.viewDidLoad()
let fun = playStation(game: "Monsters")
// do what you want with the `fun` value.
// maybe set it as text to some label?
myLabel.text = fun
}
You can read more about Lazy Initialization in this blogpost, also make sure to read the official documentation.

Swift Transfer -> Array to ObjectiveC

I have problem and i cannot fix it by using google.
I have string array (written in swift). But i have objectiveC files with chart functions.
I need transfer whole swift array into objectiveC file.
Example of array:
for i in 0...11 {
mainSelectionMonthArrayValues.append(
String(WatchlistViewController().fetchDataMonth(
type:1, month: i+1, year: 2017)
)
)
}
Given you are not very specific about the code that "does not work" or the specific error you get it is hard to answer anything precisely. But given what Google finds in books for "cocoa pass swift string array to objective-c" you will have
To call an NSArray function on a Swift array you may have to cast to NSArray
so it is a pretty safe bet you will have to do this too if you want to pass mainSelectionMonthArrayValues to an Objective-C method (with an appropriate interface). Casting to an Objective-C class will not be free in most cases, but it is likely to be a constant time operation. Note however, that you will have to coerce if your object needs to be mutable on the Objective-C end. So try passing your array using something like
objCRef.callObjCMethod(mainSelectionMonthArrayValues as NSArray)
If this again "does not work" then you should provide us with more info on the kind of error you experience.

Typedef NSArray of type in Objective C

It has been a long time since I have worked in Objective C but now I am using it because I need to write something that will remain mostly source compatible for future versions. I want to create an init method that allows me to init my viewController with an array of my custom model object. In Swift I would do it like this:
typealias Stack = [StackBarTabItem]
…
func init(stacks:[Stack])
But how would I typedef an NSArray like that? I am pretty sure I can't do something like typedef NSArray<StackBarTabItem> Stack; so what is the syntax in objective c?
Until iOS 9 and Xcode 7, this isn't officially supported. One way to do this is to subclass NSArray or NSMutableArray and enforce typing in your subclass, but this isn't really recommended. One way to deal with the fact that NSArray can only hold ids is to use respondsToSelector before calling a method on any of the objects in the array.
This solution isn't really a substitute for a good typing system, but it's a common practice to get around this limitation. Thankfully, generic support is getting added soon!
Objective-C is dynamically typed. You simply do not check for it.
Asking the audience on talks and in internet fora, the real danger that code will be shipped with a typing bug is minimal and by far lower than other sources of errors. Simply do not care about this.
Ask yourself: How could that happen without getting a runtime error at the very beginning of your next program run?

What does this block mean in Swift - Alamofire?

This is a code block in Alamofire/Manager.swift:
It is inside a class named "public class Manager"
public static let sharedInstance: Manager = {
let configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
return Manager(configuration: configuration)
}()
Obviously, this is "let something equals the closure," but what I don't get is what does the "()" in the end of the line mean?
To defer the execution of the code? How? (It seems to me that the execution won't be deferred as it has the "()"? And I am wondering why this is not causing the existing of a memory circle? It returns the Manger itself and the returned new instance will also do the same, returning a new self...
Why not a key word "lazy"?
I have a strange feeling that i've seem this usage somewhere else too. I'm learning Swift for 60 days now. Am I fast or slow? How to be a iOS developer also?(I mean how to be a real one, not enroll the program)
For now I'm kind of confused and reading all the source code I could get. Sometimes I feel the official docs and Xcode sucks and I don't know how to read a source code scratch. Any tips and advice?
This initializes sharedInstance with the result of the closure (without the parens at the end it would just initialize it to the closure itself) It's a standard syntax for initializing variable with an initializer too complex for a simple expression. In this multiple statements are required so that the HTTPAdditionalHeaders can be initialized.
Okay, I've made a mistake. The trick lies that the sharedInstance used a key word "static" This is common, but in python, which I am most familiar with, do not use this key word.
According to the official guide:
“You can also define properties that belong to the type itself, not to any one instance of that type. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called type properties.”
Apple Inc. “The Swift Programming Language”. iBooks. https://itun.es/cn/jEUH0.l
the answer is at the session name "Setting a Default Property Value with a Closure or Function": https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID231

Expensive Object management in Swift

I have been looking at Swift the last couple of days and it looks good, I am confused on a point though even after review of the guide Apple published.
I understand that memory management in Swift uses ARC and therefore quite safe, however in situations where I'd like more fine grained control of object creation and destruction I'm slightly confused.
Take these two simple examples:
In ObjC, when you'd (for example) like a UIViewController you intend to push to stay around for the lifetime of your app and only be created once (say because it's expensive to create), you'd make it a property and then wrap it's Alloc Init like this:
if (!self.myProperty)
{
self.myProperty = [[MyObj alloc] init];
}
This way it only creates once, keeps state and the same object instance can be reused indefinitely, yielding known object references, and good performance not having to recreate each time the viewController goes out of scope.
Another example of this is with NSMutableString, vs Swifts String.
You can set an NSMutableString's string many times and it will keep the same object reference, however this doesn't seem to be the case with a Swift String when changing it.
This may just be 'deprecated thinking in Objective C' but is there a best practice with regard to keeping around expensive objects or to keep state (same object) for certain objects during the lifetime of their usage.
I think what you're looking for is a "Lazy stored property":
The example in the swift docs is:
class DataManager {
#lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
and it says about #lazy:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the #lazy attribute before its declaration.
The comment about NSMutableString is a little different, you can continue to use NSMutableString in your swift code, but Apple are encouraging developers to use the Swift built-in types whenever possible :)
see the "String Mutability" section in the swift docs

Resources