2010-10-15 28 views
19

Tôi đang lên kế hoạch cho ứng dụng iPhone đầu tiên của mình và tôi muốn nhận được một số yếu tố đầu vào về cách xây dựng ứng dụng này ngay từ đầu. Ứng dụng iPhone đang được xây dựng để được ghép nối với ứng dụng web công khai mà đã được xây dựng bằng PHP.Tôi nên làm cách nào để kiến ​​trúc cho ứng dụng iPhone của mình nói chuyện với trang web của mình?

Tôi muốn nền tảng web trở thành trung tâm (dữ liệu được đặt trong cơ sở dữ liệu mySQL) và có các khách hàng iPhone nói chuyện với nó và sử dụng các phương pháp REST'ful để thực hiện các chức năng của trang web (tìm nạp mới nhất nội dung, đăng nội dung, bỏ phiếu, quản lý tài khoản làm ví dụ).

Tôi muốn khách hàng lấy bản sao dữ liệu cục bộ trong cơ sở dữ liệu SQLite, nhưng làm mới để tải phiên bản mới nhất của nguồn cấp dữ liệu (tương tự ứng dụng Twitter).

Vài suy nghĩ tôi có ngay bây giờ:

  • Sử dụng một cái gì đó giống như ASIHTTPRequest để gửi dữ liệu/nhận được vào các file PHP trên máy chủ nghe cho các yêu cầu

  • JSON - Tôi sẽ khấm khá hơn để gửi GET/POSTS tới một PHP trả về các đối tượng JSON và làm việc với một số loại trình bao bọc nào đó để quản lý dữ liệu và truyền đạt các thay đổi tới cơ sở dữ liệu SQLite cục bộ?

  • Tôi có hoàn toàn tắt trong cách tôi nên xây dựng điều này để giao tiếp với web không? Có phải có cách nào tốt nhất cho việc này không?

Tôi thực sự đánh giá cao bất kỳ đầu vào nào về cách bạn sẽ kiến ​​trúc kiểu sắp xếp này.

Cảm ơn bạn,

EDIT: Sau khi đọc bài của tôi một lần nữa, tôi biết nó có vẻ giống như một client Twitter, nhưng nó là KHÔNG, mặc dù nó có nhiều tính năng/cấu trúc của một loại thiết lập Twitter tương tự. Cảm ơn!

+0

Có phải cơ sở dữ liệu SQLite giống nhau cho tất cả người dùng không? Hoặc là nó cụ thể cho mỗi người dùng? Cơ sở dữ liệu/dữ liệu sẽ lớn như thế nào đối với bản sao ban đầu và lần tải xuống sau? – baalexander

+0

cơ sở dữ liệu SQLite sẽ chỉ lưu trữ phiên bản nguồn cấp dữ liệu địa phương hóa, dữ liệu được lấy từ cơ sở dữ liệu mySQL trung tâm. Đối với việc tìm nạp nội tạng, tôi đoán tôi có thể kiểm soát mức độ lớn mà tôi muốn khi tôi có thể đặt số lượng các mục nguồn cấp dữ liệu trước đó có được, đó chỉ là văn bản. – barfoon

+0

Chỉ là một ghi chú lịch sử. Trong nhiều năm ** ASIHTTPRequest ** là giải pháp goto trong vũ trụ iOS, phổ biến nhất và tốt nhất trong tất cả các thư viện iOS! Thật không may nó không còn với chúng tôi những ngày này, nhưng nó là một cái gì đó đặc biệt. Ah, kỷ niệm! – Fattie

Trả lời

17

Như bạn đã nêu trong kế hoạch, XML và REST của bạn là một cách tuyệt vời để giao tiếp với một ứng dụng web. Tôi muốn gợi ý một vài chi tiết về cách thiết kế và xây dựng nó, hoặc những gì bạn nên ghi nhớ.

Trước hết, tôi tin rằng điều quan trọng là phải gắn bó với MVC. Tôi đã thấy mọi người tạo kết nối HTTP trong bộ điều khiển xem, bộ điều khiển là đại diện của NSXMLParser, bộ điều khiển chứa dữ liệu trong các biến thành viên. Tôi thậm chí đã nhìn thấy UITableCells thiết lập kết nối HTTP. Đừng làm thế!

Mô hình của bạn và mã thao tác cơ bản của nó phải được trích xuất nhiều từ giao diện người dùng nhất có thể. Vì bạn đã tạo mô hình trong ứng dụng web của mình, hãy thử tạo lại các thực thể trong dự án iPhone của bạn. Đừng ngại có một số phương thức đơn giản trong các lớp thực thể, nhưng không làm cho chúng sử dụng các tài nguyên bên ngoài, đặc biệt là các kết nối TCP. Ví dụ về các phương thức trong lớp thực thể, bạn có thể có các phương thức định dạng dữ liệu theo các cách cụ thể (ngày làm ví dụ hoặc trả về tên đầy đủ dưới dạng nối của họ và tên) hoặc thậm chí bạn có thể có một phương thức như - (void)update. để gọi lớp chịu trách nhiệm cập nhật mô hình.

Tạo một lớp khác để cập nhật mô hình - tìm nạp XML từ ứng dụng web. Thậm chí không cân nhắc việc sử dụng các kết nối đồng bộ, thậm chí không phải từ một chuỗi chuyên dụng. Kết nối không đồng bộ với đại biểu là con đường để đi. Đôi khi, nhiều yêu cầu cần được thực hiện để nhận tất cả dữ liệu bắt buộc.Bạn có thể muốn tạo một số loại máy trạng thái để giữ thông tin về giai đoạn tải xuống của bạn và tiến bộ từ giai đoạn này sang giai đoạn khác, bỏ qua đến cuối nếu xảy ra lỗi, thực thi lại từ giai đoạn không thành công sau một vài khoảnh khắc.

Tải xuống dữ liệu ở đâu đó tạm thời và trước tiên khi bạn có dữ liệu, hãy chuyển đổi và cập nhật giao diện người dùng. Điều này giúp đáp ứng trong khi khởi chạy ứng dụng - người dùng sẽ làm việc ngay lập tức với dữ liệu được lưu trữ cục bộ, trong khi cơ chế cập nhật đang tải xuống dữ liệu mới.

Nếu bạn cần tải xuống nhiều tệp, hãy thử tải xuống đồng thời, nếu phụ thuộc giữa các tệp cho phép điều đó. Điều này liên quan đến việc tạo ra một kết nối cho mỗi yêu cầu, có thể là ví dụ đại biểu cho mỗi người trong số họ. Tất nhiên bạn có thể chỉ có một cá thể ủy nhiệm cho tất cả các kết nối đó, nhưng nó phức tạp hơn một chút để theo dõi dữ liệu. Việc tải xuống đồng thời có thể làm giảm đáng kể độ trễ, giúp cơ chế này nhanh hơn nhiều cho người dùng.

Để tiết kiệm thời gian và băng thông, hãy xem xét sử dụng tiêu đề If-Modified-Since và/hoặc ETag của HTTP. Hãy nhớ thời gian hoặc thẻ khi bạn yêu cầu dữ liệu lần cuối cùng và lần sau gửi dữ liệu đó trong tiêu đề của HTTP. Ứng dụng web của bạn phải trả lại mã HTTP 304 nếu nội dung chưa bị thay đổi. Ứng dụng iPhone sẽ phản ứng trên mã này tương ứng trong connection:didReceiveResponse:.

Tạo một lớp chuyên dụng để phân tích cú pháp XML và cập nhật mô hình. Bạn có thể sử dụng NSXMLParser, nhưng nếu tệp của bạn không lớn, tôi khuyên bạn nên dùng TouchXML, thật vui khi làm việc với XML dưới dạng tài liệu (nó cũng hỗ trợ XPath), thay vì API dựa trên sự kiện. Bạn cũng có thể sử dụng trình phân tích cú pháp này khi các tệp được tải xuống để kiểm tra tính hợp lệ của chúng - tải xuống lại nếu phân tích cú pháp không thành công. Đó là khi lớp dành riêng cho phân tích có ích.

Nếu tập dữ liệu của bạn không lớn, nếu bạn không cần lưu dữ liệu tải xuống vĩnh viễn trên iPhone, bạn có thể không cần lưu trữ chúng trong cơ sở dữ liệu SQLite, bạn có thể lưu trữ chúng ở định dạng XML. . Điều đó ít nhất có thể là cách cho một ứng dụng twitter. Nó dễ dàng hơn theo cách đó, nhưng đối với các tập dữ liệu lớn hơn XML tiêu thụ rất nhiều bộ nhớ và sức mạnh xử lý - trong trường hợp đó, SQLite là tốt hơn.

Tôi khuyên bạn nên sử dụng Dữ liệu cốt lõi, nhưng bạn đề cập đến đây là ứng dụng iPhone đầu tiên của bạn, vì vậy tôi khuyên bạn không nên sử dụng nó. Chưa.

Đừng quên đa nhiệm - ứng dụng của bạn có thể chuyển sang chế độ ngủ khi đang tải xuống, bạn cần hủy kết nối và dọn dẹp cơ chế cập nhật của mình. Khi bạn thức dậy, bạn có thể muốn tiếp tục cập nhật.

Về phần xem của ứng dụng - sử dụng Trình tạo giao diện. Nó có thể gây đau đớn ngay từ đầu, nhưng nó sẽ giảm giá trong thời gian dài.

Xem bộ điều khiển là keo giữa mô hình và chế độ xem. Không lưu trữ dữ liệu trong đó. Hãy suy nghĩ hai lần về những gì để thực hiện ở đâu, và ai nên gọi nó.

Điều này không liên quan đến kiến ​​trúc của ứng dụng, nhưng tôi muốn nhắc nhở rằng Mục tiêu-C là ngôn ngữ rất biểu cảm. Mã nên đọc giống như một câu. Mở rộng các lớp với các giao thức. Ví dụ như ngày khác tôi cần dòng đầu tiên của một chuỗi. Chắc chắn, bạn có thể viết một lớp lót nơi bạn tìm thấy lần xuất hiện đầu tiên của một dòng mới và nhận chuỗi con từ đầu đến đó. Nhưng có vẻ không đúng. Tôi đã thêm - (NSString*)firstLine vào giao thức NSString của tôi. Mã trông đẹp hơn rất nhiều theo cách này, nó không cần bất kỳ bình luận nào.

Có rất nhiều điều cần xem xét trong cả kiến ​​trúc và thiết kế của bất kỳ dự án nào, cả hai đều nên đi đôi với nhau. Nếu một người gây rắc rối cho người khác, bạn cần phải thích nghi. Không có gì được viết bằng đá.

0

Tôi sẽ làm điều này giống như tôi đã làm với rất nhiều công cụ trang web AJAX. tức là:

  1. Có URL ở phía máy chủ của bạn gói thông tin được truyền sang định dạng XML. (Điều này có thể thông qua một kịch bản CGI/PHP hoặc bất cứ điều gì). Việc truyền XML của bạn trong nội dung thư - vì vậy thật dễ dàng để đọc và gỡ lỗi với trình duyệt web chuẩn.

  2. Sử dụng các phương pháp tiêu chuẩn của iPhone NSXMLParser để phân tích các trường dữ liệu riêng lẻ từ tài liệu XML và ghi nó trở lại cơ sở dữ liệu của bạn. Phương pháp này được trang bị cho cả hai lấy dữ liệu từ một URL phân tích nó trong một cuộc gọi - như:

NSURL *xmlURL = [NSURL URLWithString:@"http://www.example.com/livefeed.cgi"]; 
NSXMLParser *myParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL]; 
  1. Walk thông qua hệ thống phân cấp dữ liệu với các phương pháp NSXMLParser và cư cơ sở dữ liệu của bạn cho phù hợp.
+1

Hãy nhận biết rằng [NSXMLParser alloc] initWithContentsOfURL: xmlURL là cuộc gọi đồng bộ sẽ chặn cho đến khi dữ liệu được tìm nạp - có thể bạn không muốn làm điều này từ chuỗi chính của mình, vì ứng dụng của bạn sẽ xuất hiện hoàn toàn đóng băng nếu máy chủ phản hồi chậm. – JosephH

1

Đó là khá một câu hỏi rộng, và tôi nghĩ rằng bạn đang đi một cách đúng đắn dù sao, tuy nhiên tôi sẽ làm hết sức mình để đưa ra một số lời khuyên:

JSON, ASIHTTPRequest và POSTS cho PHP script âm thanh như một cách tuyệt vời để đi.

Nếu dữ liệu không thực sự nhạy cảm, tôi sẽ sử dụng http hầu hết thời gian và chỉ sử dụng https cho trang đăng nhập để đặt cookie hoặc trả lại "mã thông báo" mà bạn sử dụng trong các yêu cầu tiếp theo. (HTTPS có thể khá chậm so với kết nối 3G vì phí trên số lượng gói để thiết lập kết nối SSL cao hơn kết nối TCP đơn giản.)

Bạn nên đảm bảo bạn chuyển đúng bất kỳ dữ liệu nào từ đầu vào đến các tập lệnh PHP vào cơ sở dữ liệu, để tránh bất kỳ tấn công SQL injection nào - tức là. sử dụng tham số hóa SQL, không tạo truy vấn sql bằng cách thực hiện "SELECT * from users where username="+$_GET['username']"

3

Tôi hiện đang làm việc trên một ứng dụng nghe có vẻ tương tự như của bạn. Tôi cũng đề nghị ASIHTTPRequest, và có lẽ giống như TouchJSON để phân tích cú pháp JSON, hoặc mở rộng/tạo một đại biểu của NSXMLParser nếu bạn muốn phân tích cú pháp XML. Theo đề xuất của JosephH, tùy thuộc vào cách ứng dụng của bạn hoạt động, bạn có thể muốn xem xét các phương pháp xác thực thay thế: Tôi sẽ xem xét một thứ dựa trên mã thông báo như OAuth, có ready-made libraries để mọi người tìm hiểu.

SQLite hoàn toàn khả thi đối với bộ đệm ẩn nguồn cấp dữ liệu, mặc dù tôi thích NSCoding để bạn có thể cố định các cấu trúc dữ liệu tùy chỉnh của mình. Là một gợi ý chung, hãy đảm bảo dành nhiều thời gian suy nghĩ về mọi trường hợp sử dụng và trường hợp góc cho các kết nối: thật dễ dàng để giả sử người dùng sẽ chỉ liên hệ với máy chủ theo những cách nhất định và vào những thời điểm nhất định, sau đó sau bạn ném vào đa nhiệm/cuộc gọi đến/màn hình khóa/cảnh báo bộ nhớ, mọi thứ có thể nhận được lông mà không cần bất kỳ kế hoạch nào.

Tất cả trong tất cả, bạn dường như đi đúng hướng, chỉ cần đảm bảo bạn có kế hoạch ra tất cả mọi thứ trước :)

3

Apple có một đoạn mã mẫu mới có chiều sâu hoàn toàn mới - MVCNetworking trình bày chi tiết cách sử dụng các lớp con của NSHTTPRequests và NSOperationQueues.

2

Như những người khác đã đề cập, tôi nghĩ bạn đang đặt câu hỏi phù hợp và đang đi đúng hướng. Tất cả các câu trả lời ở trên là lời khuyên có giá trị. Đây là lời khuyên của tôi, và tôi hy vọng bạn sẽ thấy nó hữu ích.

Bất kể bạn chọn phương pháp/thư viện nào để nói chuyện với dịch vụ web của mình, tôi nghĩ việc tách riêng sạch sẽ theo cách bạn thiết kế mô hình dữ liệu trên điện thoại VS. mô hình dữ liệu trong ứng dụng web của bạn. Bạn có 3 sự phân biệt quan trọng cần ghi nhớ cho thiết kế của bạn:

  1. mô hình dữ liệu trên ứng dụng web (thể hiện qua cơ sở dữ liệu mySQL hiện tại của bạn)

    Do đây là đã có, không có nhiều điều để nói về nó, ngoại trừ việc nó sẽ ảnh hưởng rất nhiều đến thiết kế của bạn cho 2 phần sau. Tôi đề xuất làm cho mô hình này là 'tham chiếu chính' cho cách dữ liệu của bạn được thể hiện trên các nền tảng.

  2. mô hình dữ liệu trên ứng dụng iPhone (thể hiện qua các thông tin mà bạn cần để hiển thị trong ứng dụng iPhone)

    Đây là nơi vui vẻ bắt đầu. Trước tiên, bạn cần hiểu rõ về dữ liệu nào bạn cần hiển thị trong ứng dụng điện thoại. Vì vậy, có một thiết kế tốt, cấp cao của ứng dụng của bạn trước tiên (sử dụng bút và giấy, vẽ mô hình của mỗi chế độ xem và tương tác giữa chúng, mô hình điều hướng giữa các bộ điều khiển xem của bạn, v.v.). Nó thực sự giúp hiểu được sự tương tác giữa các bộ điều khiển xem của bạn và các bit và mẩu dữ liệu khác nhau mà bạn muốn hiển thị trong ứng dụng. Điều này sẽ giúp bạn tạo ra các yêu cầu cho mô hình dữ liệu trên điện thoại. Dựa trên những yêu cầu này, hãy ánh xạ mô hình dữ liệu (web) hiện có thành một mô hình mới, phù hợp với ứng dụng iPhone của bạn. Mô hình mới này có thể có hoặc không bao gồm tất cả các bảng và trường được tìm thấy trong ứng dụng web của bạn. Tuy nhiên, đại diện chung của các mô hình 2 nên rất tương tự (ví dụ như các mối quan hệ, các kiểu dữ liệu, vv) mô hình

  3. dữ liệu sử dụng để giao tiếp giữa 2 ở trên (đây là 'trao đổi dữ liệu giao thức' của bạn)

    Khi bạn có 2 biểu diễn dữ liệu của mình ở trên, bạn cần 'dịch' từ một sang khác, cả hai cách. Thiết kế giao thức trao đổi dữ liệu của bạn đơn giản và gọn nhẹ nhất có thể. Bạn không muốn lãng phí byte vào thông tin vô ích, vì việc truyền tải qua mạng rất tốn kém. (Là một lưu ý phụ, bạn có thể nghĩ đến việc nén dữ liệu được truyền sau này, nhưng điều quan trọng là phải có một thiết kế tốt ngay từ đầu). Tốt nhất là bắt đầu với giao thức trong đó siêu dữ liệu giống với siêu dữ liệu trong mô hình ứng dụng web của bạn (ví dụ: cùng mối quan hệ, tên bảng, thuộc tính, v.v.). Nhưng hãy nhớ, bạn sẽ chỉ phải tuần tự hóa/de-serialize các thực thể và mối quan hệ mà bạn đã liệt kê ở điểm 2) ở trên. Vì vậy, thiết kế cho phù hợp. Giao thức trao đổi của bạn cũng có thể bao gồm mã thông báo phiên, thông tin xác thực, số phiên bản hoặc siêu dữ liệu khác, nếu bạn cần.

    Hãy nhớ rằng: giao thức trao đổi dữ liệu của bạn là điều sẽ loại bỏ ứng dụng web và mô hình ứng dụng iPhone của bạn. Tôi thấy rằng tốt nhất nên bỏ cặp chúng vì chúng có thể phát triển theo thời gian. Ví dụ, mô hình dữ liệu trên iPhone có thể phát triển rất nhiều, đặc biệt là khi bạn cần phải mô hình lại một số mối quan hệ hoặc thêm/xóa các thuộc tính khỏi các thực thể của bạn để cải thiện khả năng phản hồi của ứng dụng hoặc trải nghiệm người dùng, điều hướng, hay bất cứ cái gì.

    Vì đây là một mối quan tâm toàn bộ, bạn cần phải thiết kế cơ chế tuần tự hóa/de-serialization chung trên đầu (JSON/XML/parser bạn chọn) đủ linh hoạt để duy trì sự khác biệt tiềm năng giữa 2 mô hình dữ liệu của bạn. Những khác biệt này có thể là: tên thực thể/thuộc tính/mối quan hệ, tên mã định danh chính, loại dữ liệu, thuộc tính cần bỏ qua và danh sách tiếp tục. Tôi chắc chắn sẽ triển khai một lớp tiện ích serializer/de-serializer trong ứng dụng iPhone, được hỗ trợ bởi một tệp cấu hình .plist chứa tất cả các thực thể được hỗ trợ, các mối quan tâm, các bí danh mà bạn có thể có. Tất nhiên, mỗi đối tượng mô hình nên 'biết' làm thế nào để tuần tự hóa, de-serialize chính nó và các mối quan hệ của nó (tức là chiều sâu đồ thị đối tượng yêu cầu).

    Một lưu ý cuối cùng, vì bạn sẽ kết thúc với 2 biểu diễn dữ liệu của mình, bạn sẽ cần một cách để độc đáo xác định đối tượng ở cả hai bên. Ví dụ: giả sử thêm thuộc tính uuid vào tất cả dữ liệu cần trao đổi hoặc sử dụng bất kỳ phương pháp nào khác phù hợp với nhu cầu của bạn.

Tôi đang xây dựng một ứng dụng có yêu cầu tương tự với bạn và đây là những cách tiếp cận mà tôi thấy là tốt nhất cho đến nay. Ngoài ra, bạn có thể thấy video này hữu ích (nó đã truyền cảm hứng cho tôi rất nhiều về cách triển khai một số vấn đề tôi đã đề cập ở trên và đặc biệt thú vị nếu bạn đang sử dụng CoreData):

http://itunes.apple.com/ca/podcast/linkedin-important-life-lessons/id384233225?i=85092597 (xem bài giảng có tựa đề "LinkedIn : Bài học về cuộc sống quan trọng trên CoreData & GameKit (ngày 12 tháng 3 năm 2010) ")

Chúc may mắn!

Các vấn đề liên quan