#nsarray
Explore tagged Tumblr posts
Text
Higher Order Functions in Objective-C
No, you did not get fooled by your eyes. The title is not a typo.
First, let's take a look at how it performs in Swift playground
If you pay attention to the snippet below, you will notice the intent of codes itself is focus on function for each element in a collection and there are no signs of a for-loop pattern. It helps developers to focus on more operations itself but not control flow with data process.
// Map: Iterate a collection and applies the same block operation to each element in it. print(characters.map({ String($0).uppercased() })) // Filter: Iterate a collection and return elements that meet a condition. print(characters.filter({ $0 == "o"})) // Reduce: Combine all elements in a collection to create a single output. print(characters.reduce("", { String($0) + String($1) })) // FlatMap: Flatten a collection of collections. let _characters = ["Hello".characters, ", ".characters, "playground".characters] print(_characters.flatMap({ $0 }))
Okay, now let's get hands dirty
Unlike Swift, higher order functions are not built-in natively in Objective-C. Therefore, we need to create our own category to have these functions be accessible. If you browse the codes below, the core concept is not complicated basically. It's all around the function enumerateObjectsUsingBlock: and adds some minor variation according to its purpose.
- (NSArray *)map:(id (^)(id obj))block { NSMutableArray *mutableArray = [NSMutableArray new]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [mutableArray addObject:block(obj)]; }]; return mutableArray; } - (NSArray *)filter:(BOOL (^)(id obj))block { NSMutableArray *mutableArray = [NSMutableArray new]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (block(obj) == YES) { [mutableArray addObject:obj]; } }]; return mutableArray; } - (id)reduce:(id)initial block:(id (^)(id obj1, id obj2))block { __block id obj = initial; [self enumerateObjectsUsingBlock:^(id _obj, NSUInteger idx, BOOL *stop) { obj = block(obj, _obj); }]; return obj; } - (NSArray *)flatMap:(id (^)(id obj))block { NSMutableArray *mutableArray = [NSMutableArray new]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id _obj = block(obj); if ([_obj isKindOfClass:[NSArray class]]) { NSArray *_array = [_obj flatMap:block]; [mutableArray addObjectsFromArray:_array]; return; } [mutableArray addObject:_obj]; }]; return mutableArray; }
So, how to use them?
The usage is very similar to the ways in Swift but little wordy indeed :) However, the patterns and ideas are still the same. We only take care operations and no need to deal with flow controls.
NSArray *array = @[ @"H", @"e", @"l", @"l", @"o", @",", @" ", @"w", @"o", @"r", @"l", @"d", @"!" ]; // Map: Iterate an array and applies the same block operation to each element in it. NSLog(@"%@", [array map:^id(id obj) { return [(NSString *)obj uppercaseString]; }]); // Filter: Iterate an array and return elements that meet a condition. NSLog(@"%@", [array filter:^BOOL(id obj) { return [(NSString *)obj isEqualToString:@"o"]; }]); // Reduce: Combine all elements in an array to create a single output. NSLog(@"%@", [array reduce:@"Hey, " block:^id(id obj1, id obj2) { return [NSString stringWithFormat:@"%@%@", obj1, obj2]; }]); array = @[ @[@"H", @"e", @"l", @"l", @"o"], @[@",", @" "], @[@"w", @"o", @"r", @"l", @"d", @"!"] ]; // FlatMap: Flatten an array of arrays. NSLog(@"%@", [array flatMap:^id(id obj) { return obj; }]);
But.... Wait! there might be something wrong here!!
Yes, the devil is always in the details. That's why BUT is so important all the time. As a developer with years experience, you might wonder if is it a good practice in Objective-C? The reason is that type safety becomes developers' responsibility more or less. After all, Swift and Objective-C don't share the same philosophy at type inference and type safety in many ways. My suggestion is to add a class restrictor for each function to improve safety. Although adding class restrictor might become wordier in writing, I still think the safer the better in the long run. The snippet below is to demonstrate the usage with a class restrictor. The full implementation is available at GitHub here.
NSArray *array = @[ @"H", @"e", @"l", @"l", @"o", @",", @" ", @"w", @3, @"o", @"r", @"l", @"d", @"!" ]; // Map: Iterate an array and applies the same block operation to each element in it. NSLog(@"%@", [array map:^id(id obj) { return [(NSString *)obj uppercaseString]; } class:[NSString class]]); // Filter: Iterate an array and return elements that meet a condition. NSLog(@"%@", [array filter:^BOOL(id obj) { return [(NSString *)obj isEqualToString:@"o"]; } class:[NSString class]]); // Reduce: Combine all elements in an array to create a single output. NSLog(@"%@", [array reduce:@"Hey, " block:^id(id obj1, id obj2) { return [NSString stringWithFormat:@"%@%@", obj1, obj2]; } class:[NSString class]]); array = @[ @[@"H", @"e", @"l", @"l", @"o"], @[@",", @" ", @3], @[@6, @8, @6], @[@"w", @"o", @"r", @"l", @"d", @"!"] ]; // FlatMap: Flatten an array of arrays. NSLog(@"%@", [array flatMap:^id(id obj) { return obj; } class:[NSString class]]);
0 notes
Text
Flutter for mac m1

#Flutter for mac m1 code
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Ĭommand PhaseScriptExecution failed with a nonzero exit codeĪs for the Error log from Xcode: /Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//provider-3.2.0/lib/src/provider.dart:259:19: Error: The method 'inheritFromWidgetOfExactType' isn't defined for the class 'BuildContext'. : context.ancestorInheritedElementForWidgetOfExactType(type)?.widget Try correcting the name to the name of an existing method, or defining a method named 'ancestorInheritedElementForWidgetOfExactType'. Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//provider-3.2.0/lib/src/provider.dart:260:19: Error: The method 'ancestorInheritedElementForWidgetOfExactType' isn't defined for the class 'BuildContext'. ? context.inheritFromWidgetOfExactType(type) as InheritedProvider Try correcting the name to the name of an existing method, or defining a method named 'inheritFromWidgetOfExactType'. 'BuildContext' is from 'package:flutter/src/widgets/framework.dart' ('/Users/wissamboughannam/Developer/flutter/packages/flutter/lib/src/widgets/framework.dart'). Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//provider-3.2.0/lib/src/provider.dart:259:19: Error: The method 'inheritFromWidgetOfExactType' isn't defined for the class 'BuildContext'. Volumes/Sub/Flutter-Projects/test-project/test_project_app_v2/test_app_2/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m:101:20: warning: this old-style function definition is not preceded by a prototype Volumes/Sub/Flutter-Projects/test-project/test_project_app_v2/test_app_2/ios/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m:58:28: warning: this old-style function definition is not preceded by a prototype
#Flutter for mac m1 code
+ (PHFetchResult *)fetchAssetsWithALAssetURLs:(NSArray *)assetURLs options:(nullable PHFetchOptions *)options API_DEPRECATED("Will be removed in a future release", ios(8, 11), tvos(8, 11)) API_UNAVAILABLE(macos) Įrror: the following command failed with exit code 0 but produced no further outputĬompileC /Users/wissamboughannam/Library/Developer/Xcode/DerivedData/Runner-awkucyxpawezvvfjchbivjxuwsah/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/file_picker.build/Objects-normal/x86_64/FilePickerPlugin.o /Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//file_picker-1.4.2/ios/Classes/FilePickerPlugin.m normal x86_64 objective-c .clang.1_0.compiler Applications/Xcode-beta.app/Contents/Developer/Platforms/atform/Developer/SDKs/iPhoneSimulator14.5.sdk/System/Library/Frameworks/amework/Headers/PHAsset.h:74:1: note: 'fetchAssetsWithALAssetURLs:options:' has been explicitly marked deprecated here In module 'Photos' imported from /Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//image_picker-0.6.7+1/ios/Classes/FLTImagePickerPhotoAssetUtil.h:6: Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//image_picker-0.6.7+1/ios/Classes/FLTImagePickerPhotoAssetUtil.m:21:47: warning: 'fetchAssetsWithALAssetURLs:options:' is deprecated: first deprecated in iOS 11 - Will be removed in a future release UIKIT_EXTERN UIImagePickerControllerInfoKey const UIImagePickerControllerReferenceURL API_DEPRECATED("Will be removed in a future release, use PHPicker.", ios(4.1, 11.0)) API_UNAVAILABLE(tvos) // an NSURL that references an asset in the AssetsLibrary framework Applications/Xcode-beta.app/Contents/Developer/Platforms/atform/Developer/SDKs/iPhoneSimulator14.5.sdk/System/Library/Frameworks/amework/Headers/UIImagePickerController.h:62:51: note: 'UIImagePickerControllerReferenceURL' has been explicitly marked deprecated here In module 'UIKit' imported from /Volumes/Sub/Flutter-Projects/test-project/test_project_app_v2/test_app_2/ios/Pods/Target Support Files/image_picker/image_picker-prefix.pch:2: Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//image_picker-0.6.7+1/ios/Classes/FLTImagePickerPhotoAssetUtil.m:17:44: warning: 'UIImagePickerControllerReferenceURL' is deprecated: first deprecated in iOS 11.0 - Will be removed in a future release, use PHPicker. Applications/Xcode-beta.app/Contents/Developer/Platforms/atform/Developer/SDKs/iPhoneSimulator14.5.sdk/System/Library/Frameworks/amework/Headers/UIAlertView.h:27:12: note: 'UIAlertView' has been explicitly marked deprecated UIAlertView : UIView module 'UIKit' imported from /Volumes/Sub/Flutter-Projects/test-project/test_project_app_v2/test_app_2/ios/Pods/Target Support Files/image_picker/image_picker-prefix.pch:2: Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead Users/wissamboughannam/Developer/flutter/.pub-cache/hosted//image_picker-0.6.7+1/ios/Classes/FLTImagePickerPlugin.m:141:20: warning: 'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated.

0 notes
Link
original source : https://stackoverflow.com/questions/19325677/tab-bar-covers-tableview-cells-in-ios7?answertab=votes#tab-top
tab bar가 scroll view의 밑부분을 가리는 문제를 해결하는 방법
https://stackoverflow.com/a/19325718/3151712
약간의 문제가 코드에 있어서 수정했다.
let adjustForTabbarInsets:UIEdgeInsets = UIEdgeInsetsMake(0, 0, (self.tabBarController?.tabBar.frame)!.height, 0);
self.scrollView.contentInset = adjustForTabbarInsets;
self.scrollView.scrollIndicatorInsets = adjustForTabbarInsets;
2 notes
·
View notes
Text
HackingWithSwift Day 2
So started with array. Not much different from NSArray from ObjC. Just added with type annotation (String, Int, Double, Boolean) or explicit define option.
let one = “one” let two = “two” let three = “three” let four = “four”
let numbers = [one, two, three, four]
And follow by Set, which should be similar to NSSet.
“Sets are collections of values just like arrays, except they have two differences: - Items aren’t stored in any order; they are stored in what is effectively a random order. - No item can appear twice in a set; all items must be unique.”
Quoted from author, pretty straight forward
let colors = Set(["red", "green", "blue"])
["red", "green", "blue"] = Array, so this code is init a constant set name colors with an array
Since Set has no overlap value, so it says that it’s good for a fast lookup compare to array. But how fast is it ? Shall put that to my further research list
The law of tuple by the author 1. You can’t add or remove items from a tuple; they are fixed in size. 2. You can’t change the type of items in a tuple; they always have the same types they were created with. 3. You can access items in a tuple using numerical positions or by naming them, but Swift won’t let you read numbers or names that don’t exist.
var tuple = ("Taylor", "Swift") Without putting a name for each variable, one can only access it by numerical position, like index in array, so tuple.0 = “Taylor” , tuple.1 = “Swift”
var tuple = (first: "Taylor", last: "Swift") With name, I can do tuple.first or tuple.last
Compare to array, tuple is more flexible-is var person = (name: "Paul", age: 40, isMarried: true) A variable that combine 3 different data type. Can’t say array can’t do so, but maybe more hassle ? At the end ,it’s up to the developer to decide on how to achieve better readability and the scalability of the data/class
Arrays vs Sets vs Tuples When to use it ?
If you need a specific, fixed collection of related values where each item has a precise position or name, you should use a tuple: let address = (house: 555, street: "Taylor Swift Avenue", city: "Nashville")
Although the author say so, for me, it’s just a cheat code so that I don’t need to write a block to return result like that, or rely on NSDictionary to do so, make the code much cleaner haha.
As for arrays vs sets , it’s just unique set vs order matters but duplicate is fine principle
Okay, move on to Dictionary, quite similar to NSDictionary let heights = [ "Taylor Swift": 1.78, "Ed Sheeran": 1.73 ] Can use “string” to search for the example above, or build your own and use “int” to search. [String: Double] [String: String] [String: Bool] [Int: String] Typical type annotation style, but there’s more combination and more complex one we can work on, especially after added “Any”. Dictionary comes with default value option. Or one can just always detect if it’s nil or not instead of detect the default value assigned, both way works.
So to initialise empty collections var teams = [String: String]() var results = [Int]() var words = Set<String>() var numbers = Set<Int>() Dictionary and Array doesn’t require angle bracket (not mandatory, but can use too)
And time for enumeration!!!! enum Result { case success case failure }
One of my favourite because we can assign different type of value to it, like STRING let status = Result.failure
So with this I can just return a string value, rather than need a switch case, loop through the enum that use int or NSInteger based as value and return a string text based on that value
Enum with associated value enum Activity { case bored case running(destination: String) case talking(topic: String) case singing(volume: Int) }
let talking = Activity.talking(topic: "football") Which can associate more than 1 parameter A bit hard to think of the advantage of this associated value, hopefully can see more practical example after this, instead of just the weather one in the article.
enum Planet: Int { case mercury case venus case earth case mars } Define enum with data type, in this case, mercury raw value is equal to 0 , while venus become 1, incremental till the bottom one. Or explicit define mercury = 2, then venus = 3, incremental till the bottom one
So if mercury = 2, To get mars value, that will be let mars = Planet(rawValue: 5)
Still need a little bit more practice on the format of array, set , and tuple, didn’t do so well during the review. Shame on me, geez
0 notes
Text
2020: Year in Code
2020: Year in Code Git Repos: Dropbox 2020 Code Sketches: ├── AutolayoutBookWork ├── BluetoothLab ├── CollectionViewTest ├── CombineLab ├── DataSourceCellConfig ├── NSSecureCoding-Example-Objc ├── QR-Code-Generation-in-Swift.playground ├── SimpleAPIClient ├── Swift-Hackspace ├── SwiftUI\ -\ Apple\ Tutorials ├── SwiftUI-Lab ├── SwiftUIPlayPen ├── WWDC2020-Code-Sketches ├── mac-SwiftUI-Experiment └── month-bar-prototype Dropbox/Code Runner Scratchspace: ├── AdventOfCode2020 ├── FunctionalBoardGame ├── FunctionalBoardGame.swift ├── GenericsSpace ├── GenericsSpace.swift ├── NSArray-First-N-Elements.m ├── OpaqueReturnTypes.swift ├── Output-Bytes-of-Data-Type.swift ├── URL Construction.swift iMac Code Sketches: ├── dearPyGui │ ├── README.md │ └── hello.py ├── deno │ ├── README.md │ ├── app.ts │ └── oak-rest-api ├── iOS │ ├── EmojiHunter │ └── TimeScrubberControl ├── javascript-lang-fundamentals │ ├── Promises │ └── string-interpolation.js ├── nodejs │ ├── exploreFileSystem │ └── simpleServer ├── rails │ └── imageserver ├── sapper-stuff │ └── babylon ├── stimulusjs │ ├── README.md │ ├── stimulus-starter │ └── stimulus-without-build-system └── svelte-livestream └── svelte-project iMac Code for Twitch: ├── Apple-Swift-UI-Tutorial ├── BigList-Catalyst ├── HackingWithSwift-SwiftUI └── SwiftUI-PlayPen-Twitch iMac Git Repos: ├── Athena ├── Brainshots ├── OnboardingScreen ├── Project-Healthboost ├── StreakEngine-deleteme ├── ToastLab ├── Wisdom ├── dailylog ├── dailylog-streaks ├── data-sources-in-memory ├── daystream-website ├── dot-plan ├── focus-app ├── <name>.github.io ├── playsounds ├── streakkit ├── streakkit-client └── yapdatabaseexploration MBP Code Sketches: ├── deno-lab └── go-lab MBP Git Repos: ├── Athena ├── Code\ Sketches │ └── emoji-detection-in-ios ├── FileSystemAccess-MacApp ├── PlaySounds ├── UIKitFundamentals ├── Wisdom ├── combine-lab ├── dailylog ├── data-sources-in-memory ├── dot-plan ├── focus-app ├── kidbits.html ├── streakengine-swift ├── streakkit └── streaks-r-d Dashboards: ├── Dashboard ├── Dashboard-of-Outcomes └── Dashboard-of-Tasks bitbucket daily-dashboard.git Dashboard bitbucket outcomes-dashboard.git Dashboard-of-Outcomes bitbucket projects-dashboard.git Dashboard-of-Tasks ➜ Tasks l _Archived-Completed Bluetooth Learning Learn-Docker Learn-Python-Basics ➜ Tasks l _Archived-Abandoned Automate-the-Boring-Stuff Dashboard-Projects-ScreenCapture Learn-Category-Theory-With-Haskell Learn-Rust Releases: Dashboards, scripts, Daily Log, Focus app? Tech: Python, Ruby, Swift, ObjC, Deno, Javascript
0 notes
Text
Crashlytics: Efficient Tools For Crash Reporting
Crashlytics: Efficient Tools For Crash Reporting
(No Ratings Yet) Loading...
Pham Van Hoang, [email protected], is the author of this article and he contributes to RobustTechHouse Blog
What is Crashlytics?
Crashlytics is a free tool for crash reporting for mobile apps offered by Twitter that capture crashes and various other information.
It is the best option for all your beta testing and crash reporting needs.
It covers crash reports, delivery, feedback, emails notification and much more.
It’s very easy to setup and install. Once installed, it instantly starts logging data (note that ‘Testflight’ needs a review period for beta builds – sometimes it could take a day for beta reviewing).
It’s completely free and can be used on an unlimited number of apps with unlimited users examining unlimited crashes etc.
It presents all data with amazing visuals, making it very easy to interpret and debug accordingly.
It supports both Android and iOS.
Integrating Crashlytics
Step 1: Register Fabric accounts, Fabric includes Crashlytics and several other tools such as Answer, Digits, MoPub (some other useful tools). You may want to check out our last article about Digits – Free Login And Authentication For IOS Apps Using Phone Number.
Step 2: Download and install Fabric for Xcode
Step 3: Select the project that you want to integrate Crashlytics and install Crashlytics to the relevant project
The steps to install are pretty easy. Follow each step in the instructions until you get to this screen:
Once you’re done, you can archive your project and distribute to your testers
Check your email box, you will see the email from Crashlytics.
When you click view details, it will show the crash report screen of the project:
Let’s See How Crashlytics Works
Now, we just need to add some codes to force our app to crash to check out the report. Go to ViewController.m class and add the codes below.
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame = CGRectMake(20, 50, 100, 30); [button setTitle:@"Check crash" forState:UIControlStateNormal]; [button addTarget:self action:@selector(crashButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } - (IBAction)crashButtonTapped:(id)sender { NSArray *array = @[@"check"]; id accessOutOfArrayBounds= [array objectAtIndex:3]; }
You can see when we tap button “Check crash”, the function access the object at index 3, which is out of the array bounds. So it will cause our app to crash, run the app and click the “Check crash” button few times and refresh the report page.
Note: if you got the message “1 unsymbolicated crash from missing dSYMs in 1 version in the last 24 hours ” like above. You may need to check: how to upload missing dSYMs here?.
We just got the reports send from users telling about the crash occurs from line 31 , which is the exact function that we deliberately forced our app to crash. Note that it occurred 3 times and affected 1 user.
One of the great things about Crashlytics is the level of detail you’re given when a crash occurs. As a product owner, product manager, developer, you are able to quickly assess the risk the crash poses to your overall install base. You can see the issues and the number of crashes in each issue to determine which one need to be fix first. Also with the device and operation breakdown shown in the dashboard, you can determine if a particular crash is only occurring on iOS8 (or another version) or on a particular device. This is in my opinion is an enormous help to developers.
In our case, the problem is about accessing data out of array bounds, so you just need to check the index of object and fix it.
Pretty awesome huh! You can learn more about here Crashlytics for iOS.
Thank you for reading, if you have any questions, please leaves the comments below.
Brought to you by the RobustTechHouse team (A top app development company in Singapore). If you like our articles, please also check out our Facebook page.
Crashlytics: Efficient Tools For Crash Reporting was originally published on RobustTechHouse - Mobile App Development Singapore
0 notes
Text
NSJSONSerialization - Foundation | Apple Developer Documentation [はてなブックマーク]
NSJSONSerialization - Foundation | Apple Developer Documentation
You use the NSJSONSerialization class to convert JSON to Foundation objects and convert Foundation objects to JSON. A Foundation object that may be converted to JSON must have the following properties: The top level object is an NSArray or NSDictionary. All objects are instances of NSString, NSNu...
from kjw_junichiのはてなブックマーク https://ift.tt/2Rm51FB
0 notes
Text
Add Search to Table View iOS Tutorial
Most modern iOS apps have a feature of a search bar to search for items in a Table View. This tutorial will show how to add the search functionality to a Table View which let the user search through the items by specifying a search term. This tutorial is made with Xcode 10 and built for iOS 12.
Open Xcode and create a new Single View App.
For product name, use IOSAddSearchTableViewTutorial and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and choose Next.
Remove the View Controller from the Storyboard and drag a Navigation Controller to the empty canvas. When the initial View Controller is deleted there isn't a starting point defined. Select the Navigation Controller and go to the Attribute Inspector. In the View Controller Section select the "Is Initial View Controller" checkbox.
Double-click on the Navigation Bar in The Table View Controller and set the title to "Numbers". Select the Table View Cell and go to the Attributes Inspector. In the Table View Cell section set the Identifier to "Cell".
The Storyboard should look like this.
Since we have deleted the View Controller from the Storyboard we can also delete the ViewController.swift file. Add a new file to the project, select iOS->Source->Cocoa Touch Class. Name it TableViewController and make it a subclass of UITableViewController.
The TableViewController class needs to be linked to The Table View Controller object in the Storyboard. Select it and go the Identity Inspector. In the Custom Class section change the class to TableViewController.
Go to the TableViewController.swift file and change the class declaration line
class TableViewController: UITableViewController, UISearchResultsUpdating {
The UISearchResultsUpdating protocol updates the search results, later we will add a delegate method to let the TableViewController conform to this protocol. Add the following properties
let tableData = ["One","Two","Three","Twenty-One"] var filteredTableData = [String]() var resultSearchController = UISearchController()
The tableData property will hold the items of the Table View, where the filteredTableData property will contain the result from the search query. The Search Controller manages the results of the search. Change the viewDidLoad method to
override func viewDidLoad() { super.viewDidLoad() resultSearchController = ({ let controller = UISearchController(searchResultsController: nil) controller.searchResultsUpdater = self controller.dimsBackgroundDuringPresentation = false controller.searchBar.sizeToFit() tableView.tableHeaderView = controller.searchBar return controller })() // Reload the table tableView.reloadData() }
A closure is used which is assigned to the resultSearchController. The results of the search will be presented in the current Table View, so the searchResultsController parameter of the UISearchController init method is set to nil. Also, the searchResultsUpdater property is set to the current Table View Controller and the background dimming is set to false. The searchable is added to the Table View and the data is reloaded. Next, implement the Table View Data Source delegate methods
override func numberOfSections(in tableView: UITableView) -> Int { // 1 // return the number of sections return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 2 // return the number of rows if (resultSearchController.isActive) { return filteredTableData.count } else { return tableData.count } } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 3 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) if (resultSearchController.isActive) { cell.textLabel?.text = filteredTableData[indexPath.row] return cell } else { cell.textLabel?.text = tableData[indexPath.row] print(tableData[indexPath.row]) return cell } }
Only One section is being used
If the Search Controller is active the number of filtered items are assigned to the number of rows in the Table View, otherwise the tableData array is being used.
If the Search Controller is active, the filtered items are displayed, otherwise the original items of the tableData array are displayed.
Finally, implement the updateSearchResults(for:_) delegate method of the UISearchResultsUpdating protocol
func updateSearchResults(for searchController: UISearchController) { filteredTableData.removeAll(keepingCapacity: false) let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text!) let array = (tableData as NSArray).filtered(using: searchPredicate) filteredTableData = array as! [String] self.tableView.reloadData() }
The updateSearchResults(for:_) method is called when the user updates the Search bar with input. In this method we will handle the search filtering of our search term. NSPredicate is an sort of expression that handles the search criteria. "c" means case-sensitive. The results are then assigned to the filteredTableData array and the Table View is reloaded. Build and Run the project, enter a search query and the results are being displayed.
You can download the source code of the IOSAddSearchTableViewTutorial at the ioscreator repository on Github.
0 notes
Text
The 10 Most Common Mistakes iOS Developers Don't Know They're Making
What’s the only thing worse than having a buggy app rejected by the App Store? Having it accepted. Once the one-star reviews start rolling in, it’s almost impossible to recover. This costs companies money and developers their jobs. iOS is now the second-largest mobile operating system in the world. It also has a very high adoption rate, with more than 85% of users on the latest version. As you might expect, highly engaged users have high expectations—if your app or update isn’t flawless, you’ll hear about it. With the demand for iOS developers continuing to skyrocket, many engineers have switched to mobile development (more than 1,000 new apps are submitted to Apple every day). But true iOS expertise extends far beyond basic coding. Below are 10 common mistakes that iOS developers fall prey to, and how you can avoid them.

85% of iOS users use the latest OS version. That means they expect your app or update to be flawless.
Common Mistake #1: Not Understanding Asynchronous Processes
A very common type of mistake among new programmers is handling asynchronous code improperly. Let’s consider a typical scenario: User opens a screen with the table view, some data is fetched from the server and displayed in a table view. We can write it more formally: @property (nonatomic, strong) NSArray *dataFromServer; - (void)viewDidLoad { __weak __typeof(self) weakSelf = self; latestDataWithCompletionBlock:^(NSArray *newData, NSError *error){ weakSelf.dataFromServer = newData; // 1 }]; ; // 2 } // and other data source delegate methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataFromServer.count; } At first glance, everything looks right: We fetch data from the server and then update the UI. However, the problem is fetching data is an asynchronous process, and won’t return new data immediately, which means reloadData will be called before receiving the new data. To fix this mistake, we should move line #2 right after line #1 inside the block. @property (nonatomic, strong) NSArray *dataFromServer; - (void)viewDidLoad { __weak __typeof(self) weakSelf = self; latestDataWithCompletionBlock:^(NSArray *newData, NSError *error){ weakSelf.dataFromServer = newData; // 1 ; // 2 }]; } // and other data source delegate methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataFromServer.count; } However, there may be situations where this code still does not behave as expected, which brings us to …
Common Mistake #2: Running UI-Related Code on a Thread Other than the Main Queue
Let’s imagine we used corrected code example from the previous common mistake, but our table view is still not updated with the new data even after the asynchronous process has successfully completed. What might be wrong with such simple code? To understand it, we can set a breakpoint inside the block and find out on which queue this block is called. There is a high chance the described behavior is happening because our call is not in the main queue, where all UI-related code should be performed. Most popular libraries—such as Alamofire, AFNetworking, and Haneke—are designed to call completionBlockon the main queue after performing an asynchronous task. However, you can’t always rely on this and it is easy to forget to dispatch your code to the right queue. To make sure all your UI-related code is on the main queue, don’t forget to dispatch it to that queue: dispatch_async(dispatch_get_main_queue(), ^{ ; });
Common Mistake #3: Misunderstanding Concurrency & Multithreading
Concurrency could be compared to a really sharp knife: You can easily cut yourself if you’re not careful or experienced enough, but it’s extremely useful and efficient once you know how to use it properly and safely. You can try to avoid using concurrency, but no matter what kind of apps you’re building, there is really high chance you can’t do without it. Concurrency can have significant benefits for your application. Notably: Almost every application has calls to web services (for example, to perform some heavy calculations or read data from a database). If these tasks are performed on the main queue, the application will freeze for some time, making it non-responsive. Moreover, if this takes too long, iOS will shut down the app completely. Moving these tasks to another queue allows the user to continue use the application while the operation is being performed without the app appearing to freeze. Modern iOS devices have more than one core, so why should the user wait for tasks to finish sequentially when they can be performed in parallel? But the advantages of concurrency don’t come without complexity and the potential for introducing gnarly bugs, such as race conditions that are really hard to reproduce. Let’s consider some real-world examples (note that some code is omitted for simplicity). Case 1 final class SpinLock { private var lock = OS_SPINLOCK_INIT func withLock(@noescape body: () -> Return) -> Return { OSSpinLockLock(&lock) defer { OSSpinLockUnlock(&lock) } return body() } } class ThreadSafeVar { private let lock: ReadWriteLock private var _value: Value var value: Value { get { return lock.withReadLock { return _value } } set { lock.withWriteLock { _value = newValue } } } } The multithreaded code: let counter = ThreadSafeVar(value: 0) // this code might be called from several threads counter.value += 1 if (counter.value == someValue) { // do something } At first glance, everything is synced and appears as if it should work as expected, since ThreadSaveVar wraps counter and makes it thread safe. Unfortunately, this is not true, as two threads might reach the increment line simultaneously and counter.value == someValue will never become true as a result. As a workaround, we can make ThreadSafeCounter which returns its value after incrementing: class ThreadSafeCounter { private var value: Int32 = 0 func increment() -> Int { return Int(OSAtomicIncrement32(&value)) } } Case 2 struct SynchronizedDataArray { private let synchronizationQueue = dispatch_queue_create("queue_name", nil) private var _data = () var data: { var dataInternal = () dispatch_sync(self.synchronizationQueue) { dataInternal = self._data } return dataInternal } mutating func append(item: DataType) { appendItems() } mutating func appendItems(items: ) { dispatch_barrier_sync(synchronizationQueue) { self._data += items } } } In this case, dispatch_barrier_sync was used to sync access to the array. This is a favorite pattern to ensure access synchronization. Unfortunately, this code doesn’t take into account that struct makes a copy each time we append an item to it, thus having a new synchronization queue each time. Here, even if it looks correct at first sight, it might not work as expected. It also requires a lot of work to test and debug it, but in the end, you can improve your app speed and responsiveness.
Common Mistake #4: Not Knowing Pitfalls of Mutable Objects
Swift is very helpful in avoiding mistakes with value types, but there are still a lot of developers who use Objective-C. Mutable objects are very dangerous and can lead to hidden problems. It is a well-known rule that immutable objects should be returned from functions, but most developers don’t know why. Let’s consider the following code: // Box.h @interface Box: NSObject @property (nonatomic, readonly, strong) NSArray *boxes; @end // Box.m @interface Box() @property (nonatomic, strong) NSMutableArray *m_boxes; - (void)addBox:(Box *)box; @end @implementation Box - (instancetype)init { self = ; if (self) { _m_boxes = ; } return self; } - (void)addBox:(Box *)box { ; } - (NSArray *)boxes { return self.m_boxes; } @end The code above is correct, because NSMutableArray is a subclass of NSArray. So what can go wrong with this code? The first and the most obvious thing is that another developer might come along and do the following: NSArray *childBoxes = ; if (]) { // add more boxes to childBoxes } This code will mess up your class. But in that case, it’s a code smell, and it’s left up to that developer to pick up the pieces. Here is the case, though, that is much worse and demonstrates an unexpected behavior: Box *box = init]; NSArray *childBoxes = ; init]]; NSArray *newChildBoxes = ; The expectation here is that > , but what if it is not? Then the class is not well designed because it mutates a value that was already returned. If you believe that inequality should not be true, try experimenting with UIView and . Luckily, we can easily fix our code, by rewriting the getter from the first example: - (NSArray *)boxes { return ; }
Common Mistake #5: Not Understanding How iOS NSDictionary Works Internally
If you ever worked with a custom class and NSDictionary, you might realize you cannot use your class if it doesn’t conform to NSCopying as a dictionary key. Most developers have never asked themselves why Apple added that restriction. Why does Apple copy the key and use that copy instead of the original object? The key to understanding this is figuring out how NSDictionary works internally. Technically, it’s just a hash table. Let’s quickly recap how it works on a high level while adding an Object for a Key (table resizing and performance optimization is omitted here for simplicity): Step 1: It calculates hash(Key). Step 2: Based on the hash, it looks for a place to put the object. Usually, this is done by taking the modulus of the hash value with the dictionary length. The resulting index is then used to store the Key/Value pair. Step 3: If there is no object in that location, it creates a linked list and stores our Record (Object and Key). Otherwise, it appends Record to the end of the list. Now, let’s describe how a record is fetched from the dictionary: Step 1: It calculates hash(Key). Step 2: It searches a Key by hash. If there is no data, nil is returned. Step 3: If there is a linked list, it iterates through the Object until . With this understanding of what is occurring under the hood, two conclusions can be drawn: If the Key’s hash changes, Record should be moved to another linked list. Keys should be unique. Let’s examine this on a simple class: @interface Person @property NSMutableString *name; @end @implementation Person - (BOOL)isEqual:(id)object { if (self == object) { return YES; } if (!]) { return NO; } return ; } - (NSUInteger)hash { return ; } @end Now imagine NSDictionary doesn’t copy Keys: NSMutableDictionary *gotCharactersRating = init]; Person *p = init]; p.name = @"Job Snow"; gotCharactersRating = @10; Oh! We have a typo there! Let’s fix it! p.name = @"Jon Snow"; What should happen with our dictionary? As the name was mutated, we now have a different hash. Now our Object lies in the wrong place (it still has the old hash value, as the Dictionary doesn’t know about the data change), and it’s not really clear what hash we should use to lookup data in the dictionary. There could be an even worse case. Imagine if we already had “Jon Snow” in our dictionary with a rating of 5. The dictionary would end up with two different values for the same Key. As you can see, there are many problems that can arise from having mutable keys in NSDictionary. The best practice to avoid such issues is to copy the object before storing it, and to mark properties as copy. This practice will also help you to keep your class consistent.
Common Mistake #6: Using Storyboards Instead of XIBs
Most new iOS developers follow Apple’s suggestion and use Storyboards by default for the UI. However, there are a lot of drawbacks and only a few (debatable) advantages in using Storyboards. Storyboard drawbacks include: It’s really hard to modify a Storyboard for several team members. Technically, you can use many Storyboards, but the only advantage, in that case, is making it possible to have segues between controllers on the Storyboard. Controllers and segues names from Storyboards are Strings, so you have to either re-enter all those Strings throughout your code (and one day you will break it), or maintain a huge list of Storyboard constants. You could use SBConstants, but renaming on the Storyboard is still not an easy task. Storyboards force you into a non-modular design. While working with a Storyboard, there is very little incentive to make your views reusable. This may be acceptable for the minimum viable product (MVP) or quick UI prototyping, but in real applications you might need to use the same view several times across your app. Storyboard (debatable) advantages: The whole app navigation can be seen at a glance. However, real applications can have more than ten controllers, connected in different directions. Storyboards with such connections look like a ball of yarn and don’t give any high-level understanding of data flows. Static tables. This is the only real advantage I can think of. The problem is that 90 percent of static tables tends to turn into dynamic tables during app evolution and a dynamic table can be more easily handled by XIBs.
Common Mistake #7: Confusing Object & Pointer Comparison
While comparing two objects, we can consider two equality: pointer and object equality. Pointer equality is a situation when both pointers point to the same object. In Objective-C, we use ==operator for comparing two pointers. Object equality is a situation when two objects represent two logically identical objects, like the same user from a database. In Objective-C, we use isEqual, or even better, type specific isEqualToString, isEqualToDate, etc. operators for comparing two objects. Consider the following code: NSString *a = @"a"; // 1 NSString *b = @"a"; // 2 if (a == b) { // 3 NSLog(@"%@ is equal to %@", a, b); } else { NSLog(@"%@ is NOT equal to %@", a, b); } What will be printed out to the console when we run that code? We will get a is equal to b, as both objects a and b are pointing to the same object in memory. But now let’s change line #2 to: NSString *b = copy]; Now we get a is NOT equal to b since these pointers are now pointing to different objects even though those objects have the same values. This problem can be avoided by relying on isEqual, or type specific functions. In our code example, we should replace line #3 with following code for it to always work properly: if () {
Common Mistake #8: Using Hardcoded Values
There are two primary problems with hardcoded values: It’s often not clear what they represent. They need to be re-entered (or copied and pasted) when they need to be used in multiple places in the code. Consider the following example: if ( timeIntervalSinceDate:self.lastAppLaunch] // do something } or ; ... ; What does 172800 represent? Why is it being used? It is probably not obvious that this corresponds to the number of seconds in 2 days (there are 24 x 60 x 60, or 86,400, seconds in a day). Rather than using hardcoded values, you could define a value using the #define statement. For example: #define SECONDS_PER_DAY 86400 #define SIMPLE_CELL_IDENTIFIER @"SimpleCell" #define is a preprocessor macro that replaces the named definition with its value in the code. So, if you have #define in a header file and import it somewhere, all occurrences of the defined value in that file will be replaced too. This works well, except for one issue. To illustrate the remaining problem, consider the following code: #define X = 3 ... CGFloat y = X / 2; What would you expect the value of y to be after this code executes? If you said 1.5, you are incorrect. y will be equal to 1 (not 1.5) after this code executes. Why? The answer is that #define has no information about the type. So, in our case, we have a division of two Int values (3 and 2), which results in an Int (i.e., 1) which is then cast to a Float. This can be avoided by using constants instead which are, by definition, typed: static const CGFloat X = 3; ... CGFloat y = X / 2; // y will now equal 1.5, as expected
Common Mistake #9: Using Default Keyword in a Switch Statement
Using the default keyword in a switch statement can lead to bugs and unexpected behavior. Consider the following code in Objective-C: typedef NS_ENUM(NSUInteger, UserType) { UserTypeAdmin, UserTypeRegular }; - (BOOL)canEditUserWithType:(UserType)userType { switch (userType) { case UserTypeAdmin: return YES; default: return NO; } } The same code written in Swift: enum UserType { case Admin, Regular } func canEditUserWithType(type: UserType) -> Bool { switch(type) { case .Admin: return true default: return false } } This code works as intended, allowing only Admin users to be able to change other records. However, what might happen we add another user type Manager that should be able to edit records as well? If we forget to update this switch statement, the code will compile, but it will not work as expected. However, if the developer used enum values instead of the default keyword from the very beginning, the oversight will be identified at compile time, and could be fixed before going to test or production. Here is the good way to handle this in Objective-C: typedef NS_ENUM(NSUInteger, UserType) { UserTypeAdmin, UserTypeRegular, UserTypeManager }; - (BOOL)canEditUserWithType:(UserType)userType { switch (userType) { case UserTypeAdmin: case UserTypeManager: return YES; case UserTypeRegular: return NO; } } The same code written in Swift: enum UserType { case Admin, Regular, Manager } func canEditUserWithType(type: UserType) -> Bool { switch(type) { case .Manager: fallthrough case .Admin: return true case .Regular: return false } }
Common Mistake #10: Using NSLog for Logging
Many iOS developers use NSLog in their apps for logging, but most of the time this is a terrible mistake. If we check the Apple documentation for the NSLog function description, we will see it is very simple: void NSLog(NSString *format, ...); What could possibly go wrong with it? In fact, nothing. However, if you connect your device to the XCode Organizer, you’ll see all your debug messages there. For this reason alone, you should never use NSLog for logging: it’s easy to show some unwanted internal data, plus it looks unprofessional. Better approach is to replace NSLogs with configurable CocoaLumberjack or some other logging framework.
Wrap Up
iOS is a very powerful and rapidly evolving platform. Apple makes a massive ongoing effort to introduce new hardware and features for iOS itself, while also continually expanding the Swift language. Improving your Objective-C and Swift skills will make you a great iOS developer and offer opportunities to work on challenging projects using cutting-edge technologies. Source: https://www.toptal.com/ios/top-ios-development-mistakes Read the full article
#appdeveloper#appdeveloperalliance#appdeveloperbali#appdevelopercompany#appdeveloperforhire#appdeveloperindia#appdeveloperinmaking#appdeveloperinthemaking#appdeveloperintraining#appdeveloperlife#appdevelopermalaysia#appdevelopermelbourne#appdeveloperproblems#appdevelopers#appdevelopersabudhabi#appdevelopersaustralia#appdevelopersdurban#appdevelopersindubai#appdevelopersingapore#appdevelopersinindore#appdevelopersjaipur#appdeveloperssouthafrica#appdevelopersuae#appdevelopersusa#appdeveloperswanted#appdeveloperswelcomed#appdeveloperusa#appdeveloperwanted#appdeveloperwithanapp#appdeveloper📱
0 notes
Text
An iOS developer must know
1 — Source control
Congrats you were employed! presently bring the code from the repo and get the opportunity to work. hold up what? each undertaking will require source control, regardless of whether you are the main dev. the most widely recognized ones are git and svn.
Sync depends on a concentrated framework for form administration. it's a focal archive where working duplicates are created and a system association is required for access. its entrance approval is way based, it tracks changes by enrolling documents and the change history must be seen, completely, in the vault. working duplicates just contain the most up to date form.
Git depends on a circulated framework for adaptation administration. you will have a neighbourhood store on which you can work, with a system association just required to synchronize. its entrance approval is for the whole catalogue, tracks changes by enrolling content and both the archive and working duplicates have the entire change history, Learn IOS training in Chennai at Greens Technologys .
2 — Architecture designs
Your fingers are jerking with energy, you made sense of source control! or on the other hand was that the espresso? doesn't make a difference! you are in the zone and it's an ideal opportunity to code! not a chance. what pause?
Before you begin pounding your console, you need to pick a design example to set up. on the off chance that you aren't beginning the undertaking, you need to fit in with the actualized design. there is a wide cluster of examples utilized in portable application improvement, mvc, mvp, mvvm, snake, and so forth I will give you a brisk review of the most usually utilized in ios advancement:
Mica — short for model, see, controller. the controller makes the extension between the model and the view, which are uninformed of one another. the association between the view and the controller is tight-sew, along these lines, the controller winds up taking care of pretty much everything. what does this mean? basically, in case you're fabricating a perplexing perspective, your controller (viewcontroller) will be madly enormous. there are approaches to go around this, anyway they resist the tenets of mvc. another drawback to mvc would test. on the off chance that you do tests (great on you!), you will presumably just test the model, because of it being the main layer isolate from the rest. the in addition to of utilizing the mvc design is that it's natural and most ios engineers are utilized to it.
Mvvm — short for model, see, viewmodel. ties (essentially responsive writing computer programs) are setup between the view and the viewmodel, this permits the viewmodel to conjure changes on the model, which at that point refreshes the viewmodel, consequently refreshing the view because of the ties. the viewmodel remains unaware of the view, which encourages testing and ties decrease a ton of code.
3 — Objective-c versus quick
When choosing which dialect you will programme your application in, you have to realize what every dialect conveys to the table. whenever given the choice, I for one, recommend utilizing quick. why? truly objective-c has not very many favorable circumstances over quick. the vast majority of the precedents and instructional exercises are composed in target c and with each refresh to quick, changes are made to the standards, which can be debilitating. in any case, these are issues that over the long haul will blur away.
Quick truly jumps ahead from various perspectives. it's anything but difficult to peruse, takes after characteristic english and in light of the fact that it's not based on c, it drops inheritance traditions. to the individuals who know objective-c, this implies no more semi-colons, technique calls don't require sections and no requirement for brackets to encompass restrictive articulations. it's likewise less demanding to keep up your code, quick just needs a .quick document rather than a .h and a .m record, in light of the fact that xcode and the llvm compiler can make sense of conditions and perform incremental forms naturally. by and large you should stress less over making standard code and find that you can accomplish similar outcomes with less code.
Not persuaded? quick if more secure, quicker and deals with memory management(most of it!). know what occurs in goal c when you call a strategy with a uninitialised pointer variable? nothing. the articulation turns into a no-operation and is skipped. sounds extraordinary on the grounds that it doesn't crash the application, in any case, it prompts a progression of bugs and inconsistent conduct that will make you need to reexamine your vocation. I sh*t you not. being an expert puppy walker just turned into somewhat more engaging. quick neutralizes this with optionals. not exclusively will you have a superior thought of what can be nil and set certifications into place to counteract nil being utilized, however in the event that a nil discretionary gets utilized, quick will trigger a runtime crash, encouraging investigating. memory-wise and put essentially, bend (programmed reference including) improves quick. in target c, circular segment doesn't work for procedural c code and apis like center illustrations.
4--To React or not to React?
Utilitarian responsive programming (frp) is the new prevailing fashion it appears. its will likely empower simple sythesis of nonconcurrent activities and occasion/information streams.
least demanding approach to represent is with a touch of code. suppose little timmy and his sister, jenny, need to purchase another gaming console. timmy gets 5€ from his folks consistently, same goes for jenny. anyway jenny makes another 5€ by conveying daily papers on ends of the week. on the off chance that they both spare each penny, we can check each week if the support is achievable! each time one of their funds is influenced, their consolidated esteem is computed. on the off chance that it is sufficient, a message is spared in the variable isconsoleattainable. anytime we can check the message by buying in to it.
5 — Dependency administrator
Cocoapods and carthage are the most widely recognized reliance supervisors for quick and goal c cocoa ventures. they disentangle the way toward executing a library and keeping it refreshed.
Carthage is a decentralized reliance director, contrary to cocoapods. drawback to this is it turns out to be more troublesome for clients to locate the current libraries. then again, it requires less upkeep work and keeps away from any main issue of disappointment.
6 — Storing data
Let’s begin with a basic method for sparing information for your applications. nsuserdefaults, called along these lines, since it's by and large used to spare default client information, that is placed in when the application is first stacked. thus it's made to be straightforward and simple to utilize, anyway this infers a few impediments. one of it's impediments is the kind of articles it acknowledges. it acts particularly like a property list (plist), which likewise has a similar impediment. the six sort of articles they can store are the accompanying:
nsdata
nsdate
nsnumber
nsdictionary
nsstring
nsarray
To be perfect with quick, nsnumber can acknowledge the accompanying:
uint
int
skim
twofold
bool
Articles can be spared to nsuserdefaults in the accompanying way (first make a consistent that will keep the key for the protest we are sparing):
There are a few comfort strategies for perusing and writing to nsuserdefaults, that get particular questions rather than an anyobject.
Keychain is a secret phrase administration framework and can contain passwords, endorsements, private keys or private notes. the keychain has two levels of gadget encryption. the main level uses the bolt screen password as the encryption key. the second level uses a key created by and put away on the gadget.
What does this mean? it's not precisely super protected, uniquely on the off chance that you don't utilize a bolt screen password. there are likewise approaches to get to the key utilized on the second level, since it's saved money on the gadget.
Best arrangement is to utilize your own encryption. (try not to store the key on the gadget)
Coredata is a structure outlined by apple, for your application to speak with it's database in a protest arranged way. it rearranges the procedure, diminishing the code and evacuating the need to test that segment of code.
You should utilize it if your application requires tireless information, it improves the way toward holding on information a lot and means you don't need to fabricate your own particular manner of speaking with a db or testing it either.
7 — Collectionviews and tableviews
Pretty much every application has at least one gathering sees as well as table perspectives. knowing how they function, and when to utilize either, will anticipate confused changes to your application later on.
Tableviews show a rundown of things, in a solitary section, a vertical mold, and constrained to vertical looking over as it were. every thing is spoken to by a uitableviewcell, that can be totally modified. these can be arranged into areas and lines.
Collectionviews likewise show a rundown of things, be that as it may, they can have various sections and columns (lattice for instance). they can scroll on a level plane as well as vertically, and every thing is spoken to by a uicollectionviewcell. much the same as uitableviewcells, these can be redone voluntarily, and are arranged into segments and columns.
They both have comparative usefulness and utilize reusable cells to enhance ease. picking which one you require relies upon the multifaceted nature you need the rundown to have. a gathering perspective can be utilized to speak to any rundown and, as I would like to think, is dependably a decent decision. envision you need to speak to a contact list. it's straightforward, should be possible with only one segment, so you choose a uitableview. extraordinary it works! hardly any months down the line, your planner chooses that the contacts ought to be shown in framework design, rather than rundown arrange. the main way you can do this, is to change your uitableview usage to a uicollectionview execution. what i'm endeavoring to get at is, despite the fact that your rundown may be straightforward and a uitableview can do the trick, if there is a decent possibility the plan will change, it's presumably best to imlpement the rundown with a uicollectionview.
Whichever you wind up picking, it's a smart thought to make a non specific tableview/collectionview. it makes execution less demanding and enables you to reutilize a ton of code.
8 — Storyboards versus xibs versus automatic ui
Every one of these techniques can be utilized independently to make a ui, anyway nothing keeps you from joining them.
Storyboards permit a more extensive perspective of the venture, which planners love, since they can see the application stream and the majority of the screens. the drawback is that as more screens are included, the associations turn out to be all the more confounding and storyboard stack time is expanded. blend strife issues happen much more regularly, on the grounds that the entire ui has a place with one record. they are likewise much more hard to determine.
xibs give a visual perspective of screens or bits of a screen. their points of interest are simplicity of reuse, less union clashes than the storyboard approach and a simple method to perceive what's on each screen.
Programming your ui gives you a considerable measure of authority over it, less union clashes and, in the event that they do happen, are anything but difficult to fathom. drawback is the absence of visual guide and additional time it will take to program.
There are altogether different ways to deal with making your application's ui. it's very abstract, in any case, what I consider the best methodology is a mix of each of the 3. numerous storyboards (now that we can segue between storyboards!), with xibs for any visual that is anything but a principle screen and, at last, a pinch of programming for the additional control required in specific circumstances.
9 — Protocols!
Conventions exist in our day by day lives to ensure, in a given circumstance, we know how to respond. for instance, suppose you are a fire fighter and a crisis circumstance arrises. each fire fighter needs to fit in with the convention that sets the prerequisites to effectively react. the equivalent applies to a quick/objective-c convention.
A convention characterizes a draft of the strategies, properties and different necessities for given functionalities. it tends to be embraced by a class, a structure or a list, that will at that point have a real execution of those necessities.
IOS @ Greens Technologys
If you are seeking to get a good IOS training in Chennai, then Greens Technologys should be the first and the foremost option.
We are named as the best training institute in Chennai for providing the IT related trainings. Greens Technologys is already having an eminent name in Chennai forproviding the best software courses training.
We have more than 115 courses for you. We offer both online and physical training along with the flexible timings so as to ease the things for you.
0 notes
Text
Finder Sync Extension
The macOS Finder Sync Extension allows extending the Finder’s UI to show the file synchronization status. Apple’s documentation on the macOS FinderSyncExtension is good, but it lacks more info on communication between the MainApp and the Finder Sync Extension. In this article, one such example is shown as a possible solution for bidirectional communication between the two.
Creating the extension
Once you’ve created your macOS project, select the project in the project navigator and add the new target “Finder Sync Extension”.
Sandboxing
Depending on your project’s needs, you may want/need to disable the App Sandbox. If your project is going to use a virtual file system such as osxfuse, the App Sandbox needs to be disabled.
You’ll have to leave the App Sandbox enabled for the Finder Sync Extension though. Set ‘User Selected File’ permissions to None in the Finder Sync Extension. If you leave it to ‘Read Only’, which it is by default, the extension won’t be able to receive messages from the MainApp.
App groups
To be able to communicate with one another, the MainApp and the Finder Sync Extension must belong to the same App Group. Create an App Group in a pattern like: group.[app-bundle-id]
What the demo app demonstrates
The demo application consists of two components: FinderSyncExample and FinderSyncExtension. FinderSyncExample is what we call the ‘MainApp’. When started, the MainApp offers a path to a demo folder which will be created when the Set button is pressed. After successful folder creation, the app shows controls for modifying file sync statuses. Beneath the controls, there is a label showing a custom message which can be sent from the Finder extension menu.
MainApp updating file statuses in the Finder
It is possible to set a status for three files: file1.txt, file2.txt and file3.txt. Select a desired status from combo-box and tap the appropriate Set button. Observe how Finder applies sync status to the relevant file.
Finder sending message to the MainApp
On the Finder window, open the SyncExtension menu and select ‘Example Menu Item’ on it. Observe how on the MainApp window message-label is updated to show a message received from the Finder.
Multiple FinderSyncExtension instances can exist simultaneously
It is possible that more than one Finder Sync Extension is running. One Finder Sync Extension can be running in a regular Finder window. The other FinderSyncExtension process can be running in an open-file or save-document dialog. In that case, MainApp has to be able to update all FinderSyncExtension instances. Keep this in mind when designing the communication between the MainApp and the FinderSyncExtension.
Bidirectional communication
Communication between the MainApp and the FinderSyncExtension can be implemented in several ways. The concept described in this article relies on Distributed Notifications. Other options may include mach_ports, CFMessagePort or XPC. We chose Distributed Notifications because it fits with the One-application – Multiple-extensions concept.
Both the MainApp and the FinderSyncExtension processes are able to subscribe to certain messages. Delivering and receiving messages is like using the well-known NSNotificationCenter.
Sending a message from MainApp to FinderSyncExtension
To be able to receive notifications, FinderSyncExtension registers as an observer for certain notifications:
NSString* observedObject = self.mainAppBundleID; NSDistributedNotificationCenter* center = [NSDistributedNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(observingPathSet:) name:@"ObservingPathSetNotification" object:observedObject]; [center addObserver:self selector:@selector(filesStatusUpdated:) name:@"FilesStatusUpdatedNotification" object:observedObject];
The relevant code is available in the FinderCommChannel class.
For the MainApp to be able to send a message to FinderSyncExtension, use NSDistributedNotificationCenter:
NSDistributedNotificationCenter* center = [NSDistributedNotificationCenter defaultCenter]; [center postNotificationName:name object:NSBundle.mainBundle.bundleIdentifier userInfo:data deliverImmediately:YES];
More details are available in the AppCommChannel class. AppCommChannel belongs to the MainApp target. It handles sending messages to FinderSyncExtension and receiving messages from the extension. FinderCommChannel belongs to FinderSyncExtension target. It handles sending messages to the MainApp and receiving messages from the MainApp.
Throttling messages
In real-world apps, it can happen that an app wants to update the sync status of many files in a short time interval. For that reason, it may be a good idea to gather such updates and send them all in one notification. macOS will complain about sending too many notifications in a short interval. It can also give up on delivery of notifications in such cases. The AppCommChannel class shows the usage of NSTimer for throttling support. A timer checks every 250ms if there are queued updates to be delivered to FinderSyncExtension.
For a clearer display, a sequence diagram showing sending messages from the MainApp to FinderSyncExtension is given bellow.
Sending messages from FinderSyncExtension to MainApp
To send a message from FinderSync to the MainApp, NSDistributedNotificationCenter is used but in slightly different way:
- (void) send:(NSString*)name data:(NSDictionary*)data { NSDistributedNotificationCenter* center = [NSDistributedNotificationCenter defaultCenter]; NSData* jsonData = [NSJSONSerialization dataWithJSONObject:data options:0 error:nil]; NSString* json = [NSString.alloc initWithData:jsonData encoding:NSUTF8StringEncoding]; [center postNotificationName:name object:json userInfo:nil deliverImmediately:YES]; }
Notice that the JSON string is sent as the object of the notification, and not in the userInfo. That is necessary for these notifications to work properly.
Restarting FinderSyncExtension on app launch
Sometimes, it may be useful to restart the extension when your MainApp is launched. To do that, execute the following code when MainApp launches (i.e. in didFinishLaunchingWithOptions method):
+ (void) restart { NSString* bundleID = NSBundle.mainBundle.bundleIdentifier; NSString* extBundleID = [NSString stringWithFormat:@"%@.FinderSyncExt", bundleID]; NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:extBundleID]; ASTEach(apps, ^(NSRunningApplication* app) { NSString* killCommand = [NSString stringWithFormat:@"kill -s 9 %d", app.processIdentifier]; system(killCommand.UTF8String); }); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSString* runCommand = [NSString stringWithFormat:@"pluginkit -e use -i %@", extBundleID]; system(runCommand.UTF8String); }); }
Debugging
Debugging the FinderSyncExtension is pretty straightforward. Some options are described below.
Debugging with Xcode alone
It is possible to debug both MainApp and FinderSyncExtension simultaneously. First, start the MainApp running the Xcode target. Then, set the FinderSyncExtension scheme and run it. Set breakpoints in desired places in the MainApp source and in the FinderSyncExtension source. Sometimes, the FinderSyncExtension debug session may not be attached to the relevant process. In that case, it helps to relaunch the Finder: press Alt+Cmd+Escape to bring Force Quit Application dialog and then select the Finder and relaunch it.
Xcode should now attach the debug session properly to the new process.
Debugging with AppCode + Xcode
If you’re using AppCode, then you can launch the MainApp form AppCode and FinderSyncExtension from the Xcode. This way, you can see both logs and debug sessions a bit easier.
Troubleshooting
It could happen that, even though the MainApp and FinderSync processes are running, no file sync statuses are shown. It can also happen that the requestBadgeIdentifierForURL method is not being called at all. If that happens, check if you have other FinderSyncExtensions running on your MBP (ie Dropbox, pCloud…). You can check that in System Preferences -> Extensions -> Finder. Disable all extensions except your demo FinderSyncExtension and then see if the issue is still present.
Testing
It seems that there is not much room when it comes to testing the FinderSyncExtension. At the time of writing this post, the only way to test the extension would be to refactor the code into a framework and then have the framework tested.
Conclusion
FinderSyncExtension is a great way to show file sync statuses. Hopefully, you now have a better understanding on how to develop the extension. Solutions shown in this article are designed to be simple yet powerful enough to face real-world use cases.
Useful links
Demo project on bitbucket Finder Sync Extension FinderSync Class Human Interface Guidelines Distributed Notifications Inter-Process Communication JNWThrottledBlock – Simple throttling of blocks Open source project using mach ports for bidirectional communication
Der Beitrag Finder Sync Extension erschien zuerst auf codecentric AG Blog.
Finder Sync Extension published first on https://medium.com/@koresol
0 notes
Photo

Objective C :- NSMutableDictionary With (Binding) NSArray in iOS Latest 2017(Hindi) iOS(Video) :- An introduction using the NSMutableDictionary in Objective-C By Yogesh Patel. Source Code:- ME!
0 notes
Text
NSUserDefaults
One method we could use is NSUserDefaults. It is best when used for little bits of information like user preferences, but not for larger things like UIImages.
NSUserDefaults is read and written atomically. This means when you write something to it, the whole thing needs to be written again. And when you read one key from it, it reads the whole thing and presents just the key you requested. This is good for making sure the data is read and written correctly, but might effect performance if the amount of data in NSUserDefaults is large. It is cached after the initial app load, so subsequent reads should be quite fast, but the initial one could be slow.
NSUserDefaults is like a Property List or plist that saves stuff to the iOS defaults system. There are six data types it can store:
NSData NSString NSNumber UInt Int Float Double Bool NSDate NSArray NSDictionary
Initialising NSUserDefaults:
public let defaults = NSUserDefaults.standardUserDefaults()
Writing to NSUserDefaults:
defaults.setBool(value: Bool, forKey defaultName: String) defaults.setInteger(value: Int, forKey defaultName: String) defaults.setFloat(value: Float, forKey defaultName: String) defaults.setDouble(value: Double, forKey defaultName: String) defaults.setObject(value: AnyObject?, forKey defaultName: String) defaults.setURL(url: NSURL?, forKey defaultName: String) e.g. defaults.setBool(true, forKey: "myGroovyKey") defaults.setObject("myGroovyValue", forKey: "myGroovyKey")
The limit for how much data can be stored in NSUserDefaults is the maximum file size for iOS (logically), which is currently 4GB. But for large amounts of data storage, a good idea might be to use something else like core data.
Reading from NSUserDefaults:
defaults.boolForKey("myGroovyKey") defaults.integerForKey("myGroovyKey") defaults.floatForKey("myGroovyKey") defaults.doubleForKey("myGroovyKey") defaults.objectForKey("myGroovyKey") defaults.URLForKey("myGroovyKey") defaults.dataForKey("myGroovyKey") defaults.stringForKey("myGroovyKey") defaults.stringArrayForKey("myGroovyKey") defaults.arrayForKey("myGroovyKey") defaults.dictionaryForKey("myGroovyKey") e.g. if (defaults.boolForKey("myGroovyKey")) == true { do something awesome }
If you try to read a key and it does not exist it will return nil.
0 notes
Text
nsarray vs nsmutablearray in ios10 and ios11(beta)
https://medium.com/@ngchiwang/nsarray-vs-nsmutablearray-in-ios10-and-ios11-beta-d2748ee58841
0 notes
Text
[COCOS2D] Facebook 연동하기 버전 업데이트
New Post has been published on http://canyoumeet.info/cocos2d-facebook-%ec%97%b0%eb%8f%99%ed%95%98%ea%b8%b0-%eb%b2%84%ec%a0%84-%ec%97%85%eb%8d%b0%ec%9d%b4%ed%8a%b8/
[COCOS2D] Facebook 연동하기 버전 업데이트
오랜만에 기술 자료를 또 올리게 되었네요.
별 다른 것은 아니고 예전에 올렸던 Facebook 연동하기를 보시고 오히려 많은 분들이 혼란스러워하셔서..
(사실 SDK가 업데이트가 된 탓과..제가 설명이 부족했었던 탓도..ㅎㅎㅎ)
그래서 제가 얼마전에 만든 Mom’s garden 의 1.0.1 버전 업데이트 겸해서
새롭게 Facebook SDK를 받아서 적용을 한 사례를 적고자 합니다.
지난 번에 썼던 글을 참고하시면서 보시면 이해가 빠르실 것이라 생각됩니다.
//
많이 바뀌진 않았을려나 걱정을 했는데 오히려 더 편하게 바뀌었더군요.ㅎㅎ
간단하게 설명이 끝이 날 것 같습니다.(정말??)
위의 URL에 있는 이전 자료에서 우선 SDK를 다운받아 봅시다.(
//
)
그리고 좀 달라진 점은 많은 분들이 헷갈려하시던 FBConnect폴더의 존재입니다.
예전에는 있었는데 이제는 src폴더에 기존 내용들이 다 담겨져있네요.
저 같은 경우는 제가 제작중인 어플의 class폴더에 FBConnect 폴더를 새로 생성하여
그 안에 Facebook SDK ->src 폴더 내부의 파일을 프로젝트 파일을 제외하고 다 복사하여
FBConnect폴더에 저장한뒤 프로젝트에 추가하였습니다.
따로 파일 경로 저장이니 뭐 그런거 필요없이 우선 파일 설정은 끝입니다.(쉽죠? ㅎㅎ)
Step 2의 페이스북에 어플 등록하기는 기존과 동일하니까 그대로 사용하시면 됩니다.
대신 추가해야할 사항이 하나 있다면
Step 2에서 페이스북에 어플을 등록하면 APP ID를 받게 됩니다.(이전 글의 이미지를 참고하세요.)
이 것을 여러분이 개발중인 프로젝트에 적용을 해야합니다.
우선 첫번째로 info.plist파일에 해당 값을 넣어야 합니다.
리소스 폴더의 info.plist파일을 여신다음.
key 값들을 한번 훑어 봅시다.
혹시 URL types라는게 있나요?.. 없으면 새로 하나 추가해줍시다.
아래��� 같이..
URL types 부터 하나씩 하위 item들을 추가하신다음에 URL schemes의 item 0 의 값에 여러분의 APP ID를 넣어야 합니다.
넣는 Format은 만약 여러분의 APPID가 12345라면 fb12345
이렇게 넣어주시면 됩니다. 그러고 저장~~
다음은 소스의 구현입니다.
구현하고자 하는 view controller에 (저 같은 경우는 RootViewController 에..ㅎㅎ)
우선 Header 파일 import
#import “FBConnect/FBConnect.h”
그리고 delegate 들을 implements해야겠지요.
<RootViewController.h>
@interface RootViewController : UIViewController<FBRequestDelegate,FBDialogDelegate,FBSessionDelegate>
….
Facebook * facebook; NSArray* _permissions;
@property(readonly) Facebook *facebook;
자 이제 제대로 한번 화면에 띄워 볼까요.
우선 Facebook 객체를 먼저 생성합시다.
간단합니다.
제 소스를 기준으로 한다면.
<RootViewController.m>
…
static NSString* kAppID = @”XXXXXX”; // FACEBOOK App ID입니다. plist와 달리 그냥 숫자만 넣어주시면되요.
-(void) initFacebook
// 객체 생성
facebook = [[Facebook alloc] initWithAppId:kAppID];
// permission 설정 : 여러분의 페이스북 담벼락에 해당 App이 가지는 권한 정도겠지요. 뭐 아래와 같이 그대로 써주시면 됩니다.
_permissions = [[NSArray arrayWithObjects: @”read_stream”, @”publish_stream”, @”offline_access”,nil] retain];
-(void)loginFacebook
// 페이스북 로그인.(우선 위에서 설정한 퍼미션을 인증받기 위해 아래와 같이 실행
[facebook authorize:_permissions delegate:self];
끝입니다.(농담아니고..ㅎㅎ)
ㅎㅎ 이정도만 하시면 여러분의 위의 함수를 호출하게 되면 바로 사파리 창이 열리면서 페이스북 로그인 하라고 합니다.
(예전에 세션처리나 뭐 기타 다른거 걱정안하셔도 될듯…)
로그인을 하시면 바로 여러분의 앱에서 여러분의 페이스북 담벼락에 무슨 짓을 해도 상관없겠는지 물어봅니다.
(계속 할려면 Yes 해야지요.ㅎㅎ)
자 여기서 하나 정리를 하자면
위와 같이 처리를 하면 앱 실행 중에 사파리가 하나 더 뜨는거지요.
그러면 사파리에서 일을 다 끝내면 어떻게 하느냐..
다들 잘아시겠지만
AppDelegate.m 파일에서
– (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
위의 함수를 호출하게 됩니다. (없으시면 만드시면 됩니다.ㅎㅎ)
적당히 위 함수에 아래의 내용을 추가해줍시다.
[[viewController facebook] handleOpenURL:url];
자 또 다른 의문이 생기는게 ‘난 사파리 안띄우고 그냥 앱 안에서 Dialog를 띄우련다.’ 라는 분이 계실겁니다.
(저 같은.ㅎㅎㅎ)
그럴 경우는 FBConnect쪽 소스를 살짝 수정해주시면 됩니다. 그러면 위의 AppDelegate.m 파일을 안건드려도 실행이 됩니다.
FBConnect 폴더를 여시면 Facebook.m 파일이 있습니다.
대략 275 라인 정도에
[self authorizeWithFBAppAuth:YES safariAuth:YES];
위의 소스에서 safariAuth:YES를 NO로 변경해주시면 됩니다.(이건 무슨 말인지 설명안해도 아시겠지요.?? ㅎ)
그럼 앱 내에서 다이얼로그 형태로 facebook 로그인이 될테고 위의 permission인증의 경우 한번만 하면되는 것이므로
그냥 로그인 후 창이 닫겨버릴 것입니다.
그럼 그 다음에 해야하는 것들은 facebook이 제공하는 여러가지 API를 호출하여 원하는 화면을 띄우는 것이겠지요.
그 중에 가장 많이 사용 될 publish를 위한 Dialog를 출력하는 부분만 먼저 살펴보도록 하겠습니다.(이전 글에서 마지막 부분을 실행하기 위한 것이지요.)
<RootViewController.m>
-(void)publishWallMessage NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: kAPPID, @”app_id”, @”http://itunes.apple.com/us/app/moms-garden-handmade-story/id442160730?mt=8&ls=1“, @”link”, @”
//
“,@”picture”, @”Mom’s Garden”, @”name”, @”- Handmade Story”, @”caption”, @”Imagine how happy they will be when they read the story that you made!”, @”description”, @”Mom’s garden is the start of children’s hopes and dreams.”, @”message”, nil]; [facebook dialog:@”feed” andParams:params andDelegate:self];
정말 많이 간단해졌습니다.ㅎㅎ
그냥 위와 같이 함수 내용을 만들고 해당함수를 호출만 해주시면됩니다.
MutableDictionary의 내용을 하나씩 살펴보면
첫번째는 APP ID 입니다. 호출 함수가 objectsAndKeys 니까
왼쪽에 있는 것이 실제 value고 오른쪽에 있는 것이 key가 됩니다.
일일이 설명하기는 그렇고 위의 key와 value를 아래의 스크린 샷과 매치시켜서 보시면 이해가 빠르실 겁니다.
위에 메세지 창에 원하는 글을 다 쓰신다음 publish를 누르시면 자동으로 여러분의 facebook의 담벼락에 원하는 글이 작성이 됩니다.
혹시 저렇게 글을 쓰신다음에 추가로 원하는 동작이 있으시다면
<RootViewController.m>
– (void)dialogDidComplete:(FBDialog *)dialog //Todo….
위의 함수를 하나 추가하여 원하는 동작을 실행하시면 됩니다.
이상입니다.
추가적으로 필요한 사항은 sdk의 sample예제를 보시면 더욱 이해가 빠르실 것이라 생각됩니다.
수고하세요~~
0 notes
Text
Native Love
One of the many benefits of writing native apps is that you can treat local storage like it’s 1983.
Aside from your own threads, you don't have concurrency, and we've all learned that it's better to keep your data access in just one thread anyway, therefore, no concurrency!
Your app is running inside a container, away from other apps, which further reinforces the no-concurrency aspect, and adds security, which means that you don't have to care much about the format, or encryption of your files.
This freedom means you can choose your own format, be that some Core Data SQLLite file, a .plist defaults file, JSON, or even some binary trap.
CoreData seems like the safe way of doing things, and you do get some niceties of doing SQL, and everything is stored in just one file (exceptions apart), and you can sort of debug that to the bone with sqlite3 commands.
Screw that! Lately, I've been serialising NSArray objects in a .plist format and I love it:
Less complexity. Your code is orders of magnitude simpler, you load, update and write the whole thing on disk with the powerful NSArray objects.
It's less efficient, but we're talking small files, not GB databases. You can tail -f a file and see it update FFS! Besides, you’re running on SSDs!
You can't search or sort as well as with CoreData, or can you? Arrays have both sorting and searching, and for most problems, it's pretty good!
I'm targeting this at small problems, with hundreds or few thousand objects within the array. This in turn simplifies your TableViews since you won't have async code to manage.
What about more complex objects? That's when you make Dictionaries and add them to your array! Again, I'm talking objects that have few entries.
Again, depending on your true needs, if you don’t have truly relational database needs, large schema changes, you really don’t have to limit yourself to SQLite or other large storage libraries, when you can just dump stuff onto plain old files.
0 notes